Skip to content

Commit 51e64c3

Browse files
authored
Align NowFunc::new() with canonical ConfigOptions timezone and enhance documentation (#18347)
## Which issue does this PR close? * Closes #18219. --- ## Rationale for this change The deprecated `NowFunc::new()` constructor previously initialized its timezone using the shorthand offset `"+00"`, which was inconsistent with the canonical UTC offset format `"+00:00"` used by `ConfigOptions::default()`. This mismatch could cause subtle inconsistencies in `ScalarValue` comparisons or downstream timezone handling. This PR ensures backward compatibility while aligning `NowFunc::new()` with the canonical default configuration, making behavior consistent across both constructors. It also improves documentation to clarify this relationship and provides a regression test to confirm parity between the two initialization paths. --- ## What changes are included in this PR? * Updated the deprecated `NowFunc::new()` to delegate to `NowFunc::new_with_config(&ConfigOptions::default())`. * Added detailed doc comments explaining the rationale and proper usage of the constructors. * Introduced a new test module verifying that `NowFunc::new()` and `NowFunc::new_with_config()` produce identical return fields and scalar values. * Updated user documentation (`scalar_functions.md`) to note the constructor preference and clarify the canonical default timezone format (`+00:00`). --- ## Are these changes tested? ✅ Yes. A new test `now_func_default_matches_config` was added to confirm functional equivalence between the legacy and configuration-based constructors, including matching field outputs and scalar timezones. --- ## Are there any user-facing changes? * **Yes**, but backward-compatible: * `NowFunc::new()` remains available but now mirrors the canonical timezone offset (`+00:00`). * Documentation has been updated to guide users toward the preferred `NowFunc::new_with_config()` method. No breaking API or behavior changes are expected, as this update standardizes the default timezone while maintaining prior function signatures.
1 parent a393fc7 commit 51e64c3

File tree

1 file changed

+48
-5
lines changed
  • datafusion/functions/src/datetime

1 file changed

+48
-5
lines changed

datafusion/functions/src/datetime/now.rs

Lines changed: 48 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,14 @@ impl Default for NowFunc {
5454

5555
impl NowFunc {
5656
#[deprecated(since = "50.2.0", note = "use `new_with_config` instead")]
57+
/// Deprecated constructor retained for backwards compatibility.
58+
///
59+
/// Prefer [`NowFunc::new_with_config`] which allows specifying the
60+
/// timezone via [`ConfigOptions`]. This helper now mirrors the
61+
/// canonical default offset (`"+00:00"`) provided by
62+
/// `ConfigOptions::default()`.
5763
pub fn new() -> Self {
58-
Self {
59-
signature: Signature::nullary(Volatility::Stable),
60-
aliases: vec!["current_timestamp".to_string()],
61-
timezone: Some(Arc::from("+00")),
62-
}
64+
Self::new_with_config(&ConfigOptions::default())
6365
}
6466

6567
pub fn new_with_config(config: &ConfigOptions) -> Self {
@@ -138,3 +140,44 @@ impl ScalarUDFImpl for NowFunc {
138140
self.doc()
139141
}
140142
}
143+
144+
#[cfg(test)]
145+
mod tests {
146+
use super::*;
147+
148+
#[allow(deprecated)]
149+
#[test]
150+
fn now_func_default_matches_config() {
151+
let default_config = ConfigOptions::default();
152+
153+
let legacy_now = NowFunc::new();
154+
let configured_now = NowFunc::new_with_config(&default_config);
155+
156+
let empty_fields: [FieldRef; 0] = [];
157+
let empty_scalars: [Option<&ScalarValue>; 0] = [];
158+
159+
let legacy_field = legacy_now
160+
.return_field_from_args(ReturnFieldArgs {
161+
arg_fields: &empty_fields,
162+
scalar_arguments: &empty_scalars,
163+
})
164+
.expect("legacy now() return field");
165+
166+
let configured_field = configured_now
167+
.return_field_from_args(ReturnFieldArgs {
168+
arg_fields: &empty_fields,
169+
scalar_arguments: &empty_scalars,
170+
})
171+
.expect("configured now() return field");
172+
173+
assert_eq!(legacy_field.as_ref(), configured_field.as_ref());
174+
175+
let legacy_scalar =
176+
ScalarValue::TimestampNanosecond(None, legacy_now.timezone.clone());
177+
let configured_scalar =
178+
ScalarValue::TimestampNanosecond(None, configured_now.timezone.clone());
179+
180+
assert_eq!(legacy_scalar, configured_scalar);
181+
assert_eq!(Some("+00:00"), legacy_now.timezone.as_deref());
182+
}
183+
}

0 commit comments

Comments
 (0)