@@ -39,7 +39,9 @@ use crate::datetime::common::parse_tz;
3939use datafusion_common:: {
4040 Result , ScalarValue ,
4141 cast:: {
42- as_date32_array, as_date64_array, as_int32_array, as_interval_dt_array,
42+ as_date32_array, as_date64_array, as_duration_microsecond_array,
43+ as_duration_millisecond_array, as_duration_nanosecond_array,
44+ as_duration_second_array, as_int32_array, as_interval_dt_array,
4345 as_interval_mdn_array, as_interval_ym_array, as_primitive_array,
4446 as_time32_millisecond_array, as_time32_second_array, as_time64_microsecond_array,
4547 as_time64_nanosecond_array, as_timestamp_microsecond_array,
@@ -504,48 +506,6 @@ fn seconds_as_i32(array: &dyn Array, unit: TimeUnit) -> Result<ArrayRef> {
504506 }
505507}
506508
507- /// Invoke [`date_part`] on an `array` (e.g. Timestamp) and convert the
508- /// result to a total number of seconds, milliseconds, microseconds or
509- /// nanoseconds
510- ///
511- /// Given epoch return f64, this is a duplicated function to optimize for f64 type
512- fn seconds ( array : & dyn Array , unit : TimeUnit ) -> Result < ArrayRef > {
513- let sf = match unit {
514- Second => 1_f64 ,
515- Millisecond => 1_000_f64 ,
516- Microsecond => 1_000_000_f64 ,
517- Nanosecond => 1_000_000_000_f64 ,
518- } ;
519- let secs = date_part ( array, DatePart :: Second ) ?;
520- // This assumes array is primitive and not a dictionary
521- let secs = as_int32_array ( secs. as_ref ( ) ) ?;
522- let subsecs = date_part ( array, DatePart :: Nanosecond ) ?;
523- let subsecs = as_int32_array ( subsecs. as_ref ( ) ) ?;
524-
525- // Special case where there are no nulls.
526- if subsecs. null_count ( ) == 0 {
527- let r: Float64Array = binary ( secs, subsecs, |secs, subsecs| {
528- ( secs as f64 + ( ( subsecs % 1_000_000_000 ) as f64 / 1_000_000_000_f64 ) ) * sf
529- } ) ?;
530- Ok ( Arc :: new ( r) )
531- } else {
532- // Nulls in secs are preserved, nulls in subsecs are treated as zero to account for the case
533- // where the number of nanoseconds overflows.
534- let r: Float64Array = secs
535- . iter ( )
536- . zip ( subsecs)
537- . map ( |( secs, subsecs) | {
538- secs. map ( |secs| {
539- let subsecs = subsecs. unwrap_or ( 0 ) ;
540- ( secs as f64 + ( ( subsecs % 1_000_000_000 ) as f64 / 1_000_000_000_f64 ) )
541- * sf
542- } )
543- } )
544- . collect ( ) ;
545- Ok ( Arc :: new ( r) )
546- }
547- }
548-
549509fn epoch ( array : & dyn Array ) -> Result < ArrayRef > {
550510 const SECONDS_IN_A_DAY : f64 = 86400_f64 ;
551511 // Note: Month-to-second conversion uses 30 days as an approximation.
@@ -589,7 +549,16 @@ fn epoch(array: &dyn Array) -> Result<ArrayRef> {
589549 + x. nanoseconds as f64 / 1_000_000_000_f64
590550 } )
591551 }
592- Duration ( _) => return seconds ( array, Second ) ,
552+ Duration ( Second ) => as_duration_second_array ( array) ?. unary ( |x| x as f64 ) ,
553+ Duration ( Millisecond ) => {
554+ as_duration_millisecond_array ( array) ?. unary ( |x| x as f64 / 1_000_f64 )
555+ }
556+ Duration ( Microsecond ) => {
557+ as_duration_microsecond_array ( array) ?. unary ( |x| x as f64 / 1_000_000_f64 )
558+ }
559+ Duration ( Nanosecond ) => {
560+ as_duration_nanosecond_array ( array) ?. unary ( |x| x as f64 / 1_000_000_000_f64 )
561+ }
593562 d => return exec_err ! ( "Cannot convert {d:?} to epoch" ) ,
594563 } ;
595564 Ok ( Arc :: new ( f) )
0 commit comments