Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 9cd676e

Browse files
committed
fix: calculate total seconds from interval fields for extract(epoch)
1 parent 472a729 commit 9cd676e

2 files changed

Lines changed: 41 additions & 4 deletions

File tree

datafusion/functions/src/datetime/date_part.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,16 @@ use arrow::datatypes::DataType::{
2626
Date32, Date64, Duration, Interval, Time32, Time64, Timestamp,
2727
};
2828
use arrow::datatypes::TimeUnit::{Microsecond, Millisecond, Nanosecond, Second};
29-
use arrow::datatypes::{DataType, Field, FieldRef, TimeUnit};
29+
use arrow::datatypes::{
30+
DataType, Field, FieldRef, IntervalUnit as ArrowIntervalUnit, TimeUnit,
31+
};
3032
use datafusion_common::types::{NativeType, logical_date};
3133

3234
use datafusion_common::{
3335
Result, ScalarValue,
3436
cast::{
35-
as_date32_array, as_date64_array, as_int32_array, as_time32_millisecond_array,
37+
as_date32_array, as_date64_array, as_int32_array, as_interval_dt_array,
38+
as_interval_mdn_array, as_interval_ym_array, as_time32_millisecond_array,
3639
as_time32_second_array, as_time64_microsecond_array, as_time64_nanosecond_array,
3740
as_timestamp_microsecond_array, as_timestamp_millisecond_array,
3841
as_timestamp_nanosecond_array, as_timestamp_second_array,
@@ -56,7 +59,7 @@ use datafusion_macros::user_doc;
5659
argument(
5760
name = "part",
5861
description = r#"Part of the date to return. The following date parts are supported:
59-
62+
6063
- year
6164
- quarter (emits value in inclusive range [1, 4] based on which quartile of the year the date is in)
6265
- month
@@ -349,6 +352,7 @@ fn seconds(array: &dyn Array, unit: TimeUnit) -> Result<ArrayRef> {
349352

350353
fn epoch(array: &dyn Array) -> Result<ArrayRef> {
351354
const SECONDS_IN_A_DAY: f64 = 86400_f64;
355+
const DAYS_PER_MONTH: f64 = 30_f64;
352356

353357
let f: Float64Array = match array.data_type() {
354358
Timestamp(Second, _) => as_timestamp_second_array(array)?.unary(|x| x as f64),
@@ -373,7 +377,19 @@ fn epoch(array: &dyn Array) -> Result<ArrayRef> {
373377
Time64(Nanosecond) => {
374378
as_time64_nanosecond_array(array)?.unary(|x| x as f64 / 1_000_000_000_f64)
375379
}
376-
Interval(_) | Duration(_) => return seconds(array, Second),
380+
Interval(ArrowIntervalUnit::YearMonth) => as_interval_ym_array(array)?
381+
.unary(|x| x as f64 * DAYS_PER_MONTH * SECONDS_IN_A_DAY),
382+
Interval(ArrowIntervalUnit::DayTime) => as_interval_dt_array(array)?.unary(|x| {
383+
x.days as f64 * SECONDS_IN_A_DAY + x.milliseconds as f64 / 1_000_f64
384+
}),
385+
Interval(ArrowIntervalUnit::MonthDayNano) => {
386+
as_interval_mdn_array(array)?.unary(|x| {
387+
x.months as f64 * DAYS_PER_MONTH * SECONDS_IN_A_DAY
388+
+ x.days as f64 * SECONDS_IN_A_DAY
389+
+ x.nanoseconds as f64 / 1_000_000_000_f64
390+
})
391+
}
392+
Duration(_) => return seconds(array, Second),
377393
d => return exec_err!("Cannot convert {d:?} to epoch"),
378394
};
379395
Ok(Arc::new(f))

datafusion/sqllogictest/test_files/datetime/date_part.slt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -936,6 +936,27 @@ SELECT extract(second from arrow_cast(NULL, 'Interval(MonthDayNano)'))
936936
----
937937
NULL
938938

939+
# extract epoch from intervals
940+
query R
941+
SELECT extract(epoch from interval '15 minutes')
942+
----
943+
900
944+
945+
query R
946+
SELECT extract(epoch from interval '1 hour')
947+
----
948+
3600
949+
950+
query R
951+
SELECT extract(epoch from interval '1 day')
952+
----
953+
86400
954+
955+
query R
956+
SELECT extract(epoch from interval '1 month')
957+
----
958+
2592000
959+
939960
statement ok
940961
create table t (id int, i interval) as values
941962
(0, interval '5 months 1 day 10 nanoseconds'),

0 commit comments

Comments
 (0)