@@ -22,22 +22,16 @@ use std::sync::Arc;
2222use arrow:: array:: timezone:: Tz ;
2323use arrow:: array:: { Array , ArrayRef , PrimitiveBuilder } ;
2424use arrow:: datatypes:: DataType :: Timestamp ;
25+ use arrow:: datatypes:: TimeUnit :: { Microsecond , Millisecond , Nanosecond , Second } ;
2526use arrow:: datatypes:: {
2627 ArrowTimestampType , DataType , TimestampMicrosecondType , TimestampMillisecondType ,
2728 TimestampNanosecondType , TimestampSecondType ,
2829} ;
29- use arrow:: datatypes:: {
30- TimeUnit ,
31- TimeUnit :: { Microsecond , Millisecond , Nanosecond , Second } ,
32- } ;
3330
3431use chrono:: { DateTime , MappedLocalTime , Offset , TimeDelta , TimeZone , Utc } ;
3532use datafusion_common:: cast:: as_primitive_array;
36- use datafusion_common:: { exec_err, DataFusionError , Result , ScalarValue } ;
37- use datafusion_expr:: TypeSignature :: Exact ;
38- use datafusion_expr:: {
39- ColumnarValue , ScalarUDFImpl , Signature , Volatility , TIMEZONE_WILDCARD ,
40- } ;
33+ use datafusion_common:: { exec_err, plan_err, DataFusionError , Result , ScalarValue } ;
34+ use datafusion_expr:: { ColumnarValue , ScalarUDFImpl , Signature , Volatility } ;
4135
4236/// A UDF function that converts a timezone-aware timestamp to local time (with no offset or
4337/// timezone information). In other words, this function strips off the timezone from the timestamp,
@@ -55,20 +49,8 @@ impl Default for ToLocalTimeFunc {
5549
5650impl ToLocalTimeFunc {
5751 pub fn new ( ) -> Self {
58- let base_sig = |array_type : TimeUnit | {
59- [
60- Exact ( vec ! [ Timestamp ( array_type, None ) ] ) ,
61- Exact ( vec ! [ Timestamp ( array_type, Some ( TIMEZONE_WILDCARD . into( ) ) ) ] ) ,
62- ]
63- } ;
64-
65- let full_sig = [ Nanosecond , Microsecond , Millisecond , Second ]
66- . into_iter ( )
67- . flat_map ( base_sig)
68- . collect :: < Vec < _ > > ( ) ;
69-
7052 Self {
71- signature : Signature :: one_of ( full_sig , Volatility :: Immutable ) ,
53+ signature : Signature :: user_defined ( Volatility :: Immutable ) ,
7254 }
7355 }
7456
@@ -328,13 +310,10 @@ impl ScalarUDFImpl for ToLocalTimeFunc {
328310 }
329311
330312 match & arg_types[ 0 ] {
331- Timestamp ( Nanosecond , _) => Ok ( Timestamp ( Nanosecond , None ) ) ,
332- Timestamp ( Microsecond , _) => Ok ( Timestamp ( Microsecond , None ) ) ,
333- Timestamp ( Millisecond , _) => Ok ( Timestamp ( Millisecond , None ) ) ,
334- Timestamp ( Second , _) => Ok ( Timestamp ( Second , None ) ) ,
313+ Timestamp ( timeunit, _) => Ok ( Timestamp ( * timeunit, None ) ) ,
335314 _ => exec_err ! (
336315 "The to_local_time function can only accept timestamp as the arg, got {:?}" , arg_types[ 0 ]
337- ) ,
316+ )
338317 }
339318 }
340319
@@ -348,6 +327,30 @@ impl ScalarUDFImpl for ToLocalTimeFunc {
348327
349328 self . to_local_time ( args)
350329 }
330+
331+ fn coerce_types ( & self , arg_types : & [ DataType ] ) -> Result < Vec < DataType > > {
332+ if arg_types. len ( ) != 1 {
333+ return plan_err ! (
334+ "to_local_time function requires 1 argument, got {:?}" ,
335+ arg_types. len( )
336+ ) ;
337+ }
338+
339+ let first_arg = arg_types[ 0 ] . clone ( ) ;
340+ match & first_arg {
341+ Timestamp ( Nanosecond , timezone) => {
342+ Ok ( vec ! [ Timestamp ( Nanosecond , timezone. clone( ) ) ] )
343+ }
344+ Timestamp ( Microsecond , timezone) => {
345+ Ok ( vec ! [ Timestamp ( Microsecond , timezone. clone( ) ) ] )
346+ }
347+ Timestamp ( Millisecond , timezone) => {
348+ Ok ( vec ! [ Timestamp ( Millisecond , timezone. clone( ) ) ] )
349+ }
350+ Timestamp ( Second , timezone) => Ok ( vec ! [ Timestamp ( Second , timezone. clone( ) ) ] ) ,
351+ _ => plan_err ! ( "The to_local_time function can only accept Timestamp as the arg got {first_arg}" ) ,
352+ }
353+ }
351354}
352355
353356#[ cfg( test) ]
0 commit comments