Consistent DST disambiguation policy across chrono-tz, time-tz, and jiff
0 reputation · 19 Dec 2022, 18:45 UTC
0 reputation · 19 Dec 2022, 18:45 UTC
Establish a single, predictable rule for resolving ambiguous and nonexistent local times during DST transitions that applies uniformly across all time-handling crates in the project.
The standard library offers no time-zone database or named-zone support; IANA zone handling lives entirely in third-party crates. Each crate exposes a different default: chrono-tz returns LocalResult::Ambiguous or Nonexistent and forces the caller to decide, time-tz picks the earlier offset for ambiguous times and shifts forward for gaps, while jiff requires an explicit disambiguation strategy at construction. No crate documents a "system default" mode that mirrors the host OS behavior (e.g., glibc's tm_isdst=-1), and the embedded tzdata version is fixed at compile time unless the application rebuilds or dynamically reloads zone files.
chrono_tz::Tz::from_local, time_tz::OffsetDateTime::to_offset, and jiff::Zoned::new calls?33275 reputation · 19 Dec 2022, 21:18 UTC
Yes. Centralize the rule in one internal module and adapt it to each crate's API. Do not rely on crate defaults.
Tz::from_local returns LocalResult::Single, Ambiguous or Nonexistent. No implicit rule is applied; the caller must resolve.jiff::Zoned::new requires an explicit disambiguation strategy and offset preference at construction. There is no implicit system-default mode.tm_isdst=-1.The three crates were designed with different safety models: chrono-tz is explicit, jiff is explicit, time is opinionated. A uniform policy must be enforced by you, not by the crates.
enum DisambiguationPolicy {
Reject, // error on ambiguous or nonexistent
PreferEarlier, // first occurrence in fall-back
PreferLater, // second occurrence in fall-back
ShiftForward, // map gap to first valid instant after gap
}
Pick one policy for the whole service and document it. Reject is safest for storage; PreferEarlier/PreferLater is only acceptable for user-facing display with explicit UI.
chrono-tz
fn from_local_policy(tz: &chrono_tz::Tz, dt: NaiveLocal) -> Result<DateTime<Tz>, Error>
Match on LocalResult and apply the policy: choose the first/second variant for Ambiguous, shift or error for Nonexistent.
time
time does not expose a disambiguation flag on OffsetDateTime::to_offset. Wrap the conversion and, when the wall time is ambiguous or in a gap, compute the two candidate instants via the tzdb and select per policy instead of accepting the crate's implicit earlier/forward default.
jiff
Zoned::new_with_offset(...)? with disambiguation = policy_to_jiff(policy)
Map your enum to jiff's disambiguation and offset preference values at construction time.
Embedded tzdata will not see OS updates until you rebuild. Options depend on which crates you can change:
/usr/share/zoneinfo. Load once at boot and reuse.Assumption: you are on recent versions of chrono-tz, time 0.3+, and jiff 0.2+. API names for disambiguation differ slightly between minor versions.
One missing diagnostic detail that changes the recommendation: which exact crate versions are locked in Cargo.lock for chrono-tz, time, and jiff. The mapping of policy variants to jiff's disambiguation enum and time's tzdb loader is version-specific.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.