std/calendar
Civil date-time — the Date / Time / NaiveDateTime / OffsetDateTime /
DateTime ladder. DateTime (IANA-zoned, DST-aware) is the safe default for
real moments; NaiveDateTime’s prefix marks it as a wall-reading footgun.
Components and arithmetic are exposed through the DateParts / TimeParts /
Anchored interfaces plus Add impls for typed civil units; civil vs
physical arithmetic diverge across DST.
Import with import std/calendar.
Exports
Section titled “Exports”Modules
Types
Interfaces
enum Error
Section titled “enum Error”enum Error { InvalidFormat String InvalidValue String UnknownZone String Nonexistent String Ambiguous String }
Error — what went wrong constructing or projecting a calendar value.
The first two variants (InvalidFormat, InvalidValue) cover parsing
and construction across every civil type. The last three
(UnknownZone, Nonexistent, Ambiguous) are only surfaced by the
anchored projection cluster (OffsetDateTime, DateTime):
UnknownZone when the zone name isn’t in the embedded tzdb;
Nonexistent when a wall-clock reading falls in a spring-forward
gap with mode = Reject; Ambiguous when a wall-clock reading
falls in a fall-back fold with mode = Reject. (Other
disambiguation modes resolve gaps/folds silently.)
Error.to_string
Section titled “Error.to_string”impl Display
fn to_string(e: Error): String
impl Display.to_string
Error.inspect
Section titled “Error.inspect”impl Debug
fn inspect(value: Error): String
impl Debug.inspect
interface DateParts
Section titled “interface DateParts”interface DateParts { fn year(value: self): Int fn month(value: self): Int fn day(value: self): Int }
Date-bearing values expose their year/month/day components.
Impls: Date, NaiveDateTime, OffsetDateTime, DateTime.
interface TimeParts
Section titled “interface TimeParts”interface TimeParts { fn hour(value: self): Int fn minute(value: self): Int fn second(value: self): Int fn nanosecond(value: self): Int }
Time-of-day values expose their hour/minute/second/
nanosecond components. Impls: Time, NaiveDateTime,
OffsetDateTime, DateTime.
interface Anchored
Section titled “interface Anchored”interface Anchored { fn to_instant(value: self): Instant fn offset(value: self): Duration }
Anchored-to-a-moment values expose their underlying Instant
plus the effective UTC offset at that instant. Impls:
OffsetDateTime, DateTime. Re-projecting the same instant
through a different IANA zone is DateTime.with_zone(dt, zone),
a DateTime-specific function — not in this interface because
OffsetDateTime has a fixed offset, not a zone, and can’t
sensibly re-zone.
module Civil
Section titled “module Civil”type Years Int
Whole calendar years for civil calendar arithmetic on date-bearing values.
Months
Section titled “Months”type Months Int
Whole calendar months for civil calendar arithmetic on date-bearing values.
type Weeks Int
Whole calendar weeks for civil calendar arithmetic on date-bearing values.
type Days Int
Whole calendar days for civil calendar arithmetic on date-bearing values.
type Hours Int
Whole civil hours for date-time wall-clock arithmetic.
Minutes
Section titled “Minutes”type Minutes Int
Whole civil minutes for date-time wall-clock arithmetic.
Seconds
Section titled “Seconds”type Seconds Int
Whole civil seconds for date-time wall-clock arithmetic.
Milliseconds
Section titled “Milliseconds”type Milliseconds Int
Whole civil milliseconds for date-time wall-clock arithmetic.
Microseconds
Section titled “Microseconds”type Microseconds Int
Whole civil microseconds for date-time wall-clock arithmetic.
Nanoseconds
Section titled “Nanoseconds”type Nanoseconds Int
Whole civil nanoseconds for date-time wall-clock arithmetic.
struct Date
Section titled “struct Date”struct Date
opaque — construction surface is private to its defining module
A calendar date — year/month/day, no time-of-day, no zone. Construct
via Date.new(y, m, d) (validating), Date.parse, or the
Date"…" typed literal. Components reachable via year/month/day
(or the DateParts interface).
Date.new
Section titled “Date.new”fn new(year: Int, month: Int, day: Int): Result<Date, Error>
type function on Date
Construct a Date, validating the combination (no Feb 30,
leap-year aware). Returns Err(.InvalidValue(...)) for impossible
dates.
Date.parse
Section titled “Date.parse”fn parse(s: String): Result<Date, Error>
type function on Date
Parse an ISO-8601 date string (YYYY-MM-DD) into a Date. Backs
the Date"…" typed literal and is exported for callers parsing
from arbitrary string sources.
Date.days_between
Section titled “Date.days_between”fn days_between(earlier: Date, later: Date): Int
type function on Date
Number of whole days between two Dates — positive if later is
after earlier, negative if before. (Calendar-day count, ignoring
any sub-day time of day.)
Date.from_fragments
Section titled “Date.from_fragments”impl Literal
fn from_fragments(fragments: List<Fragment<String>>): Result<Date, Error>
impl Literal.from_fragments
Date.to_string
Section titled “Date.to_string”impl Display
fn to_string(d: Date): String
impl Display.to_string
ISO-8601 date string (YYYY-MM-DD).
Date.inspect
Section titled “Date.inspect”impl Debug
fn inspect(d: Date): String
impl Debug.inspect
Date.year
Section titled “Date.year”impl DateParts
fn year(value: Date): Int
impl DateParts.year
Date.month
Section titled “Date.month”impl DateParts
fn month(value: Date): Int
impl DateParts.month
Date.day
Section titled “Date.day”impl DateParts
fn day(value: Date): Int
impl DateParts.day
Date.add
Section titled “Date.add”impl Add
fn add(lhs: Date, rhs: Civil.Years): Date
impl Add.add
Add whole calendar years, clamping leap days when needed.
Date.subtract
Section titled “Date.subtract”impl Subtract
fn subtract(lhs: Date, Civil.Years(n)): Date
impl Subtract.subtract
Subtract whole calendar years, clamping leap days when needed.
Date.equal?
Section titled “Date.equal?”impl Equatable
fn equal?(a: Date, b: Date): Bool
impl Equatable.equal?
Date.hash
Section titled “Date.hash”impl Hashable
fn hash(value: Date): Int
impl Hashable.hash
Date.compare
Section titled “Date.compare”impl Comparable
fn compare(a: Date, b: Date): Ordering
impl Comparable.compare
struct Time
Section titled “struct Time”struct Time
opaque — construction surface is private to its defining module
A time-of-day — hour/minute/second/nanosecond, no date, no zone.
Construct via Time.new(h, m, s, ns) (validating), Time.parse,
or the Time"…" typed literal. Components reachable via
hour/minute/second/nanosecond (or the TimeParts interface).
Time.new
Section titled “Time.new”fn new(hour: Int, minute: Int, second: Int = 0, nanosecond: Int = 0): Result<Time, Error>
type function on Time
Construct a Time, validating each component (hour 0..=23,
minute/second 0..=59, nanosecond 0..=999_999_999).
Time.parse
Section titled “Time.parse”fn parse(s: String): Result<Time, Error>
type function on Time
Parse a time-of-day string (HH:MM:SS or HH:MM:SS.fff…).
Interactive Tests
assert Time.parse("08:30:00") == Time"08:30:00"
assert Err(Error.InvalidFormat(_msg)) = Time.parse("nope")
Time.between
Section titled “Time.between”fn between(earlier: Time, later: Time): Duration
type function on Time
Interactive Tests
assert Time.between(try Time"08:30:00", try Time"08:33:00") == Duration.minutes(
3
)
Time.from_fragments
Section titled “Time.from_fragments”impl Literal
fn from_fragments(fragments: List<Fragment<String>>): Result<Time, Error>
impl Literal.from_fragments
Time.to_string
Section titled “Time.to_string”impl Display
fn to_string(t: Time): String
impl Display.to_string
ISO time string. Sub-second precision renders as a trailing .fff…
only when nonzero (so 09:30:00, not 09:30:00.000).
Time.inspect
Section titled “Time.inspect”impl Debug
fn inspect(t: Time): String
impl Debug.inspect
Time.hour
Section titled “Time.hour”impl TimeParts
fn hour(value: Time): Int
impl TimeParts.hour
Time.minute
Section titled “Time.minute”impl TimeParts
fn minute(value: Time): Int
impl TimeParts.minute
Time.second
Section titled “Time.second”impl TimeParts
fn second(value: Time): Int
impl TimeParts.second
Time.nanosecond
Section titled “Time.nanosecond”impl TimeParts
fn nanosecond(value: Time): Int
impl TimeParts.nanosecond
Time.add
Section titled “Time.add”impl Add
fn add(lhs: Time, rhs: Duration): Time
impl Add.add
Add an exact Duration, wrapping around midnight.
Interactive Tests
assert try Time"08:33:00" + Duration.minutes(3) == try Time"08:36:00"
Time.subtract
Section titled “Time.subtract”impl Subtract
fn subtract(lhs: Time, rhs: Duration): Time
impl Subtract.subtract
Subtract an exact Duration, wrapping around midnight.
Interactive Tests
assert try Time"08:36:00" - Duration.minutes(3) == try Time"08:33:00"
Time.equal?
Section titled “Time.equal?”impl Equatable
fn equal?(a: Time, b: Time): Bool
impl Equatable.equal?
Time.hash
Section titled “Time.hash”impl Hashable
fn hash(value: Time): Int
impl Hashable.hash
Time.compare
Section titled “Time.compare”impl Comparable
fn compare(a: Time, b: Time): Ordering
impl Comparable.compare
struct NaiveDateTime
Section titled “struct NaiveDateTime”struct NaiveDateTime
opaque — construction surface is private to its defining module
A naive date+time — a wall-clock reading like 2026-05-04T14:30:00,
with no zone or offset. Looks like a complete timestamp but
isn’t: a wall reading without a zone doesn’t name a real moment in
history. Reach for DateTime (IANA-zoned) when you need a real
instant; reach for NaiveDateTime only when the value is genuinely
a wall reading (calendar templates, schedule patterns, dates with a
“local time of day” that will be resolved into a zone later).
NaiveDateTime.at
Section titled “NaiveDateTime.at”fn at(d: Date, t: Time): NaiveDateTime
type function on NaiveDateTime
Combine a Date and a Time. Both parts are already valid, so
this is infallible.
NaiveDateTime.at_midnight
Section titled “NaiveDateTime.at_midnight”fn at_midnight(d: Date): NaiveDateTime
type function on NaiveDateTime
A NaiveDateTime at midnight (00:00:00) on the given date.
NaiveDateTime.to_date
Section titled “NaiveDateTime.to_date”fn to_date(dt: NaiveDateTime): Date
type function on NaiveDateTime
The date component.
NaiveDateTime.to_time
Section titled “NaiveDateTime.to_time”fn to_time(dt: NaiveDateTime): Time
type function on NaiveDateTime
The time-of-day component.
NaiveDateTime.new
Section titled “NaiveDateTime.new”fn new(year: Int, month: Int, day: Int, hour: Int, minute: Int, second: Int = 0, nanosecond: Int = 0): Result<NaiveDateTime, Error>
type function on NaiveDateTime
Construct from seven integers, validating each component AND the year/month/day combination.
NaiveDateTime.parse
Section titled “NaiveDateTime.parse”fn parse(s: String): Result<NaiveDateTime, Error>
type function on NaiveDateTime
Parse an ISO naive datetime string (YYYY-MM-DDTHH:MM:SS[.fff…]).
Allows a single space instead of T between the date and time.
NaiveDateTime.between
Section titled “NaiveDateTime.between”fn between(earlier: NaiveDateTime, later: NaiveDateTime): Duration
type function on NaiveDateTime
Difference (later − earlier), computed as if both were UTC wall-readings.
NaiveDateTime.from_fragments
Section titled “NaiveDateTime.from_fragments”impl Literal
fn from_fragments(fragments: List<Fragment<String>>): Result<NaiveDateTime, Error>
impl Literal.from_fragments
NaiveDateTime.to_string
Section titled “NaiveDateTime.to_string”impl Display
fn to_string(dt: NaiveDateTime): String
impl Display.to_string
ISO datetime string (YYYY-MM-DDTHH:MM:SS[.fff…]).
NaiveDateTime.inspect
Section titled “NaiveDateTime.inspect”impl Debug
fn inspect(dt: NaiveDateTime): String
impl Debug.inspect
NaiveDateTime.year
Section titled “NaiveDateTime.year”impl DateParts
fn year(value: NaiveDateTime): Int
impl DateParts.year
NaiveDateTime.month
Section titled “NaiveDateTime.month”impl DateParts
fn month(value: NaiveDateTime): Int
impl DateParts.month
NaiveDateTime.day
Section titled “NaiveDateTime.day”impl DateParts
fn day(value: NaiveDateTime): Int
impl DateParts.day
NaiveDateTime.hour
Section titled “NaiveDateTime.hour”impl TimeParts
fn hour(value: NaiveDateTime): Int
impl TimeParts.hour
NaiveDateTime.minute
Section titled “NaiveDateTime.minute”impl TimeParts
fn minute(value: NaiveDateTime): Int
impl TimeParts.minute
NaiveDateTime.second
Section titled “NaiveDateTime.second”impl TimeParts
fn second(value: NaiveDateTime): Int
impl TimeParts.second
NaiveDateTime.nanosecond
Section titled “NaiveDateTime.nanosecond”impl TimeParts
fn nanosecond(value: NaiveDateTime): Int
impl TimeParts.nanosecond
NaiveDateTime.add
Section titled “NaiveDateTime.add”impl Add
fn add(lhs: NaiveDateTime, rhs: Civil.Years): NaiveDateTime
impl Add.add
Add whole calendar years, clamping leap days when needed.
NaiveDateTime.subtract
Section titled “NaiveDateTime.subtract”impl Subtract
fn subtract(lhs: NaiveDateTime, Civil.Years(n)): NaiveDateTime
impl Subtract.subtract
Subtract whole calendar years, clamping leap days when needed.
NaiveDateTime.equal?
Section titled “NaiveDateTime.equal?”impl Equatable
fn equal?(a: NaiveDateTime, b: NaiveDateTime): Bool
impl Equatable.equal?
NaiveDateTime.hash
Section titled “NaiveDateTime.hash”impl Hashable
fn hash(value: NaiveDateTime): Int
impl Hashable.hash
NaiveDateTime.compare
Section titled “NaiveDateTime.compare”impl Comparable
fn compare(a: NaiveDateTime, b: NaiveDateTime): Ordering
impl Comparable.compare
struct OffsetDateTime
Section titled “struct OffsetDateTime”struct OffsetDateTime
opaque — construction surface is private to its defining module
A date+time anchored at a fixed UTC offset (-05:00), with no DST
awareness. The right type for ISO-8601 timestamps from APIs that
include an offset but not a zone (2026-05-04T14:30:00-05:00).
For DST-aware semantics, reach for DateTime instead — DateTime
is the recommended default for real moments-in-time; an
OffsetDateTime deliberately can’t tell you which zone you were
in, so converting back to DateTime requires re-naming the zone.
Equality and ordering are instant-only: two OffsetDateTime
values with the same underlying nanos but different offsets are
equal (they’re the same moment in real history; the offset is
display metadata). Construct via OffsetDateTime.with_offset(naive, offset), OffsetDateTime.from_instant(instant, offset),
OffsetDateTime.parse, or the OffsetDateTime"…" typed literal.
OffsetDateTime.with_offset
Section titled “OffsetDateTime.with_offset”fn with_offset(dt: NaiveDateTime, offset: Duration): Result<OffsetDateTime, Error>
type function on OffsetDateTime
Combine a NaiveDateTime wall-reading with a fixed UTC offset.
Returns Err(.InvalidValue(...)) if the offset is outside the
IANA-acceptable range (±18:00).
OffsetDateTime.from_instant
Section titled “OffsetDateTime.from_instant”fn from_instant(i: Instant, offset: Duration): OffsetDateTime
type function on OffsetDateTime
Attach a fixed offset to an absolute Instant. Always total —
every instant has a representation at every fixed offset.
OffsetDateTime.parse
Section titled “OffsetDateTime.parse”fn parse(s: String): Result<OffsetDateTime, Error>
type function on OffsetDateTime
Parse an ISO-8601 timestamp with offset suffix
(YYYY-MM-DDTHH:MM:SS[.fff…][±HH:MM|Z]).
OffsetDateTime.between
Section titled “OffsetDateTime.between”fn between(earlier: OffsetDateTime, later: OffsetDateTime): Duration
type function on OffsetDateTime
OffsetDateTime.from_fragments
Section titled “OffsetDateTime.from_fragments”impl Literal
fn from_fragments(fragments: List<Fragment<String>>): Result<OffsetDateTime, Error>
impl Literal.from_fragments
OffsetDateTime.to_string
Section titled “OffsetDateTime.to_string”impl Display
fn to_string(odt: OffsetDateTime): String
impl Display.to_string
ISO-8601 datetime + offset string (YYYY-MM-DDTHH:MM:SS[.fff…]±HH:MM).
OffsetDateTime.inspect
Section titled “OffsetDateTime.inspect”impl Debug
fn inspect(odt: OffsetDateTime): String
impl Debug.inspect
OffsetDateTime.year
Section titled “OffsetDateTime.year”impl DateParts
fn year(value: OffsetDateTime): Int
impl DateParts.year
OffsetDateTime.month
Section titled “OffsetDateTime.month”impl DateParts
fn month(value: OffsetDateTime): Int
impl DateParts.month
OffsetDateTime.day
Section titled “OffsetDateTime.day”impl DateParts
fn day(value: OffsetDateTime): Int
impl DateParts.day
OffsetDateTime.hour
Section titled “OffsetDateTime.hour”impl TimeParts
fn hour(value: OffsetDateTime): Int
impl TimeParts.hour
OffsetDateTime.minute
Section titled “OffsetDateTime.minute”impl TimeParts
fn minute(value: OffsetDateTime): Int
impl TimeParts.minute
OffsetDateTime.second
Section titled “OffsetDateTime.second”impl TimeParts
fn second(value: OffsetDateTime): Int
impl TimeParts.second
OffsetDateTime.nanosecond
Section titled “OffsetDateTime.nanosecond”impl TimeParts
fn nanosecond(value: OffsetDateTime): Int
impl TimeParts.nanosecond
OffsetDateTime.to_instant
Section titled “OffsetDateTime.to_instant”impl Anchored
fn to_instant(value: OffsetDateTime): Instant
impl Anchored.to_instant
OffsetDateTime.offset
Section titled “OffsetDateTime.offset”impl Anchored
fn offset(value: OffsetDateTime): Duration
impl Anchored.offset
OffsetDateTime.add
Section titled “OffsetDateTime.add”impl Add
fn add(lhs: OffsetDateTime, rhs: Duration): OffsetDateTime
impl Add.add
Add an exact Duration.
OffsetDateTime.subtract
Section titled “OffsetDateTime.subtract”impl Subtract
fn subtract(lhs: OffsetDateTime, rhs: Duration): OffsetDateTime
impl Subtract.subtract
Subtract an exact Duration.
OffsetDateTime.equal?
Section titled “OffsetDateTime.equal?”impl Equatable
fn equal?(a: OffsetDateTime, b: OffsetDateTime): Bool
impl Equatable.equal?
OffsetDateTime.hash
Section titled “OffsetDateTime.hash”impl Hashable
fn hash(value: OffsetDateTime): Int
impl Hashable.hash
OffsetDateTime.compare
Section titled “OffsetDateTime.compare”impl Comparable
fn compare(a: OffsetDateTime, b: OffsetDateTime): Ordering
impl Comparable.compare
struct DateTime
Section titled “struct DateTime”struct DateTime
opaque — construction surface is private to its defining module
A date+time anchored to an IANA time zone (America/New_York),
fully DST-aware. The default type for real moments in history —
short name, attractive-by-design, the right choice for almost
every timestamp a program handles. Backed by time/tzdata
embedded in the runtime, so IANA-zone lookups work on every
host without external tzdata.
Equality and ordering are instant-only: same moment in two different zones compares equal. The zone is display metadata, not identity.
Construct via DateTime.in_zone(naive, zone, mode) (the fallible
wall→instant projection — see Disambiguation for the gap/fold
modes), DateTime.from_instant_in(instant, zone) (always total),
DateTime.now_in(zone) (the system clock projected into a zone),
DateTime.parse, or the DateTime"…" typed literal (RFC 9557
bracket form).
DateTime.in_zone
Section titled “DateTime.in_zone”fn in_zone(dt: NaiveDateTime, zone: String, mode: Disambiguation): Result<DateTime, Error>
type function on DateTime
Project a naive wall-reading into an IANA zone, returning a
DateTime anchored at the resolved instant. Fails on
UnknownZone always, and — only when mode = Reject — on
Nonexistent (gap) or Ambiguous (fold). The three resolving
modes (Compatible/Earlier/Later) always land on an instant.
DateTime.from_instant_in
Section titled “DateTime.from_instant_in”fn from_instant_in(i: Instant, zone: String): Result<DateTime, Error>
type function on DateTime
Project an absolute Instant into an IANA zone. Always total
once the zone is known. Fails only on UnknownZone.
DateTime.now_in
Section titled “DateTime.now_in”fn now_in(zone: String): Result<DateTime, Error>
type function on DateTime
Read the current wall clock and project into a zone. Sugar for
Instant.now() |> DateTime.from_instant_in(zone).
DateTime.to_offset
Section titled “DateTime.to_offset”fn to_offset(d: DateTime): OffsetDateTime
type function on DateTime
Freeze the zone’s current offset at this instant — produces an
OffsetDateTime carrying the offset effective at the DateTime’s
instant. Lossy: the result no longer remembers the IANA zone.
DateTime.with_zone
Section titled “DateTime.with_zone”fn with_zone(d: DateTime, zone: String): Result<DateTime, Error>
type function on DateTime
Same instant, different IANA zone — re-project the wall reading
through a new zone. Fails only on UnknownZone.
DateTime.parse
Section titled “DateTime.parse”fn parse(s: String): Result<DateTime, Error>
type function on DateTime
Parse an RFC 9557 datetime-with-zone string
(YYYY-MM-DDTHH:MM:SS[.fff…]±HH:MM[Zone/Name]). The IANA-zone
bracket suffix is required — bare offset forms parse via
OffsetDateTime.parse instead.
DateTime.between
Section titled “DateTime.between”fn between(earlier: DateTime, later: DateTime): Duration
type function on DateTime
DateTime.from_fragments
Section titled “DateTime.from_fragments”impl Literal
fn from_fragments(fragments: List<Fragment<String>>): Result<DateTime, Error>
impl Literal.from_fragments
DateTime.to_string
Section titled “DateTime.to_string”impl Display
fn to_string(d: DateTime): String
impl Display.to_string
RFC 9557 datetime+zone string.
DateTime.inspect
Section titled “DateTime.inspect”impl Debug
fn inspect(d: DateTime): String
impl Debug.inspect
DateTime.year
Section titled “DateTime.year”impl DateParts
fn year(value: DateTime): Int
impl DateParts.year
DateTime.month
Section titled “DateTime.month”impl DateParts
fn month(value: DateTime): Int
impl DateParts.month
DateTime.day
Section titled “DateTime.day”impl DateParts
fn day(value: DateTime): Int
impl DateParts.day
DateTime.hour
Section titled “DateTime.hour”impl TimeParts
fn hour(value: DateTime): Int
impl TimeParts.hour
DateTime.minute
Section titled “DateTime.minute”impl TimeParts
fn minute(value: DateTime): Int
impl TimeParts.minute
DateTime.second
Section titled “DateTime.second”impl TimeParts
fn second(value: DateTime): Int
impl TimeParts.second
DateTime.nanosecond
Section titled “DateTime.nanosecond”impl TimeParts
fn nanosecond(value: DateTime): Int
impl TimeParts.nanosecond
DateTime.to_instant
Section titled “DateTime.to_instant”impl Anchored
fn to_instant(value: DateTime): Instant
impl Anchored.to_instant
DateTime.offset
Section titled “DateTime.offset”impl Anchored
fn offset(value: DateTime): Duration
impl Anchored.offset
DateTime.add
Section titled “DateTime.add”impl Add
fn add(lhs: DateTime, rhs: Duration): DateTime
impl Add.add
Add an exact Duration.
DateTime.subtract
Section titled “DateTime.subtract”impl Subtract
fn subtract(lhs: DateTime, rhs: Duration): DateTime
impl Subtract.subtract
Subtract an exact Duration.
DateTime.equal?
Section titled “DateTime.equal?”impl Equatable
fn equal?(a: DateTime, b: DateTime): Bool
impl Equatable.equal?
DateTime.hash
Section titled “DateTime.hash”impl Hashable
fn hash(value: DateTime): Int
impl Hashable.hash
DateTime.compare
Section titled “DateTime.compare”impl Comparable
fn compare(a: DateTime, b: DateTime): Ordering
impl Comparable.compare
enum Disambiguation
Section titled “enum Disambiguation”enum Disambiguation { Compatible Earlier Later Reject }
How DateTime.in_zone resolves wall-clock readings that fall in a DST
spring-forward gap (the wall time never exists — clocks
jumped over it) or a fall-back fold (the wall time exists
twice — clocks rolled back). Modeled on Temporal’s
disambiguation option.
The four modes:
-
Compatible(the default — pass nomodeargument and you get this) — “do the obvious thing”, always returning an instant. In a fold, picks the earlier instant (the pre-transition occurrence). In a gap, advances forward through the gap so02:30becomes03:30post-transition. Matches the intuition that “30 minutes after the gap started” means “30 minutes of wall time after the gap’s start”. Reach for this unless you have a specific reason not to. -
Earlier— pick the earlier instant in both transitions. In a fold, same asCompatible(the pre-transition occurrence). In a gap, the instant just before the transition:02:30in a spring-forward gap resolves to01:30pre-transition. Useful when “earlier is safer” — e.g. scheduling a deadline or notification where the earlier interpretation prevents a missed event. -
Later— pick the later instant in both transitions. In a fold, the post-transition occurrence (01:30EST after the fall-back). In a gap, the post-transition instant (same asCompatiblefor gaps). Useful when “later is safer” — e.g. expirations and grace periods, where the later interpretation gives the user the benefit of the doubt. -
Reject— surface DST anomalies asErrinstead of resolving silently:Err(Ambiguous ...)for folds,Err(Nonexistent ...)for gaps. The strict mode for code that should never silently disambiguate — typically when the wall reading came from a user (UI form, API request) and the right answer is to bounce the ambiguity back to them.
Disambiguation.inspect
Section titled “Disambiguation.inspect”impl Debug
fn inspect(value: Disambiguation): String
impl Debug.inspect