datafusion_functions/datetime/
mod.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! date & time DataFusion functions
19
20use std::sync::Arc;
21
22use datafusion_expr::ScalarUDF;
23
24pub mod common;
25pub mod current_date;
26pub mod current_time;
27pub mod date_bin;
28pub mod date_part;
29pub mod date_trunc;
30pub mod from_unixtime;
31pub mod make_date;
32pub mod now;
33pub mod planner;
34pub mod to_char;
35pub mod to_date;
36pub mod to_local_time;
37pub mod to_timestamp;
38pub mod to_unixtime;
39
40// create UDFs
41make_udf_function!(current_date::CurrentDateFunc, current_date);
42make_udf_function!(current_time::CurrentTimeFunc, current_time);
43make_udf_function!(date_bin::DateBinFunc, date_bin);
44make_udf_function!(date_part::DatePartFunc, date_part);
45make_udf_function!(date_trunc::DateTruncFunc, date_trunc);
46make_udf_function!(make_date::MakeDateFunc, make_date);
47make_udf_function!(from_unixtime::FromUnixtimeFunc, from_unixtime);
48make_udf_function!(now::NowFunc, now);
49make_udf_function!(to_char::ToCharFunc, to_char);
50make_udf_function!(to_date::ToDateFunc, to_date);
51make_udf_function!(to_local_time::ToLocalTimeFunc, to_local_time);
52make_udf_function!(to_unixtime::ToUnixtimeFunc, to_unixtime);
53make_udf_function!(to_timestamp::ToTimestampFunc, to_timestamp);
54make_udf_function!(to_timestamp::ToTimestampSecondsFunc, to_timestamp_seconds);
55make_udf_function!(to_timestamp::ToTimestampMillisFunc, to_timestamp_millis);
56make_udf_function!(to_timestamp::ToTimestampMicrosFunc, to_timestamp_micros);
57make_udf_function!(to_timestamp::ToTimestampNanosFunc, to_timestamp_nanos);
58
59// we cannot currently use the export_functions macro since it doesn't handle
60// functions with varargs currently
61
62pub mod expr_fn {
63    use datafusion_expr::Expr;
64
65    export_functions!((
66        current_date,
67        "returns current UTC date as a Date32 value",
68    ),(
69        current_time,
70        "returns current UTC time as a Time64 value",
71    ),(
72        from_unixtime,
73        "converts an integer to RFC3339 timestamp format string",
74        unixtime
75    ),(
76        date_bin,
77        "coerces an arbitrary timestamp to the start of the nearest specified interval",
78        stride source origin
79    ),(
80        date_part,
81        "extracts a subfield from the date",
82        part date
83    ),(
84        date_trunc,
85        "truncates the date to a specified level of precision",
86        part date
87    ),(
88        make_date,
89        "make a date from year, month and day component parts",
90        year month day
91    ),(
92        now,
93        "returns the current timestamp in nanoseconds, using the same value for all instances of now() in same statement",
94    ),
95    (
96        to_local_time,
97        "converts a timezone-aware timestamp to local time (with no offset or timezone information), i.e. strips off the timezone from the timestamp",
98        args,
99    ),
100    (
101        to_unixtime,
102        "converts a string and optional formats to a Unixtime",
103        args,
104    ),(
105        to_timestamp,
106        "converts a string and optional formats to a `Timestamp(Nanoseconds, None)`",
107        args,
108    ),(
109        to_timestamp_seconds,
110        "converts a string and optional formats to a `Timestamp(Seconds, None)`",
111        args,
112    ),(
113        to_timestamp_millis,
114        "converts a string and optional formats to a `Timestamp(Milliseconds, None)`",
115        args,
116    ),(
117        to_timestamp_micros,
118        "converts a string and optional formats to a `Timestamp(Microseconds, None)`",
119        args,
120    ),(
121        to_timestamp_nanos,
122        "converts a string and optional formats to a `Timestamp(Nanoseconds, None)`",
123        args,
124    ));
125
126    /// Returns a string representation of a date, time, timestamp or duration based
127    /// on a Chrono pattern.
128    ///
129    /// The syntax for the patterns can be found at
130    /// <https://docs.rs/chrono/latest/chrono/format/strftime/index.html>
131    ///
132    /// # Examples
133    ///
134    /// ```ignore
135    /// # use chrono::prelude::*;
136    /// # use datafusion::prelude::*;
137    /// # use datafusion::error::Result;
138    /// # use datafusion_common::ScalarValue::TimestampNanosecond;
139    /// # use std::sync::Arc;
140    /// # use arrow::array::{Date32Array, RecordBatch, StringArray};
141    /// # use arrow::datatypes::{DataType, Field, Schema};
142    /// # #[tokio::main]
143    /// # async fn main() -> Result<()> {
144    /// let schema = Arc::new(Schema::new(vec![
145    ///     Field::new("values", DataType::Date32, false),
146    ///     Field::new("patterns", DataType::Utf8, false),
147    /// ]));
148    ///
149    /// let batch = RecordBatch::try_new(
150    ///     schema,
151    ///     vec![
152    ///         Arc::new(Date32Array::from(vec![
153    ///             18506,
154    ///             18507,
155    ///             18508,
156    ///             18509,
157    ///         ])),
158    ///         Arc::new(StringArray::from(vec![
159    ///             "%Y-%m-%d",
160    ///             "%Y:%m:%d",
161    ///             "%Y%m%d",
162    ///             "%d-%m-%Y",
163    ///         ])),
164    ///     ],
165    /// )?;
166    ///
167    /// let ctx = SessionContext::new();
168    /// ctx.register_batch("t", batch)?;
169    /// let df = ctx.table("t").await?;
170    ///
171    /// // use the to_char function to convert col 'values',
172    /// // to strings using patterns in col 'patterns'
173    /// let df = df.with_column(
174    ///     "date_str",
175    ///     to_char(col("values"), col("patterns"))
176    /// )?;
177    /// // Note that providing a scalar value for the pattern
178    /// // is more performant
179    /// let df = df.with_column(
180    ///     "date_str2",
181    ///     to_char(col("values"), lit("%d-%m-%Y"))
182    /// )?;
183    /// // literals can be used as well with dataframe calls
184    /// let timestamp = "2026-07-08T09:10:11"
185    ///     .parse::<NaiveDateTime>()
186    ///     .unwrap()
187    ///     .with_nanosecond(56789)
188    ///     .unwrap()
189    ///     .timestamp_nanos_opt()
190    ///     .unwrap();
191    /// let df = df.with_column(
192    ///     "timestamp_str",
193    ///     to_char(lit(TimestampNanosecond(Some(timestamp), None)), lit("%d-%m-%Y %H:%M:%S"))
194    /// )?;
195    ///
196    /// df.show().await?;
197    ///
198    /// # Ok(())
199    /// # }
200    /// ```
201    pub fn to_char(datetime: Expr, format: Expr) -> Expr {
202        super::to_char().call(vec![datetime, format])
203    }
204
205    /// ```ignore
206    /// # use std::sync::Arc;
207    ///
208    /// # use datafusion_common::Result;
209    ///
210    /// # #[tokio::main]
211    /// # async fn main() -> Result<()> {
212    /// #  use arrow::array::StringArray;
213    /// #  use arrow::datatypes::{DataType, Field, Schema};
214    /// #  use arrow::record_batch::RecordBatch;
215    /// #  use datafusion_expr::col;
216    /// #  use datafusion::prelude::*;
217    /// #  use datafusion_functions::expr_fn::to_date;
218    ///
219    ///     // define a schema.
220    ///     let schema = Arc::new(Schema::new(vec![Field::new("a", DataType::Utf8, false)]));
221    ///
222    ///     // define data.
223    ///     let batch = RecordBatch::try_new(
224    ///         schema,
225    ///         vec![Arc::new(StringArray::from(vec![
226    ///             "2020-09-08T13:42:29Z",
227    ///             "2020-09-08T13:42:29.190855-05:00",
228    ///             "2020-08-09 12:13:29",
229    ///             "2020-01-02",
230    ///         ]))],
231    ///     )?;
232    ///
233    ///     // declare a new context. In spark API, this corresponds to a new spark SQLsession
234    ///     let ctx = SessionContext::new();
235    ///
236    ///     // declare a table in memory. In spark API, this corresponds to createDataFrame(...).
237    ///     ctx.register_batch("t", batch)?;
238    ///     let df = ctx.table("t").await?;
239    ///
240    ///     // use to_date function to convert col 'a' to timestamp type using the default parsing
241    ///     let df = df.with_column("a", to_date(vec![col("a")]))?;
242    ///
243    ///     let df = df.select_columns(&["a"])?;
244    ///
245    ///     // print the results
246    ///     df.show().await?;
247    ///
248    ///     # Ok(())
249    /// # }
250    /// ```
251    pub fn to_date(args: Vec<Expr>) -> Expr {
252        super::to_date().call(args)
253    }
254}
255
256/// Returns all DataFusion functions defined in this package
257pub fn functions() -> Vec<Arc<ScalarUDF>> {
258    vec![
259        current_date(),
260        current_time(),
261        date_bin(),
262        date_part(),
263        date_trunc(),
264        from_unixtime(),
265        make_date(),
266        now(),
267        to_char(),
268        to_date(),
269        to_local_time(),
270        to_unixtime(),
271        to_timestamp(),
272        to_timestamp_seconds(),
273        to_timestamp_millis(),
274        to_timestamp_micros(),
275        to_timestamp_nanos(),
276    ]
277}