Skip to content

Commit 5c02664

Browse files
authored
Double type argument for to_timestamp function (#8159)
* feat: test queries for to_timestamp(float) WIP * feat: Float64 input for to_timestamp * cargo fmt * clippy * docs: double input type for to_timestamp * feat: cast floats to timestamp * style: cargo fmt * fix: float64 cast for timestamp nanos only
1 parent e52d150 commit 5c02664

File tree

5 files changed

+55
-4
lines changed

5 files changed

+55
-4
lines changed

datafusion/expr/src/built_in_function.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1023,6 +1023,7 @@ impl BuiltinScalarFunction {
10231023
1,
10241024
vec![
10251025
Int64,
1026+
Float64,
10261027
Timestamp(Nanosecond, None),
10271028
Timestamp(Microsecond, None),
10281029
Timestamp(Millisecond, None),

datafusion/physical-expr/src/datetime_expressions.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -971,6 +971,11 @@ pub fn to_timestamp_invoke(args: &[ColumnarValue]) -> Result<ColumnarValue> {
971971
&DataType::Timestamp(TimeUnit::Nanosecond, None),
972972
None,
973973
),
974+
DataType::Float64 => cast_column(
975+
&args[0],
976+
&DataType::Timestamp(TimeUnit::Nanosecond, None),
977+
None,
978+
),
974979
DataType::Timestamp(_, None) => cast_column(
975980
&args[0],
976981
&DataType::Timestamp(TimeUnit::Nanosecond, None),

datafusion/physical-expr/src/expressions/cast.rs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,20 @@ pub fn cast_column(
176176
kernels::cast::cast_with_options(array, cast_type, &cast_options)?,
177177
)),
178178
ColumnarValue::Scalar(scalar) => {
179-
let scalar_array = scalar.to_array()?;
179+
let scalar_array = if cast_type
180+
== &DataType::Timestamp(arrow_schema::TimeUnit::Nanosecond, None)
181+
{
182+
if let ScalarValue::Float64(Some(float_ts)) = scalar {
183+
ScalarValue::Int64(
184+
Some((float_ts * 1_000_000_000_f64).trunc() as i64),
185+
)
186+
.to_array()?
187+
} else {
188+
scalar.to_array()?
189+
}
190+
} else {
191+
scalar.to_array()?
192+
};
180193
let cast_array = kernels::cast::cast_with_options(
181194
&scalar_array,
182195
cast_type,
@@ -201,7 +214,10 @@ pub fn cast_with_options(
201214
let expr_type = expr.data_type(input_schema)?;
202215
if expr_type == cast_type {
203216
Ok(expr.clone())
204-
} else if can_cast_types(&expr_type, &cast_type) {
217+
} else if can_cast_types(&expr_type, &cast_type)
218+
|| (expr_type == DataType::Float64
219+
&& cast_type == DataType::Timestamp(arrow_schema::TimeUnit::Nanosecond, None))
220+
{
205221
Ok(Arc::new(CastExpr::new(expr, cast_type, cast_options)))
206222
} else {
207223
not_impl_err!("Unsupported CAST from {expr_type:?} to {cast_type:?}")

datafusion/sqllogictest/test_files/timestamps.slt

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,35 @@ SELECT COUNT(*) FROM ts_data_secs where ts > to_timestamp_seconds('2020-09-08T12
291291
----
292292
2
293293

294+
295+
# to_timestamp float inputs
296+
297+
query PPP
298+
SELECT to_timestamp(1.1) as c1, cast(1.1 as timestamp) as c2, 1.1::timestamp as c3;
299+
----
300+
1970-01-01T00:00:01.100 1970-01-01T00:00:01.100 1970-01-01T00:00:01.100
301+
302+
query PPP
303+
SELECT to_timestamp(-1.1) as c1, cast(-1.1 as timestamp) as c2, (-1.1)::timestamp as c3;
304+
----
305+
1969-12-31T23:59:58.900 1969-12-31T23:59:58.900 1969-12-31T23:59:58.900
306+
307+
query PPP
308+
SELECT to_timestamp(0.0) as c1, cast(0.0 as timestamp) as c2, 0.0::timestamp as c3;
309+
----
310+
1970-01-01T00:00:00 1970-01-01T00:00:00 1970-01-01T00:00:00
311+
312+
query PPP
313+
SELECT to_timestamp(1.23456789) as c1, cast(1.23456789 as timestamp) as c2, 1.23456789::timestamp as c3;
314+
----
315+
1970-01-01T00:00:01.234567890 1970-01-01T00:00:01.234567890 1970-01-01T00:00:01.234567890
316+
317+
query PPP
318+
SELECT to_timestamp(123456789.123456789) as c1, cast(123456789.123456789 as timestamp) as c2, 123456789.123456789::timestamp as c3;
319+
----
320+
1973-11-29T21:33:09.123456784 1973-11-29T21:33:09.123456784 1973-11-29T21:33:09.123456784
321+
322+
294323
# from_unixtime
295324

296325
# 1599566400 is '2020-09-08T12:00:00+00:00'

docs/source/user-guide/sql/scalar_functions.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1457,9 +1457,9 @@ extract(field FROM source)
14571457
### `to_timestamp`
14581458

14591459
Converts a value to a timestamp (`YYYY-MM-DDT00:00:00Z`).
1460-
Supports strings, integer, and unsigned integer types as input.
1460+
Supports strings, integer, unsigned integer, and double types as input.
14611461
Strings are parsed as RFC3339 (e.g. '2023-07-20T05:44:00')
1462-
Integers and unsigned integers are interpreted as seconds since the unix epoch (`1970-01-01T00:00:00Z`)
1462+
Integers, unsigned integers, and doubles are interpreted as seconds since the unix epoch (`1970-01-01T00:00:00Z`)
14631463
return the corresponding timestamp.
14641464

14651465
```

0 commit comments

Comments
 (0)