datafusion_functions/datetime/
current_date.rs1use arrow::array::timezone::Tz;
19use arrow::datatypes::DataType;
20use arrow::datatypes::DataType::Date32;
21use chrono::{Datelike, NaiveDate, TimeZone};
22
23use datafusion_common::{Result, ScalarValue, internal_err};
24use datafusion_expr::simplify::{ExprSimplifyResult, SimplifyContext};
25use datafusion_expr::{
26 ColumnarValue, Documentation, Expr, ScalarFunctionArgs, ScalarUDFImpl, Signature,
27 Volatility,
28};
29use datafusion_macros::user_doc;
30
31#[user_doc(
32 doc_section(label = "Time and Date Functions"),
33 description = r#"
34Returns the current date in the session time zone.
35
36The `current_date()` return value is determined at query time and will return the same date, no matter when in the query plan the function executes.
37"#,
38 syntax_example = "current_date()",
39 sql_example = r#"```sql
40> SELECT current_date();
41+----------------+
42| current_date() |
43+----------------+
44| 2024-12-23 |
45+----------------+
46
47-- The current date is based on the session time zone (UTC by default)
48> SET datafusion.execution.time_zone = 'Asia/Tokyo';
49> SELECT current_date();
50+----------------+
51| current_date() |
52+----------------+
53| 2024-12-24 |
54+----------------+
55```"#
56)]
57#[derive(Debug, PartialEq, Eq, Hash)]
58pub struct CurrentDateFunc {
59 signature: Signature,
60 aliases: Vec<String>,
61}
62
63impl Default for CurrentDateFunc {
64 fn default() -> Self {
65 Self::new()
66 }
67}
68
69impl CurrentDateFunc {
70 pub fn new() -> Self {
71 Self {
72 signature: Signature::nullary(Volatility::Stable),
73 aliases: vec![String::from("today")],
74 }
75 }
76}
77
78impl ScalarUDFImpl for CurrentDateFunc {
85 fn name(&self) -> &str {
86 "current_date"
87 }
88
89 fn signature(&self) -> &Signature {
90 &self.signature
91 }
92
93 fn return_type(&self, _arg_types: &[DataType]) -> Result<DataType> {
94 Ok(Date32)
95 }
96
97 fn invoke_with_args(&self, _args: ScalarFunctionArgs) -> Result<ColumnarValue> {
98 internal_err!(
99 "invoke should not be called on a simplified current_date() function"
100 )
101 }
102
103 fn aliases(&self) -> &[String] {
104 &self.aliases
105 }
106
107 fn simplify(
108 &self,
109 args: Vec<Expr>,
110 info: &SimplifyContext,
111 ) -> Result<ExprSimplifyResult> {
112 let Some(now_ts) = info.query_execution_start_time() else {
113 return Ok(ExprSimplifyResult::Original(args));
114 };
115
116 let days = info
118 .config_options()
119 .execution
120 .time_zone
121 .as_ref()
122 .and_then(|tz| tz.parse::<Tz>().ok())
123 .map_or_else(
124 || datetime_to_days(&now_ts),
125 |tz| {
126 let local_now = tz.from_utc_datetime(&now_ts.naive_utc());
127 datetime_to_days(&local_now)
128 },
129 );
130 Ok(ExprSimplifyResult::Simplified(Expr::Literal(
131 ScalarValue::Date32(Some(days)),
132 None,
133 )))
134 }
135
136 fn documentation(&self) -> Option<&Documentation> {
137 self.doc()
138 }
139}
140
141fn datetime_to_days<T: Datelike>(dt: &T) -> i32 {
143 dt.num_days_from_ce()
144 - NaiveDate::from_ymd_opt(1970, 1, 1)
145 .unwrap()
146 .num_days_from_ce()
147}