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