-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for extract(x from time)
/ date_part
from time types
#8693
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,14 +20,17 @@ use std::sync::Arc; | |
|
||
use arrow::array::{Array, ArrayRef, Float64Array}; | ||
use arrow::compute::{binary, cast, date_part, DatePart}; | ||
use arrow::datatypes::DataType::{Date32, Date64, Float64, Timestamp, Utf8}; | ||
use arrow::datatypes::DataType::{ | ||
Date32, Date64, Float64, Time32, Time64, Timestamp, Utf8, | ||
}; | ||
use arrow::datatypes::TimeUnit::{Microsecond, Millisecond, Nanosecond, Second}; | ||
use arrow::datatypes::{DataType, TimeUnit}; | ||
|
||
use datafusion_common::cast::{ | ||
as_date32_array, as_date64_array, as_int32_array, as_timestamp_microsecond_array, | ||
as_timestamp_millisecond_array, as_timestamp_nanosecond_array, | ||
as_timestamp_second_array, | ||
as_date32_array, as_date64_array, as_int32_array, as_time32_millisecond_array, | ||
as_time32_second_array, as_time64_microsecond_array, as_time64_nanosecond_array, | ||
as_timestamp_microsecond_array, as_timestamp_millisecond_array, | ||
as_timestamp_nanosecond_array, as_timestamp_second_array, | ||
}; | ||
use datafusion_common::{exec_err, Result, ScalarValue}; | ||
use datafusion_expr::TypeSignature::Exact; | ||
|
@@ -68,6 +71,10 @@ impl DatePartFunc { | |
]), | ||
Exact(vec![Utf8, Date64]), | ||
Exact(vec![Utf8, Date32]), | ||
Exact(vec![Utf8, Time32(Second)]), | ||
Exact(vec![Utf8, Time32(Millisecond)]), | ||
Exact(vec![Utf8, Time64(Microsecond)]), | ||
Exact(vec![Utf8, Time64(Nanosecond)]), | ||
], | ||
Volatility::Immutable, | ||
), | ||
|
@@ -149,12 +156,9 @@ fn date_part_f64(array: &dyn Array, part: DatePart) -> Result<ArrayRef> { | |
Ok(cast(date_part(array, part)?.as_ref(), &Float64)?) | ||
} | ||
|
||
/// invoke [`date_part`] on an `array` (e.g. Timestamp) and convert the | ||
/// Invoke [`date_part`] on an `array` (e.g. Timestamp) and convert the | ||
/// result to a total number of seconds, milliseconds, microseconds or | ||
/// nanoseconds | ||
/// | ||
/// # Panics | ||
/// If `array` is not a temporal type such as Timestamp or Date32 | ||
fn seconds(array: &dyn Array, unit: TimeUnit) -> Result<ArrayRef> { | ||
let sf = match unit { | ||
Second => 1_f64, | ||
|
@@ -163,6 +167,7 @@ fn seconds(array: &dyn Array, unit: TimeUnit) -> Result<ArrayRef> { | |
Nanosecond => 1_000_000_000_f64, | ||
}; | ||
let secs = date_part(array, DatePart::Second)?; | ||
// This assumes array is primitive and not a dictionary | ||
let secs = as_int32_array(secs.as_ref())?; | ||
let subsecs = date_part(array, DatePart::Nanosecond)?; | ||
let subsecs = as_int32_array(subsecs.as_ref())?; | ||
|
@@ -189,6 +194,16 @@ fn epoch(array: &dyn Array) -> Result<ArrayRef> { | |
} | ||
Date32 => as_date32_array(array)?.unary(|x| x as f64 * SECONDS_IN_A_DAY), | ||
Date64 => as_date64_array(array)?.unary(|x| x as f64 / 1_000_f64), | ||
Time32(Second) => as_time32_second_array(array)?.unary(|x| x as f64), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👨🍳 👌 -- very nice |
||
Time32(Millisecond) => { | ||
as_time32_millisecond_array(array)?.unary(|x| x as f64 / 1_000_f64) | ||
} | ||
Time64(Microsecond) => { | ||
as_time64_microsecond_array(array)?.unary(|x| x as f64 / 1_000_000_f64) | ||
} | ||
Time64(Nanosecond) => { | ||
as_time64_nanosecond_array(array)?.unary(|x| x as f64 / 1_000_000_000_f64) | ||
} | ||
d => return exec_err!("Can not convert {d:?} to epoch"), | ||
}; | ||
Ok(Arc::new(f)) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -939,6 +939,153 @@ SELECT date_part('nanosecond', '2020-09-08T12:00:12.12345678+00:00') | |
---- | ||
12123456780 | ||
|
||
# test_date_part_time | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it also worth testing the like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point, added 👍 |
||
|
||
## time32 seconds | ||
query R | ||
SELECT date_part('hour', arrow_cast('23:32:50'::time, 'Time32(Second)')) | ||
---- | ||
23 | ||
|
||
query R | ||
SELECT date_part('minute', arrow_cast('23:32:50'::time, 'Time32(Second)')) | ||
---- | ||
32 | ||
|
||
query R | ||
SELECT date_part('second', arrow_cast('23:32:50'::time, 'Time32(Second)')) | ||
---- | ||
50 | ||
|
||
query R | ||
SELECT date_part('millisecond', arrow_cast('23:32:50'::time, 'Time32(Second)')) | ||
---- | ||
50000 | ||
|
||
query R | ||
SELECT date_part('microsecond', arrow_cast('23:32:50'::time, 'Time32(Second)')) | ||
---- | ||
50000000 | ||
|
||
query R | ||
SELECT date_part('nanosecond', arrow_cast('23:32:50'::time, 'Time32(Second)')) | ||
---- | ||
50000000000 | ||
|
||
query R | ||
SELECT date_part('epoch', arrow_cast('23:32:50'::time, 'Time32(Second)')) | ||
---- | ||
84770 | ||
|
||
## time32 milliseconds | ||
query R | ||
SELECT date_part('hour', arrow_cast('23:32:50.123'::time, 'Time32(Millisecond)')) | ||
---- | ||
23 | ||
|
||
query R | ||
SELECT date_part('minute', arrow_cast('23:32:50.123'::time, 'Time32(Millisecond)')) | ||
---- | ||
32 | ||
|
||
query R | ||
SELECT date_part('second', arrow_cast('23:32:50.123'::time, 'Time32(Millisecond)')) | ||
---- | ||
50.123 | ||
|
||
query R | ||
SELECT date_part('millisecond', arrow_cast('23:32:50.123'::time, 'Time32(Millisecond)')) | ||
---- | ||
50123 | ||
|
||
query R | ||
SELECT date_part('microsecond', arrow_cast('23:32:50.123'::time, 'Time32(Millisecond)')) | ||
---- | ||
50123000 | ||
|
||
query R | ||
SELECT date_part('nanosecond', arrow_cast('23:32:50.123'::time, 'Time32(Millisecond)')) | ||
---- | ||
50123000000 | ||
|
||
query R | ||
SELECT date_part('epoch', arrow_cast('23:32:50.123'::time, 'Time32(Millisecond)')) | ||
---- | ||
84770.123 | ||
|
||
## time64 microseconds | ||
query R | ||
SELECT date_part('hour', arrow_cast('23:32:50.123456'::time, 'Time64(Microsecond)')) | ||
---- | ||
23 | ||
|
||
query R | ||
SELECT date_part('minute', arrow_cast('23:32:50.123456'::time, 'Time64(Microsecond)')) | ||
---- | ||
32 | ||
|
||
query R | ||
SELECT date_part('second', arrow_cast('23:32:50.123456'::time, 'Time64(Microsecond)')) | ||
---- | ||
50.123456 | ||
|
||
query R | ||
SELECT date_part('millisecond', arrow_cast('23:32:50.123456'::time, 'Time64(Microsecond)')) | ||
---- | ||
50123.456 | ||
|
||
query R | ||
SELECT date_part('microsecond', arrow_cast('23:32:50.123456'::time, 'Time64(Microsecond)')) | ||
---- | ||
50123456 | ||
|
||
query R | ||
SELECT date_part('nanosecond', arrow_cast('23:32:50.123456'::time, 'Time64(Microsecond)')) | ||
---- | ||
50123456000 | ||
|
||
query R | ||
SELECT date_part('epoch', arrow_cast('23:32:50.123456'::time, 'Time64(Microsecond)')) | ||
---- | ||
84770.123456 | ||
|
||
## time64 nanoseconds | ||
query R | ||
SELECT date_part('hour', arrow_cast('23:32:50.123456789'::time, 'Time64(Nanosecond)')) | ||
---- | ||
23 | ||
|
||
query R | ||
SELECT date_part('minute', arrow_cast('23:32:50.123456789'::time, 'Time64(Nanosecond)')) | ||
---- | ||
32 | ||
|
||
query R | ||
SELECT date_part('second', arrow_cast('23:32:50.123456789'::time, 'Time64(Nanosecond)')) | ||
---- | ||
50.123456789 | ||
|
||
query R | ||
SELECT date_part('millisecond', arrow_cast('23:32:50.123456789'::time, 'Time64(Nanosecond)')) | ||
---- | ||
50123.456789 | ||
|
||
# just some floating point stuff happening in the result here | ||
query R | ||
SELECT date_part('microsecond', arrow_cast('23:32:50.123456789'::time, 'Time64(Nanosecond)')) | ||
---- | ||
50123456.789000005 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just floating point stuff Not sure if want to look into it further or not There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is fine |
||
|
||
query R | ||
SELECT date_part('nanosecond', arrow_cast('23:32:50.123456789'::time, 'Time64(Nanosecond)')) | ||
---- | ||
50123456789 | ||
|
||
query R | ||
SELECT date_part('epoch', arrow_cast('23:32:50.123456789'::time, 'Time64(Nanosecond)')) | ||
---- | ||
84770.123456789 | ||
|
||
# test_extract_epoch | ||
|
||
query R | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Realized my previous comment #9613 (comment) was incorrect about panics since it'll just return an error, so correcting here