1717
1818use crate :: utils:: array_with_timezone;
1919use arrow:: array:: AsArray ;
20+ use arrow:: compute:: cast;
2021use arrow:: datatypes:: { DataType , Field , TimeUnit :: Microsecond } ;
2122use datafusion:: common:: { internal_datafusion_err, DataFusionError } ;
2223use datafusion:: config:: ConfigOptions ;
@@ -27,7 +28,6 @@ use num::integer::div_floor;
2728use std:: { any:: Any , fmt:: Debug , sync:: Arc } ;
2829
2930const MICROS_PER_SECOND : i64 = 1_000_000 ;
30- const SECONDS_PER_DAY : i64 = 86400 ;
3131
3232#[ derive( Debug , PartialEq , Eq , Hash ) ]
3333pub struct SparkUnixTimestamp {
@@ -72,45 +72,50 @@ impl ScalarUDFImpl for SparkUnixTimestamp {
7272 & self ,
7373 args : ScalarFunctionArgs ,
7474 ) -> datafusion:: common:: Result < ColumnarValue > {
75- let args: [ ColumnarValue ; 1 ] = args. args . try_into ( ) . map_err ( |_| {
76- internal_datafusion_err ! ( "unix_timestamp expects exactly one argument" )
77- } ) ?;
75+ let args: [ ColumnarValue ; 1 ] = args
76+ . args
77+ . try_into ( )
78+ . map_err ( |_| internal_datafusion_err ! ( "unix_timestamp expects exactly one argument" ) ) ?;
7879
7980 match args {
80- [ ColumnarValue :: Array ( array) ] => {
81- match array. data_type ( ) {
82- DataType :: Timestamp ( _, _) => {
83- let array = array_with_timezone (
84- array,
85- self . timezone . clone ( ) ,
86- Some ( & DataType :: Timestamp (
87- Microsecond ,
88- Some ( "UTC" . into ( ) ) ,
89- ) ) ,
90- ) ?;
91-
92- let timestamp_array =
93- array. as_primitive :: < arrow:: datatypes:: TimestampMicrosecondType > ( ) ;
94- let result: arrow:: array:: Int64Array = timestamp_array
95- . iter ( )
96- . map ( |v| v. map ( |micros| div_floor ( micros, MICROS_PER_SECOND ) ) )
97- . collect ( ) ;
98- Ok ( ColumnarValue :: Array ( Arc :: new ( result) ) )
99- }
100- DataType :: Date32 => {
101- let date_array = array. as_primitive :: < arrow:: datatypes:: Date32Type > ( ) ;
102- let result: arrow:: array:: Int64Array = date_array
103- . iter ( )
104- . map ( |v| v. map ( |days| ( days as i64 ) * SECONDS_PER_DAY ) )
105- . collect ( ) ;
106- Ok ( ColumnarValue :: Array ( Arc :: new ( result) ) )
107- }
108- _ => Err ( DataFusionError :: Execution ( format ! (
109- "unix_timestamp does not support input type: {:?}" ,
110- array. data_type( )
111- ) ) ) ,
81+ [ ColumnarValue :: Array ( array) ] => match array. data_type ( ) {
82+ DataType :: Timestamp ( _, _) => {
83+ let array = array_with_timezone (
84+ array,
85+ self . timezone . clone ( ) ,
86+ Some ( & DataType :: Timestamp ( Microsecond , Some ( "UTC" . into ( ) ) ) ) ,
87+ ) ?;
88+
89+ let timestamp_array =
90+ array. as_primitive :: < arrow:: datatypes:: TimestampMicrosecondType > ( ) ;
91+ let result: arrow:: array:: Int64Array = timestamp_array
92+ . iter ( )
93+ . map ( |v| v. map ( |micros| div_floor ( micros, MICROS_PER_SECOND ) ) )
94+ . collect ( ) ;
95+ Ok ( ColumnarValue :: Array ( Arc :: new ( result) ) )
11296 }
113- }
97+ DataType :: Date32 => {
98+ let timestamp_array = cast ( & array, & DataType :: Timestamp ( Microsecond , None ) ) ?;
99+
100+ let array = array_with_timezone (
101+ timestamp_array,
102+ self . timezone . clone ( ) ,
103+ Some ( & DataType :: Timestamp ( Microsecond , Some ( "UTC" . into ( ) ) ) ) ,
104+ ) ?;
105+
106+ let timestamp_array =
107+ array. as_primitive :: < arrow:: datatypes:: TimestampMicrosecondType > ( ) ;
108+ let result: arrow:: array:: Int64Array = timestamp_array
109+ . iter ( )
110+ . map ( |v| v. map ( |micros| div_floor ( micros, MICROS_PER_SECOND ) ) )
111+ . collect ( ) ;
112+ Ok ( ColumnarValue :: Array ( Arc :: new ( result) ) )
113+ }
114+ _ => Err ( DataFusionError :: Execution ( format ! (
115+ "unix_timestamp does not support input type: {:?}" ,
116+ array. data_type( )
117+ ) ) ) ,
118+ } ,
114119 _ => Err ( DataFusionError :: Execution (
115120 "unix_timestamp(scalar) should be fold in Spark JVM side." . to_string ( ) ,
116121 ) ) ,
0 commit comments