pub fn effective_timezone(
own: Option<&str>,
policy_repo_defaults: &[Option<String>],
) -> (Tz, Option<TimezoneAmbiguity>)Expand description
Pure. Decide the effective timezone a SnapshotSchedule’s cron is
evaluated in, given the schedule’s own spec.schedule.timezone (own) and the
scheduleDefaults.timezone of each matched target policy’s repository
(policy_repo_defaults, one entry per matched policy; None = that repo sets
no default). Mirrors resolve_tz fallback semantics (an unparseable name
degrades to UTC — the webhook rejects bad names up front).
Rules (the reconciler does the GETs and passes the data in):
ownset → that zone wins, no lookups, never ambiguous.ownunset, no matched policies → UTC, not ambiguous.ownunset, all matched policies resolve to one zone → that zone.ownunset, matched policies resolve to differing zones → UTC plus aTimezoneAmbiguity(recommend an explicitspec.schedule.timezone).
A single policyRef therefore never yields ambiguity (one repository). Repos
with no default resolve to UTC, so mixing “a zone” with “no default” is a
genuine disagreement and is reported.
use kopiur_api::common::effective_timezone;
// Own timezone wins outright.
let (tz, amb) = effective_timezone(Some("America/Chicago"), &[]);
assert_eq!(tz.name(), "America/Chicago");
assert!(amb.is_none());
// Unset own, one agreeing default across matched policies.
let defs = [Some("Europe/Berlin".to_string()), Some("Europe/Berlin".to_string())];
let (tz, amb) = effective_timezone(None, &defs);
assert_eq!(tz.name(), "Europe/Berlin");
assert!(amb.is_none());
// Unset own, disagreeing defaults → UTC + ambiguity signal.
let defs = [Some("Europe/Berlin".to_string()), None];
let (tz, amb) = effective_timezone(None, &defs);
assert_eq!(tz, chrono_tz::Tz::UTC);
assert!(amb.is_some());