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::{Result, ScalarValue, internal_err};
26use datafusion_expr::simplify::{ExprSimplifyResult, SimplifyContext};
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: &SimplifyContext,
126 ) -> Result<ExprSimplifyResult> {
127 let Some(now_ts) = info.query_execution_start_time() else {
128 return Ok(ExprSimplifyResult::Original(args));
129 };
130
131 Ok(ExprSimplifyResult::Simplified(Expr::Literal(
132 ScalarValue::TimestampNanosecond(
133 now_ts.timestamp_nanos_opt(),
134 self.timezone.clone(),
135 ),
136 None,
137 )))
138 }
139
140 fn aliases(&self) -> &[String] {
141 &self.aliases
142 }
143
144 fn documentation(&self) -> Option<&Documentation> {
145 self.doc()
146 }
147}
148
149#[cfg(test)]
150mod tests {
151 use super::*;
152
153 #[expect(deprecated)]
154 #[test]
155 fn now_func_default_matches_config() {
156 let default_config = ConfigOptions::default();
157
158 let legacy_now = NowFunc::new();
159 let configured_now = NowFunc::new_with_config(&default_config);
160
161 let empty_fields: [FieldRef; 0] = [];
162 let empty_scalars: [Option<&ScalarValue>; 0] = [];
163
164 let legacy_field = legacy_now
165 .return_field_from_args(ReturnFieldArgs {
166 arg_fields: &empty_fields,
167 scalar_arguments: &empty_scalars,
168 })
169 .expect("legacy now() return field");
170
171 let configured_field = configured_now
172 .return_field_from_args(ReturnFieldArgs {
173 arg_fields: &empty_fields,
174 scalar_arguments: &empty_scalars,
175 })
176 .expect("configured now() return field");
177
178 assert_eq!(legacy_field.as_ref(), configured_field.as_ref());
179
180 let legacy_scalar =
181 ScalarValue::TimestampNanosecond(None, legacy_now.timezone.clone());
182 let configured_scalar =
183 ScalarValue::TimestampNanosecond(None, configured_now.timezone.clone());
184
185 assert_eq!(legacy_scalar, configured_scalar);
186 assert_eq!(None, legacy_now.timezone.as_deref());
187 }
188}