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.
DateParts.year
Section titled “DateParts.year”fn year(value: self): Int
interface DateParts
DateParts.month
Section titled “DateParts.month”fn month(value: self): Int
interface DateParts
DateParts.day
Section titled “DateParts.day”fn day(value: self): Int
interface DateParts
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.
TimeParts.hour
Section titled “TimeParts.hour”fn hour(value: self): Int
interface TimeParts
TimeParts.minute
Section titled “TimeParts.minute”fn minute(value: self): Int
interface TimeParts
TimeParts.second
Section titled “TimeParts.second”fn second(value: self): Int
interface TimeParts
TimeParts.nanosecond
Section titled “TimeParts.nanosecond”fn nanosecond(value: self): Int
interface TimeParts
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.
Anchored.to_instant
Section titled “Anchored.to_instant”fn to_instant(value: self): Instant
interface Anchored
Anchored.offset
Section titled “Anchored.offset”fn offset(value: self): Duration
interface Anchored
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.
Interactive Tests
assert Date.new(2026, 5, 4) == Date"2026-05-04"
assert Err(Error.InvalidValue(_msg)) = Date.new(2026, 2, 30)
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.
Interactive Tests
assert Date.parse("2026-05-04") == Date"2026-05-04"
assert Err(Error.InvalidFormat(_msg)) = Date.parse("05/04/2026")
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.)
Interactive Tests
assert Date.days_between(try Date"2026-05-04", try Date"2026-05-07") == 3
assert Date.days_between(try Date"2026-05-07", try Date"2026-05-04") == -3
Date.from_fragments
Section titled “Date.from_fragments”impl Literal
fn from_fragments(fragments: List<Fragment<String>>): Result<Date, Error>
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).
Interactive Tests
assert Time.new(8, 30) == Time"08:30:00"
assert Time.new(8, 30, 15, 250_000_000) == Time"08:30:15.25"
assert Err(Error.InvalidValue(_msg)) = Time.new(24, 0)
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
Exact duration from earlier to later, measured within one civil day.
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>
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.
Interactive Tests
assert NaiveDateTime.at(
try Date"2026-05-04",
try Time"14:30:00",
) == try NaiveDateTime"2026-05-04T14:30:00"
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.
Interactive Tests
assert NaiveDateTime.at_midnight(
try Date"2026-05-04"
) == try NaiveDateTime"2026-05-04T00:00:00"
NaiveDateTime.to_date
Section titled “NaiveDateTime.to_date”fn to_date(dt: NaiveDateTime): Date
type function on NaiveDateTime
The date component.
Interactive Tests
assert NaiveDateTime.to_date(
try NaiveDateTime"2026-05-04T14:30:00"
) == try Date"2026-05-04"
NaiveDateTime.to_time
Section titled “NaiveDateTime.to_time”fn to_time(dt: NaiveDateTime): Time
type function on NaiveDateTime
The time-of-day component.
Interactive Tests
assert NaiveDateTime.to_time(
try NaiveDateTime"2026-05-04T14:30:00"
) == try Time"14:30:00"
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.
Interactive Tests
assert NaiveDateTime.new(
2026,
5,
4,
14,
30,
) == NaiveDateTime"2026-05-04T14:30:00"
assert Err(Error.InvalidValue(_msg)) = NaiveDateTime.new(2026, 2, 30, 12, 0)
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.
Interactive Tests
assert NaiveDateTime.parse(
"2026-05-04T14:30:00"
) == NaiveDateTime"2026-05-04T14:30:00"
assert NaiveDateTime.parse(
"2026-05-04 14:30:00"
) == NaiveDateTime"2026-05-04T14:30:00"
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.
Interactive Tests
assert NaiveDateTime.between(
try NaiveDateTime"2026-05-04T09:00:00",
try NaiveDateTime"2026-05-04T11:30:00",
) == Duration.minutes(150)
NaiveDateTime.from_fragments
Section titled “NaiveDateTime.from_fragments”impl Literal
fn from_fragments(fragments: List<Fragment<String>>): Result<NaiveDateTime, Error>
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).
Interactive Tests
assert OffsetDateTime.with_offset(
try NaiveDateTime"2026-05-04T09:00:00",
Duration.hours(-5),
) == OffsetDateTime"2026-05-04T09:00:00-05: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.
Interactive Tests
assert OffsetDateTime.from_instant(
Instant.from_seconds(0),
Duration.hours(0),
) == try OffsetDateTime"1970-01-01T00:00:00Z"
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]).
Interactive Tests
assert OffsetDateTime.parse(
"2026-05-04T14:30:00-05:00"
) == OffsetDateTime"2026-05-04T14:30:00-05:00"
assert Err(Error.InvalidFormat(_msg)) = OffsetDateTime.parse(
"2026-05-04T14:30:00"
)
OffsetDateTime.between
Section titled “OffsetDateTime.between”fn between(earlier: OffsetDateTime, later: OffsetDateTime): Duration
type function on OffsetDateTime
Exact duration between two fixed-offset date-times, comparing their underlying instants rather than their displayed wall readings.
Interactive Tests
assert OffsetDateTime.between(
try OffsetDateTime"2026-05-04T14:30:00-05:00",
try OffsetDateTime"2026-05-04T20:30:00+00:00",
) == Duration.hours(1)
OffsetDateTime.from_fragments
Section titled “OffsetDateTime.from_fragments”impl Literal
fn from_fragments(fragments: List<Fragment<String>>): Result<OffsetDateTime, Error>
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.
Interactive Tests
assert DateTime.in_zone(
try NaiveDateTime"2026-06-15T12:00:00",
"America/New_York",
) == DateTime"2026-06-15T12:00:00-04:00[America/New_York]"
assert Err(Error.UnknownZone(_zone)) = DateTime.in_zone(
try NaiveDateTime"2026-06-15T12:00:00",
"Mars/Base",
)
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.
Interactive Tests
assert DateTime.from_instant_in(
Instant.from_seconds(0),
"UTC",
) == DateTime"1970-01-01T00:00:00Z[UTC]"
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).
Interactive Tests
assert Err(Error.UnknownZone(_zone)) = DateTime.now_in("Mars/Base")
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.
Interactive Tests
assert DateTime.to_offset(
try DateTime"2026-06-15T12:00:00-04:00[America/New_York]"
) == try OffsetDateTime"2026-06-15T12:00:00-04:00"
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.
Interactive Tests
assert DateTime.with_zone(
try DateTime"2026-06-15T12:00:00-04:00[America/New_York]",
"Europe/Paris",
) == DateTime"2026-06-15T18:00:00+02:00[Europe/Paris]"
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.
Interactive Tests
assert DateTime.parse(
"2026-06-15T12:00:00-04:00[America/New_York]"
) == DateTime"2026-06-15T12:00:00-04:00[America/New_York]"
assert Err(Error.InvalidFormat(_msg)) = DateTime.parse(
"2026-06-15T12:00:00-04:00"
)
DateTime.between
Section titled “DateTime.between”fn between(earlier: DateTime, later: DateTime): Duration
type function on DateTime
Exact duration between two zoned date-times, comparing their underlying instants rather than their displayed wall readings.
Interactive Tests
assert DateTime.between(
try DateTime"2026-06-15T12:00:00-04:00[America/New_York]",
try DateTime"2026-06-15T18:30:00+02:00[Europe/Paris]",
) == Duration.minutes(30)
DateTime.from_fragments
Section titled “DateTime.from_fragments”impl Literal
fn from_fragments(fragments: List<Fragment<String>>): Result<DateTime, Error>
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