datafusion_functions/datetime/
now.rs1use arrow::datatypes::DataType::Timestamp;
19use arrow::datatypes::TimeUnit::Nanosecond;
20use arrow::datatypes::{DataType, Field, FieldRef};
21use std::any::Any;
22use std::sync::Arc;
23
24use datafusion_common::config::ConfigOptions;
25use datafusion_common::{internal_err, Result, ScalarValue};
26use datafusion_expr::simplify::{ExprSimplifyResult, SimplifyInfo};
27use datafusion_expr::{
28 ColumnarValue, Documentation, Expr, ReturnFieldArgs, ScalarUDF, ScalarUDFImpl,
29 Signature, Volatility,
30};
31use datafusion_macros::user_doc;
32
33#[user_doc(
34 doc_section(label = "Time and Date Functions"),
35 description = r#"
36Returns the current timestamp in the system configured timezone (None by default).
37
38The `now()` return value is determined at query time and will return the same timestamp, no matter when in the query plan the function executes.
39"#,
40 syntax_example = "now()"
41)]
42#[derive(Debug, PartialEq, Eq, Hash)]
43pub struct NowFunc {
44 signature: Signature,
45 aliases: Vec<String>,
46 timezone: Option<Arc<str>>,
47}
48
49impl Default for NowFunc {
50 fn default() -> Self {
51 Self::new_with_config(&ConfigOptions::default())
52 }
53}
54
55impl NowFunc {
56 #[deprecated(since = "50.2.0", note = "use `new_with_config` instead")]
57 pub fn new() -> Self {
63 Self::new_with_config(&ConfigOptions::default())
64 }
65
66 pub fn new_with_config(config: &ConfigOptions) -> Self {
67 Self {
68 signature: Signature::nullary(Volatility::Stable),
69 aliases: vec!["current_timestamp".to_string()],
70 timezone: config
71 .execution
72 .time_zone
73 .as_ref()
74 .map(|tz| Arc::from(tz.as_str())),
75 }
76 }
77}
78
79impl ScalarUDFImpl for NowFunc {
86 fn as_any(&self) -> &dyn Any {
87 self
88 }
89
90 fn name(&self) -> &str {
91 "now"
92 }
93
94 fn signature(&self) -> &Signature {
95 &self.signature
96 }
97
98 fn with_updated_config(&self, config: &ConfigOptions) -> Option<ScalarUDF> {
99 Some(Self::new_with_config(config).into())
100 }
101
102 fn return_field_from_args(&self, _args: ReturnFieldArgs) -> Result<FieldRef> {
103 Ok(Field::new(
104 self.name(),
105 Timestamp(Nanosecond, self.timezone.clone()),
106 false,
107 )
108 .into())
109 }
110
111 fn return_type(&self, _arg_types: &[DataType]) -> Result<DataType> {
112 internal_err!("return_field_from_args should be called instead")
113 }
114
115 fn invoke_with_args(
116 &self,
117 _args: datafusion_expr::ScalarFunctionArgs,
118 ) -> Result<ColumnarValue> {
119 internal_err!("invoke should not be called on a simplified now() function")
120 }
121
122 fn simplify(
123 &self,
124 _args: Vec<Expr>,
125 info: &dyn SimplifyInfo,
126 ) -> Result<ExprSimplifyResult> {
127 let now_ts = info
128 .execution_props()
129 .query_execution_start_time
130 .timestamp_nanos_opt();
131
132 Ok(ExprSimplifyResult::Simplified(Expr::Literal(
133 ScalarValue::TimestampNanosecond(now_ts, self.timezone.clone()),
134 None,
135 )))
136 }
137
138 fn aliases(&self) -> &[String] {
139 &self.aliases
140 }
141
142 fn documentation(&self) -> Option<&Documentation> {
143 self.doc()
144 }
145}
146
147#[cfg(test)]
148mod tests {
149 use super::*;
150
151 #[allow(deprecated)]
152 #[test]
153 fn now_func_default_matches_config() {
154 let default_config = ConfigOptions::default();
155
156 let legacy_now = NowFunc::new();
157 let configured_now = NowFunc::new_with_config(&default_config);
158
159 let empty_fields: [FieldRef; 0] = [];
160 let empty_scalars: [Option<&ScalarValue>; 0] = [];
161
162 let legacy_field = legacy_now
163 .return_field_from_args(ReturnFieldArgs {
164 arg_fields: &empty_fields,
165 scalar_arguments: &empty_scalars,
166 })
167 .expect("legacy now() return field");
168
169 let configured_field = configured_now
170 .return_field_from_args(ReturnFieldArgs {
171 arg_fields: &empty_fields,
172 scalar_arguments: &empty_scalars,
173 })
174 .expect("configured now() return field");
175
176 assert_eq!(legacy_field.as_ref(), configured_field.as_ref());
177
178 let legacy_scalar =
179 ScalarValue::TimestampNanosecond(None, legacy_now.timezone.clone());
180 let configured_scalar =
181 ScalarValue::TimestampNanosecond(None, configured_now.timezone.clone());
182
183 assert_eq!(legacy_scalar, configured_scalar);
184 assert_eq!(None, legacy_now.timezone.as_deref());
185 }
186}