temporal

    An implementation of ECMAScript Temporal: calendar and time-zone aware dates, times, instants and durations. Ported from the Rust temporal_rs.

    date
    time
    calendar
    timezone
    duration
    temporal
    Download zip
    Version
    0.1.1
    License
    Apache-2.0
    Last updated
    14 days ago
    Downloads
    33

    #temporal

    A MoonBit implementation of ECMAScript Temporal, ported from temporal_rs — the Rust implementation that backs Temporal in Boa, Kiesel and V8.

    Temporal replaces Date with a set of types that each say exactly what they mean: a calendar date with no time zone, a wall-clock time with no date, an exact instant, a span of time. Operations that are ambiguous in the real world — "one month after January 31st", "how long is a day" — are made explicit rather than guessed at.

    ///|
    test "the core types" {
    // A calendar date: no time, no time zone.
    let date = @temporal.PlainDate::try_new(2025, 3, 1)
    inspect(date, content="2025-03-01")

    // A wall-clock time: no date, no time zone.
    let time = @temporal.PlainTime::try_new(hour=11, minute=16, second=10)
    inspect(time, content="11:16:10")

    // The two combined.
    inspect(date.to_plain_date_time(time~), content="2025-03-01T11:16:10")

    // An exact point on the timeline.
    inspect(
    @temporal.Instant::of_string("2025-03-01T11:16:10Z"),
    content="2025-03-01T11:16:10Z",
    )

    // A span of time, with no anchor.
    inspect(@temporal.Duration::of(hours=2, minutes=30), content="PT2H30M")
    }

    #Installation

    moon add marianoguerra/temporal

    Then add it to the importing package's moon.pkg:

    import { "marianoguerra/temporal", }

    #What it covers

    TypeWhat it isCalendarTime zone
    PlainDateA calendar dateyesno
    PlainTimeA wall-clock timenono
    PlainDateTimeA calendar date and wall-clock timeyesno
    PlainYearMonthA year and month, no dayyesno
    PlainMonthDayA month and day, no yearyesno
    InstantAn exact point on the timelinenono
    ZonedDateTimeAn exact point, read in a zoneyesyes
    DurationA span of timenono

    Each supports construction, field access, with_fields, add/subtract, until/since, round where it applies, comparison, and RFC 9557 parsing and formatting.

    #Calendar arithmetic is not day counting

    Adding a month means walking the calendar, so the result depends on where you start and on how long the target month is.

    ///|
    test "month arithmetic is calendar-aware" {
    let one_month = @temporal.Duration::of(months=1)

    // February has no 31st, so the day is constrained to the end of the month —
    // and how far depends on whether it is a leap year.
    inspect(
    @temporal.PlainDate::try_new(2023, 1, 31).add(one_month),
    content="2023-02-28",
    )
    inspect(
    @temporal.PlainDate::try_new(2024, 1, 31).add(one_month),
    content="2024-02-29",
    )

    // `reject` turns the constraint into an error instead.
    let jan31 = @temporal.PlainDate::try_new(2023, 1, 31)
    try jan31.add(one_month, overflow=Reject) |> ignore catch {
    _ => ()
    } noraise {
    _ => fail("expected the constrained day to be rejected")
    }
    }

    Because months are not a fixed length, the same gap between two dates has several equally correct descriptions. You choose which by naming the largest unit.

    ///|
    test "a difference is expressed in the units you ask for" {
    let start = @temporal.PlainDate::try_new(2019, 1, 1)
    let end = @temporal.PlainDate::try_new(2023, 9, 15)
    let with_unit = (unit : @temporal.DateTimeUnit) => {
    start.until(
    end,
    settings=@temporal.DifferenceSettings::new(largest_unit=unit),
    )
    }
    inspect(with_unit(Year), content="P4Y8M14D")
    inspect(with_unit(Month), content="P56M14D")
    inspect(with_unit(Day), content="P1718D")
    }

    #Durations

    A duration is unanchored, so its calendar components cannot be reduced to time components without a reference point.

    ///|
    test "durations round and total against a reference point" {
    let duration = @temporal.Duration::of_string("P1Y2M3DT4H5M6.789S")
    inspect(duration.years(), content="1")
    inspect(duration.months(), content="2")

    // Time-only durations need no reference.
    inspect(
    @temporal.Duration::of(minutes=45).add(@temporal.Duration::of(hours=1)),
    content="PT1H45M",
    )
    inspect(
    @temporal.Duration::of(hours=1, minutes=30).total(
    Minute,
    @temporal.utc_only_provider,
    ),
    content="90",
    )

    // Calendar units need one, because their length depends on where they start.
    // From 2020-01-01, 45 days is one month and 14 days, and 14 is less than
    // half of February's 29, so it rounds down.
    let relative = @temporal.PlainDate::try_new(2020, 1, 1)
    inspect(
    @temporal.Duration::of(days=45).round(
    @temporal.RoundingOptions::new(smallest_unit=Month),
    @temporal.utc_only_provider,
    relative_to=DateRelative(relative),
    ),
    content="P1M",
    )
    }

    #Rounding

    Every rounding operation takes a unit, an increment, and one of the nine ECMAScript rounding modes.

    ///|
    test "rounding" {
    let time = @temporal.PlainTime::try_new(hour=12, minute=34, second=56)
    inspect(
    time.round(@temporal.RoundingOptions::new(smallest_unit=Minute)),
    content="12:35:00",
    )
    inspect(
    time.round(
    @temporal.RoundingOptions::new(smallest_unit=Minute, rounding_mode=Floor),
    ),
    content="12:34:00",
    )
    // The increment must divide its unit evenly.
    inspect(
    time.round(
    @temporal.RoundingOptions::new(
    smallest_unit=Minute,
    increment=@temporal.RoundingIncrement::try_new(15),
    ),
    ),
    content="12:30:00",
    )
    }

    #Parsing and formatting

    Strings are RFC 9557: ISO 8601 plus bracketed annotations for the time zone and the calendar. An invalid string raises a RangeError, as the specification requires.

    ///|
    test "RFC 9557 strings" {
    inspect(
    @temporal.PlainDateTime::of_string("2025-03-01T11:16:10.5[u-ca=iso8601]"),
    content="2025-03-01T11:16:10.5",
    )
    // A `Z` designator asserts an exact instant, so a plain type rejects it.
    try
    @temporal.PlainDateTime::of_string("2025-03-01T11:16:10Z") |> ignore
    catch {
    err => assert_true(err is @temporal.RangeError(_))
    } noraise {
    _ => fail("expected the UTC designator to be rejected")
    }
    }

    #Time zones

    A ZonedDateTime needs a TimeZoneProvider to resolve a named IANA zone, because the transition rules are far larger than a date library should embed. Fixed offsets and UTC work out of the box through utc_only_provider; supplying IANA data means implementing the TimeZoneProvider trait.

    ///|
    test "zoned date-times over a fixed offset" {
    let zdt = @temporal.ZonedDateTime::of_string(
    "2025-03-01T11:16:10Z[UTC]", @temporal.utc_only_provider,
    )
    inspect(zdt.hour(), content="11")

    // Moving to another zone keeps the instant and changes the wall clock.
    let chicago_offset = @temporal.TimeZone::OffsetZone(
    @temporal.UtcOffset::from_minutes(-360),
    )
    let shifted = zdt.with_time_zone(chicago_offset, @temporal.utc_only_provider)
    inspect(shifted.hour(), content="5")
    assert_eq(shifted.epoch_nanoseconds(), zdt.epoch_nanoseconds())
    }

    #Errors

    Every fallible operation raises TemporalError, whose variants name the JavaScript error an engine would throw, so an embedder can map them directly.

    ///|
    test "errors carry an ECMAScript error kind" {
    try @temporal.PlainDate::try_new(2023, 2, 30) |> ignore catch {
    err => {
    assert_true(err is @temporal.RangeError(_))
    inspect(err.kind_name(), content="RangeError")
    }
    } noraise {
    _ => fail("expected February 30th to be rejected")
    }
    }

    #Scope and known differences from temporal_rs

    • Only the ISO 8601 calendar is implemented. The Calendar type exists and round-trips through parsing and toString annotations, but a non-ISO identifier such as gregory or japanese raises a RangeError explaining that it is recognized but unimplemented. temporal_rs supports these through ICU4X.
    • No time zone database is embedded. Fixed offsets and UTC work directly; named IANA zones need a TimeZoneProvider implementation. temporal_rs ships compiled TZif data behind a feature flag.
    • No access to the host clock. There is no Now; construct an Instant from epoch nanoseconds supplied by the caller.

    Everything else — the ISO calendar arithmetic, duration normalization and relative rounding, the RFC 9557 parser and formatter, and the full rounding and difference option surface — is a direct port and is checked against temporal_rs case for case.

    #Testing

    The suite has four layers, all run by moon test:

    • Unit tests (temporal_test.mbt) cover the named edge cases: range limits, month-length interactions, and the regressions temporal_rs carries tests for.
    • Property tests (property_test.mbt, int128/int128_test.mbt) assert laws rather than values — round trips, symmetries, idempotence — using the seeded generator in internal/prop. The 128-bit integer type is checked against BigInt as an oracle, including that its Double conversion is correctly rounded.
    • Conformance tests (conformance_cases_test.mbt) replay several thousand operations whose expected results were produced by temporal_rs itself. The file is generated, so moon test re-checks this port against the reference implementation without needing Rust installed.
    • Differential fuzzing (tools/fuzz.py) generates fresh random cases on every run and compares them against the Rust oracle live.

    Regenerating the conformance corpus, or fuzzing, needs Rust:

    cargo build --release --manifest-path tools/oracle/Cargo.toml # Refresh the frozen corpus. python3 tools/gen_conformance.py # Fuzz against the oracle; each round uses a fresh seed. python3 tools/fuzz.py --rounds 20 --count 3000

    #References

    #License

    Apache-2.0

    TimeZoneProvider

    pub trait TimeZoneProvider {
    fn offset_nanoseconds_for(Self, String,
    Int128
    ) -> Int64 raise TemporalError
    fn candidates_for_local_datetime(Self, String, IsoDateTime) -> CandidateEpochNanoseconds raise TemporalError
    }

    Supplies the transition data for named IANA time zones.

    Implement this to plug in a TZif database or any other source of zone rules; the library itself embeds none.

    TemporalError

    pub(all) suberror TemporalError {
    Generic(String)
    TypeError(String)
    RangeError(String)
    SyntaxError(String)
    AssertError(String)
    } derive(Eq)

    The error type raised by every fallible Temporal operation.

    The variants mirror the ECMAScript exception that a JavaScript engine would surface for the same failure, which is what temporal_rs models with its ErrorKind. Keeping that distinction lets an engine embedding this library map a failure onto the right JavaScript error constructor.

    TemporalError::kind_name

    fn TemporalError::kind_name(self : TemporalError) -> String

    Returns the ECMAScript error constructor name for this failure.

    TemporalError::message

    fn TemporalError::message(self : TemporalError) -> String

    Returns the human-readable description of the failure.

    TemporalError::to_string

    fn TemporalError::to_string(self : TemporalError) -> String

    Calendar

    pub(all) enum Calendar {
    ISO
    } derive(Eq,
    Debug
    )

    The calendar system a date is interpreted in.

    This port implements the ISO 8601 calendar. The type exists as a distinct value rather than being elided because calendar identity is observable through parsing, toString annotations, and the cross-calendar mismatch checks that arithmetic and comparison perform.

    impl Default for Calendar
    impl Show for Calendar

    Calendar::identifier

    fn Calendar::identifier(self : Calendar) -> String

    Returns the canonical calendar identifier.

    Calendar::of_string

    fn Calendar::of_string(s : String) -> Calendar raise TemporalError

    Parses a calendar identifier.

    Identifiers are matched case-insensitively, as the Temporal specification requires. Calendars other than iso8601 are rejected: they are recognised as valid Temporal calendars but are not implemented here.

    test {
    inspect(@temporal.Calendar::of_string("ISO8601"), content="iso8601")
    }

    CandidateEpochNanoseconds

    The possible instants a wall-clock time maps to in a time zone.

    A time in a spring-forward gap has none, a time in a fall-back overlap has two, and every other time has exactly one.

    DateDuration

    pub struct DateDuration {
    years : Int64
    months : Int64
    weeks : Int64
    days : Int64
    } derive(Default, Eq,
    Debug
    )

    The date portion of a duration: years, months, weeks and days.

    Unlike a time duration these components cannot be normalized against each other, because the length of a year or a month depends on where in the calendar it starts.

    DateDuration::abs

    Returns the duration with every component made non-negative.

    DateDuration::days

    fn DateDuration::days(self : DateDuration) -> Int64

    Returns the days component.

    DateDuration::default

    fn DateDuration::default() -> DateDuration

    DateDuration::months

    fn DateDuration::months(self : DateDuration) -> Int64

    Returns the months component.

    DateDuration::negated

    fn DateDuration::negated(self : DateDuration) -> DateDuration

    Returns the duration with every component negated.

    DateDuration::new

    fn DateDuration::new(years : Int64, months : Int64, weeks : Int64, days : Int64) -> DateDuration raise TemporalError

    CreateDateDurationRecord: creates a validated date duration.

    All non-zero fields must share a sign, and each must stay inside the range a Duration permits.

    test {
    let d = @temporal.DateDuration::new(1, 2, 3, 4)
    inspect(d.years(), content="1")
    inspect(d.days(), content="4")
    }

    DateDuration::sign

    fn DateDuration::sign(self : DateDuration) -> Sign

    DateDurationSign: the sign shared by every non-zero component.

    DateDuration::weeks

    fn DateDuration::weeks(self : DateDuration) -> Int64

    Returns the weeks component.

    DateDuration::years

    fn DateDuration::years(self : DateDuration) -> Int64

    Returns the years component.

    DateTimeUnit

    pub(all) enum DateTimeUnit {
    Auto
    Nanosecond
    Microsecond
    Millisecond
    Second
    Minute
    Hour
    Day
    Week
    Month
    Year
    } derive(Compare, Eq, Hash,
    Debug
    )

    A Temporal unit, from Table 21: Temporal units by descending magnitude.

    The declaration order is significant: comparison operators use it, so a larger unit compares greater. Auto sorts below every real unit, matching the discriminant order temporal_rs relies on.

    DateTimeUnit::as_nanoseconds

    fn DateTimeUnit::as_nanoseconds(self : DateTimeUnit) -> Int64?

    Returns the length of this unit in nanoseconds, or None for units whose length is not fixed (year, month, week) and for Auto.

    DateTimeUnit::is_calendar_unit

    fn DateTimeUnit::is_calendar_unit(self : DateTimeUnit) -> Bool

    Returns whether this is one of the calendar units: year, month or week.

    DateTimeUnit::is_date_unit

    fn DateTimeUnit::is_date_unit(self : DateTimeUnit) -> Bool

    Returns whether this unit belongs to the date group: year, month, week or day.

    DateTimeUnit::is_time_unit

    fn DateTimeUnit::is_time_unit(self : DateTimeUnit) -> Bool

    Returns whether this unit belongs to the time group: hour through nanosecond.

    DateTimeUnit::larger

    fn DateTimeUnit::larger(self : DateTimeUnit, other : DateTimeUnit) -> DateTimeUnit

    LargerOfTwoTemporalUnits.

    DateTimeUnit::of_string

    fn DateTimeUnit::of_string(s : String) -> DateTimeUnit raise TemporalError

    Parses a unit from its option string. Both singular and plural spellings are accepted, as in GetTemporalUnitValuedOption.

    test {
    inspect(@temporal.DateTimeUnit::of_string("days"), content="day")
    inspect(@temporal.DateTimeUnit::of_string("nanosecond"), content="nanosecond")
    }

    DateTimeUnit::to_maximum_rounding_increment

    fn DateTimeUnit::to_maximum_rounding_increment(self : DateTimeUnit) -> Int?

    MaximumTemporalDurationRoundingIncrement: the largest rounding increment permitted for this unit, or None when unbounded.

    DateTimeUnit::to_singular

    fn DateTimeUnit::to_singular(self : DateTimeUnit) -> String

    Returns the singular option string for this unit, as accepted and produced by the Temporal API.

    DifferenceOperation

    type DifferenceOperation derive(Eq,
    Debug
    )

    Which direction a difference is being taken in. since negates the rounding mode relative to until.

    DifferenceSettings

    pub struct DifferenceSettings {
    largest_unit : DateTimeUnit?
    smallest_unit : DateTimeUnit?
    rounding_mode : RoundingMode?
    increment : RoundingIncrement?
    } derive(Default,
    Debug
    )

    The unit-and-rounding options accepted by the until and since methods.

    DifferenceSettings::default

    DifferenceSettings::new

    fn DifferenceSettings::new(largest_unit? : DateTimeUnit, smallest_unit? : DateTimeUnit, rounding_mode? : RoundingMode, increment? : RoundingIncrement) -> DifferenceSettings

    Builds difference settings; every field defaults to unset.

    Disambiguation

    pub(all) enum Disambiguation {
    Compatible
    Earlier
    Later
    Reject
    } derive(Eq,
    Debug
    )

    How to resolve a wall-clock time that is ambiguous or nonexistent in a time zone, as happens around a DST transition.

    Disambiguation::of_string

    fn Disambiguation::of_string(s : String) -> Disambiguation raise TemporalError

    Parses a disambiguation option value.

    DisplayCalendar

    pub(all) enum DisplayCalendar {
    Auto
    Always
    Never
    Critical
    } derive(Eq,
    Debug
    )

    Whether toString should include the calendar annotation.

    DisplayCalendar::default

    DisplayCalendar::of_string

    fn DisplayCalendar::of_string(s : String) -> DisplayCalendar raise TemporalError

    Parses a calendarName option value.

    DisplayOffset

    pub(all) enum DisplayOffset {
    Auto
    Never
    } derive(Eq,
    Debug
    )

    Whether toString should include the UTC offset.

    DisplayOffset::default

    fn DisplayOffset::default() -> DisplayOffset

    DisplayOffset::of_string

    fn DisplayOffset::of_string(s : String) -> DisplayOffset raise TemporalError

    Parses an offset display option value.

    DisplayTimeZone

    pub(all) enum DisplayTimeZone {
    Auto
    Never
    Critical
    } derive(Eq,
    Debug
    )

    Whether toString should include the time zone annotation.

    DisplayTimeZone::default

    DisplayTimeZone::of_string

    fn DisplayTimeZone::of_string(s : String) -> DisplayTimeZone raise TemporalError

    Parses a timeZoneName option value.

    Duration

    pub struct Duration {
    years : Int64
    months : Int64
    weeks : Int64
    days : Int64
    hours : Int64
    minutes : Int64
    seconds : Int64
    milliseconds : Int64
    microseconds :
    Int128

    nanoseconds :
    Int128

    } derive(Eq)

    A span of time, such as "2 hours and 30 minutes" or "3 years, 2 months".

    A duration is not anchored to any point on the timeline. Its date components (years, months, weeks, days) and time components (hours through nanoseconds) are kept separate because the length of a year or month depends on where it starts, so converting between the two groups requires a reference point.

    Every non-zero component of a valid duration shares the same sign.

    impl Default for Duration
    impl Show for Duration

    Duration::abs

    fn Duration::abs(self : Duration) -> Duration

    Returns the duration with every component made non-negative.

    Duration::add

    fn Duration::add(self : Duration, other : Duration) -> Duration raise TemporalError

    Adds two durations.

    Neither operand may have a calendar component, because combining years or months requires a reference point; use PlainDate::add or ZonedDateTime::add for that.

    test {
    let a = @temporal.Duration::of(minutes=45)
    let b = @temporal.Duration::of(hours=1)
    inspect(a.add(b), content="PT1H45M")
    }

    Duration::date_duration

    fn Duration::date_duration(self : Duration) -> DateDuration

    Returns the date components as a [DateDuration].

    This is lossy: any time components are dropped.

    Duration::days

    fn Duration::days(self : Duration) -> Int64

    Returns the days component.

    Duration::from_date_duration

    fn Duration::from_date_duration(date : DateDuration) -> Duration raise TemporalError

    Creates a duration with only date components.

    Duration::hours

    fn Duration::hours(self : Duration) -> Int64

    Returns the hours component.

    Duration::is_zero

    fn Duration::is_zero(self : Duration) -> Bool

    Returns whether every component is zero.

    Duration::microseconds

    Returns the microseconds component.

    Duration::milliseconds

    fn Duration::milliseconds(self : Duration) -> Int64

    Returns the milliseconds component.

    Duration::minutes

    fn Duration::minutes(self : Duration) -> Int64

    Returns the minutes component.

    Duration::months

    fn Duration::months(self : Duration) -> Int64

    Returns the months component.

    Duration::nanoseconds

    Returns the nanoseconds component.

    Duration::negated

    fn Duration::negated(self : Duration) -> Duration

    Returns the duration with every component negated.

    test {
    inspect(@temporal.Duration::of(days=1, hours=2).negated(), content="-P1DT2H")
    }

    Duration::new

    fn Duration::new(years : Int64, months : Int64, weeks : Int64, days : Int64, hours : Int64, minutes : Int64, seconds : Int64, milliseconds : Int64, microseconds :
    Int128
    , nanoseconds :
    Int128
    ) -> Duration raise TemporalError

    CreateTemporalDuration: creates a validated duration.

    Raises a RangeError when the components disagree in sign or the total magnitude is not representable.

    test {
    let d = @temporal.Duration::of(weeks=2, days=3)
    inspect(d, content="P2W3D")
    }

    Duration::of

    fn Duration::of(years? : Int64, months? : Int64, weeks? : Int64, days? : Int64, hours? : Int64, minutes? : Int64, seconds? : Int64, milliseconds? : Int64, microseconds? : Int64, nanoseconds? : Int64) -> Duration raise TemporalError

    Creates a duration from date and time components given as Int.

    This is the ergonomic form for the common case; use [Duration::new] when a component needs the full Int64 or 128-bit range.

    test {
    let d = @temporal.Duration::of(hours=2, minutes=30)
    inspect(d, content="PT2H30M")
    }

    Duration::of_string

    fn Duration::of_string(source : String) -> Duration raise TemporalError

    Parses a Duration from an ISO 8601 duration string.

    test {
    let d = @temporal.Duration::of_string("P1Y2M3DT4H5M6.789S")
    inspect(d, content="P1Y2M3DT4H5M6.789S")
    inspect(@temporal.Duration::of_string("-P1D"), content="-P1D")
    }

    Duration::round

    fn[P : TimeZoneProvider] Duration::round(self : Duration, options : RoundingOptions, provider : P, relative_to? : RelativeTo) -> Duration raise TemporalError

    Rounds the duration.

    relative_to is required whenever the duration uses calendar units, or when rounding to one.

    test {
    let d = @temporal.Duration::of(hours=1, minutes=45)
    let options = @temporal.RoundingOptions::new(smallest_unit=Hour)
    inspect(d.round(options, @temporal.utc_only_provider), content="PT2H")
    }

    Duration::seconds

    fn Duration::seconds(self : Duration) -> Int64

    Returns the seconds component.

    Duration::sign

    fn Duration::sign(self : Duration) -> Sign

    DurationSign: the sign shared by every non-zero component.

    test {
    inspect(@temporal.Duration::of(days=-1).sign(), content="-1")
    inspect(@temporal.duration_zero.sign(), content="0")
    }

    Duration::subtract

    fn Duration::subtract(self : Duration, other : Duration) -> Duration raise TemporalError

    Subtracts other from this duration.

    The same calendar-component restriction as [Duration::add] applies.

    Duration::to_string

    fn Duration::to_string(self : Duration) -> String

    Renders the duration using the default options.

    test {
    inspect(
    @temporal.Duration::of(years=1, months=2, days=3).to_string(),
    content="P1Y2M3D",
    )
    inspect(@temporal.duration_zero.to_string(), content="PT0S")
    }

    Duration::to_string_with_options

    fn Duration::to_string_with_options(self : Duration, options : ToStringRoundingOptions) -> String raise TemporalError

    TemporalDurationToString: renders the duration, first rounding the sub-second part as the options require.

    test {
    let d = @temporal.Duration::of(seconds=1, milliseconds=500)
    inspect(
    d.to_string_with_options(
    @temporal.ToStringRoundingOptions::new(precision=Digit(1)),
    ),
    content="PT1.5S",
    )
    }

    Duration::total

    fn[P : TimeZoneProvider] Duration::total(self : Duration, unit : DateTimeUnit, provider : P, relative_to? : RelativeTo) -> Double raise TemporalError

    Returns the duration expressed as a fractional count of unit.

    relative_to is required whenever the duration uses calendar units, or when totalling into one.

    test {
    let d = @temporal.Duration::of(hours=1, minutes=30)
    inspect(d.total(Minute, @temporal.utc_only_provider), content="90")
    }

    Duration::weeks

    fn Duration::weeks(self : Duration) -> Int64

    Returns the weeks component.

    Duration::years

    fn Duration::years(self : Duration) -> Int64

    Returns the years component.

    EpochNanosecondsAndOffset

    pub struct EpochNanosecondsAndOffset {
    nanoseconds :
    Int128

    offset : UtcOffset
    } derive(Eq,
    Debug
    )

    An instant paired with the offset in force at that instant.

    Instant

    pub struct Instant {
    epoch_nanoseconds :
    Int128

    } derive(Compare, Eq)

    An exact point on the timeline, as a count of nanoseconds since the Unix epoch.

    An instant carries no calendar and no time zone; it is the same moment everywhere. The representable range is ±10^8 days around the epoch, the same range ECMAScript Date covers.

    impl Show for Instant

    Instant::add

    fn Instant::add(self : Instant, duration : Duration) -> Instant raise TemporalError

    Adds a duration.

    The duration may only have time components: an instant has no calendar, so years, months, weeks and days have no defined length against it.

    Instant::compare

    fn Instant::compare(Instant, Instant) -> Int

    Instant::epoch_milliseconds

    fn Instant::epoch_milliseconds(self : Instant) -> Int64

    Returns the milliseconds since the epoch, rounded toward negative infinity.

    Instant::epoch_nanoseconds

    Returns the nanoseconds since the epoch.

    Instant::from_epoch_milliseconds

    fn Instant::from_epoch_milliseconds(epoch_milliseconds : Int64) -> Instant raise TemporalError

    Creates an instant from milliseconds since the epoch.

    Instant::from_epoch_nanoseconds

    fn Instant::from_epoch_nanoseconds(epoch_nanoseconds :
    Int128
    ) -> Instant raise TemporalError

    Creates an instant from nanoseconds since the epoch.

    test {
    let instant = @temporal.Instant::from_epoch_nanoseconds(
    @int128.of_int64(1740827770000000000L),
    )
    inspect(instant, content="2025-03-01T11:16:10Z")
    }

    Instant::of_string

    fn Instant::of_string(source : String) -> Instant raise TemporalError

    Parses an instant from an RFC 9557 string, which must carry a UTC offset.

    test {
    inspect(
    @temporal.Instant::of_string("2025-03-01T11:16:10+01:00"),
    content="2025-03-01T10:16:10Z",
    )
    }

    Instant::round

    fn Instant::round(self : Instant, options : RoundingOptions) -> Instant raise TemporalError

    Rounds the instant to a multiple of the given unit.

    Rounding is done as though the instant were positive, so that moments before and after the epoch round in the same direction.

    Instant::since

    fn Instant::since(self : Instant, other : Instant, settings? : DifferenceSettings) -> Duration raise TemporalError

    Returns the duration from other until this instant.

    Instant::subtract

    fn Instant::subtract(self : Instant, duration : Duration) -> Instant raise TemporalError

    Subtracts a duration.

    Instant::to_string

    fn Instant::to_string(self : Instant) -> String

    Renders the instant in UTC, as YYYY-MM-DDTHH:MM:SSZ.

    Instant::to_string_with_options

    fn[P : TimeZoneProvider] Instant::to_string_with_options(self : Instant, options : ToStringRoundingOptions, time_zone : TimeZone?, provider : P) -> String raise TemporalError

    Renders the instant in RFC 9557 form.

    Without a time zone the instant is rendered in UTC with a Z suffix; with one, it is rendered as a local time with that zone's offset.

    Instant::to_zoned_date_time

    fn[P : TimeZoneProvider] Instant::to_zoned_date_time(self : Instant, time_zone : TimeZone, provider : P, calendar? : Calendar) -> ZonedDateTime raise TemporalError

    Converts to a ZonedDateTime in the given time zone.

    Instant::until

    fn Instant::until(self : Instant, other : Instant, settings? : DifferenceSettings) -> Duration raise TemporalError

    Returns the duration from this instant until other.

    InternalDurationRecord

    type InternalDurationRecord derive(
    Debug
    )

    A duration split into its calendar part and its normalized time part.

    IsoDate

    pub struct IsoDate {
    year : Int
    month : Int
    day : Int
    } derive(Compare, Eq,
    Debug
    )

    A calendar date in the ISO 8601 calendar, as the [[ISOYear]], [[ISOMonth]] and [[ISODay]] internal slots.

    The fields are declared in descending significance so that the derived comparison is the chronological one.
    impl Show for IsoDate

    IsoDate::compare

    fn IsoDate::compare(IsoDate, IsoDate) -> Int

    IsoDate::day

    fn IsoDate::day(self : IsoDate) -> Int

    Returns the day of the month.

    IsoDate::is_valid

    fn IsoDate::is_valid(self : IsoDate) -> Bool

    Returns whether the date names a day that exists.

    IsoDate::month

    fn IsoDate::month(self : IsoDate) -> Int

    Returns the month, 1-based.

    IsoDate::to_epoch_days

    fn IsoDate::to_epoch_days(self : IsoDate) -> Int64

    ISODateToEpochDays: days since 1970-01-01.

    IsoDate::year

    fn IsoDate::year(self : IsoDate) -> Int

    Returns the year.

    IsoDateTime

    pub struct IsoDateTime {
    date : IsoDate
    time : IsoTime
    } derive(Compare, Eq,
    Debug
    )

    A calendar date paired with a wall-clock time, with no time zone.
    impl Show for IsoDateTime

    IsoDateTime::compare

    fn IsoDateTime::compare(IsoDateTime, IsoDateTime) -> Int

    IsoDateTime::date

    fn IsoDateTime::date(self : IsoDateTime) -> IsoDate

    Returns the date part.

    IsoDateTime::time

    fn IsoDateTime::time(self : IsoDateTime) -> IsoTime

    Returns the time part.

    IsoTime

    pub struct IsoTime {
    hour : Int
    minute : Int
    second : Int
    millisecond : Int
    microsecond : Int
    nanosecond : Int
    } derive(Compare, Eq,
    Debug
    )

    A wall-clock time, as the [[ISOHour]] through [[ISONanosecond]] internal slots.

    The fields are declared in descending significance so that the derived comparison orders times chronologically.
    impl Show for IsoTime

    IsoTime::hour

    fn IsoTime::hour(self : IsoTime) -> Int

    Returns the hour.

    IsoTime::microsecond

    fn IsoTime::microsecond(self : IsoTime) -> Int

    Returns the microsecond within the millisecond.

    IsoTime::millisecond

    fn IsoTime::millisecond(self : IsoTime) -> Int

    Returns the millisecond.

    IsoTime::minute

    fn IsoTime::minute(self : IsoTime) -> Int

    Returns the minute.

    IsoTime::nanosecond

    fn IsoTime::nanosecond(self : IsoTime) -> Int

    Returns the nanosecond within the microsecond.

    IsoTime::second

    fn IsoTime::second(self : IsoTime) -> Int

    Returns the second.

    OffsetDisambiguation

    pub(all) enum OffsetDisambiguation {
    Use
    Prefer
    Ignore
    Reject
    } derive(Eq,
    Debug
    )

    How to treat a UTC offset that disagrees with the named time zone.

    OffsetDisambiguation::of_string

    fn OffsetDisambiguation::of_string(s : String) -> OffsetDisambiguation raise TemporalError

    Parses an offset option value.

    Overflow

    pub(all) enum Overflow {
    Constrain
    Reject
    } derive(Eq,
    Debug
    )

    How to handle a field that is out of range for its calendar.
    impl Default for Overflow
    impl Show for Overflow

    Overflow::of_string

    fn Overflow::of_string(s : String) -> Overflow raise TemporalError

    Parses an overflow option value.

    PlainDate

    pub struct PlainDate {
    iso : IsoDate
    calendar : Calendar
    } derive(Eq)

    A calendar date with no time and no time zone, such as a birthday.

    impl Show for PlainDate

    PlainDate::add

    fn PlainDate::add(self : PlainDate, duration : Duration, overflow? : Overflow) -> PlainDate raise TemporalError

    Adds a duration to this date.

    The duration's time components are truncated to whole days first, as AddDurationToDate requires.

    test {
    let jan31 = @temporal.PlainDate::try_new(2023, 1, 31)
    let one_month = @temporal.Duration::of(months=1)
    // February has no 31st, so `constrain` clamps to the end of the month.
    inspect(jan31.add(one_month), content="2023-02-28")
    }

    PlainDate::calendar

    fn PlainDate::calendar(self : PlainDate) -> Calendar

    Returns the calendar.

    PlainDate::day

    fn PlainDate::day(self : PlainDate) -> Int

    Returns the day of the month.

    PlainDate::day_of_week

    fn PlainDate::day_of_week(self : PlainDate) -> Int

    Returns the ISO day of the week, Monday = 1 through Sunday = 7.

    PlainDate::day_of_year

    fn PlainDate::day_of_year(self : PlainDate) -> Int

    Returns the 1-based day of the year.

    PlainDate::days_in_month

    fn PlainDate::days_in_month(self : PlainDate) -> Int

    Returns the number of days in this month.

    PlainDate::days_in_week

    fn PlainDate::days_in_week(_self : PlainDate) -> Int

    Returns the number of days in the week, always 7 in the ISO calendar.

    PlainDate::days_in_year

    fn PlainDate::days_in_year(self : PlainDate) -> Int

    Returns the number of days in this year.

    PlainDate::equals

    fn PlainDate::equals(self : PlainDate, other : PlainDate) -> Bool

    Returns whether two dates name the same day in the same calendar.

    PlainDate::from_iso

    fn PlainDate::from_iso(iso : IsoDate, calendar : Calendar) -> PlainDate

    Creates a date from an already-validated ISO date.

    PlainDate::in_leap_year

    fn PlainDate::in_leap_year(self : PlainDate) -> Bool

    Returns whether this year is a leap year.

    PlainDate::iso

    fn PlainDate::iso(self : PlainDate) -> IsoDate

    Returns the underlying ISO date.

    PlainDate::month

    fn PlainDate::month(self : PlainDate) -> Int

    Returns the month, 1-based.

    PlainDate::month_code

    fn PlainDate::month_code(self : PlainDate) -> String

    Returns the calendar-independent month code, such as M02 for February.

    PlainDate::months_in_year

    fn PlainDate::months_in_year(_self : PlainDate) -> Int

    Returns the number of months in this year, always 12 in the ISO calendar.

    PlainDate::new_with_overflow

    fn PlainDate::new_with_overflow(year : Int, month : Int, day : Int, overflow : Overflow, calendar : Calendar) -> PlainDate raise TemporalError

    Creates a date, handling out-of-range fields according to overflow.

    PlainDate::of_string

    fn PlainDate::of_string(source : String) -> PlainDate raise TemporalError

    Parses a PlainDate from an RFC 9557 string.

    test {
    inspect(@temporal.PlainDate::of_string("2025-03-01"), content="2025-03-01")
    inspect(
    @temporal.PlainDate::of_string("2025-03-01T11:16:10[u-ca=iso8601]"),
    content="2025-03-01",
    )
    }

    PlainDate::since

    fn PlainDate::since(self : PlainDate, other : PlainDate, settings? : DifferenceSettings) -> Duration raise TemporalError

    Returns the duration from other until this date.

    PlainDate::subtract

    fn PlainDate::subtract(self : PlainDate, duration : Duration, overflow? : Overflow) -> PlainDate raise TemporalError

    Subtracts a duration from this date.

    PlainDate::to_plain_date_time

    fn PlainDate::to_plain_date_time(self : PlainDate, time? : PlainTime) -> PlainDateTime raise TemporalError

    Combines this date with a time to produce a PlainDateTime.

    Without a time, midnight is used.

    PlainDate::to_string

    fn PlainDate::to_string(self : PlainDate) -> String

    Renders the date as YYYY-MM-DD.

    PlainDate::to_string_with_options

    fn PlainDate::to_string_with_options(self : PlainDate, display_calendar : DisplayCalendar) -> String

    Renders the date as YYYY-MM-DD, with an optional calendar annotation.

    PlainDate::try_new

    fn PlainDate::try_new(year : Int, month : Int, day : Int) -> PlainDate raise TemporalError

    Creates a date in the ISO calendar, rejecting one that does not exist.

    test {
    inspect(@temporal.PlainDate::try_new(2024, 2, 29), content="2024-02-29")
    }

    PlainDate::until

    fn PlainDate::until(self : PlainDate, other : PlainDate, settings? : DifferenceSettings) -> Duration raise TemporalError

    Returns the duration from this date until other.

    test {
    let a = @temporal.PlainDate::try_new(2020, 1, 1)
    let b = @temporal.PlainDate::try_new(2024, 3, 15)
    let settings = @temporal.DifferenceSettings::new(largest_unit=Year)
    inspect(a.until(b, settings~), content="P4Y2M14D")
    }

    PlainDate::week_of_year

    fn PlainDate::week_of_year(self : PlainDate) -> Int

    Returns the ISO week number.

    PlainDate::with_calendar

    fn PlainDate::with_calendar(self : PlainDate, calendar : Calendar) -> PlainDate

    Returns a copy in a different calendar.

    PlainDate::with_fields

    fn PlainDate::with_fields(self : PlainDate, year? : Int, month? : Int, day? : Int, overflow? : Overflow) -> PlainDate raise TemporalError

    Returns a copy with the given fields replaced.

    test {
    let date = @temporal.PlainDate::try_new(2024, 3, 15)
    inspect(date.with_fields(month=1), content="2024-01-15")
    }

    PlainDate::year

    fn PlainDate::year(self : PlainDate) -> Int

    Returns the year.

    PlainDate::year_of_week

    fn PlainDate::year_of_week(self : PlainDate) -> Int

    Returns the year the ISO week belongs to, which can differ from the calendar year at either end of a year.

    PlainDateTime

    pub struct PlainDateTime {
    iso : IsoDateTime
    calendar : Calendar
    } derive(Eq)

    PlainDateTime::add

    fn PlainDateTime::add(self : PlainDateTime, duration : Duration, overflow? : Overflow) -> PlainDateTime raise TemporalError

    AddDurationToDateTime: adds a duration, treating each of its days as exactly 24 hours.

    test {
    let dt = @temporal.PlainDateTime::try_new(2024, 1, 31, hour=23)
    // The time is added first: 23:00 + 2h rolls into the next day, so the
    // date arithmetic sees one month and one day.
    inspect(
    dt.add(@temporal.Duration::of(months=1, hours=2)),
    content="2024-03-01T01:00:00",
    )
    }

    PlainDateTime::calendar

    fn PlainDateTime::calendar(self : PlainDateTime) -> Calendar

    Returns the calendar.

    PlainDateTime::day

    fn PlainDateTime::day(self : PlainDateTime) -> Int

    Returns the day of the month.

    PlainDateTime::day_of_week

    fn PlainDateTime::day_of_week(self : PlainDateTime) -> Int

    Returns the ISO day of the week, Monday = 1 through Sunday = 7.

    PlainDateTime::day_of_year

    fn PlainDateTime::day_of_year(self : PlainDateTime) -> Int

    Returns the 1-based day of the year.

    PlainDateTime::days_in_month

    fn PlainDateTime::days_in_month(self : PlainDateTime) -> Int

    Returns the number of days in this month.

    PlainDateTime::days_in_year

    fn PlainDateTime::days_in_year(self : PlainDateTime) -> Int

    Returns the number of days in this year.

    PlainDateTime::equals

    fn PlainDateTime::equals(self : PlainDateTime, other : PlainDateTime) -> Bool

    Returns whether two date-times are the same instant in the same calendar.

    PlainDateTime::from_iso

    fn PlainDateTime::from_iso(iso : IsoDateTime, calendar : Calendar) -> PlainDateTime

    Creates a date-time from an already-validated ISO date-time.

    PlainDateTime::hour

    fn PlainDateTime::hour(self : PlainDateTime) -> Int

    Returns the hour.

    PlainDateTime::in_leap_year

    fn PlainDateTime::in_leap_year(self : PlainDateTime) -> Bool

    Returns whether this year is a leap year.

    PlainDateTime::iso

    Returns the underlying ISO date-time.

    PlainDateTime::microsecond

    fn PlainDateTime::microsecond(self : PlainDateTime) -> Int

    Returns the microsecond within the millisecond.

    PlainDateTime::millisecond

    fn PlainDateTime::millisecond(self : PlainDateTime) -> Int

    Returns the millisecond.

    PlainDateTime::minute

    fn PlainDateTime::minute(self : PlainDateTime) -> Int

    Returns the minute.

    PlainDateTime::month

    fn PlainDateTime::month(self : PlainDateTime) -> Int

    Returns the month, 1-based.

    PlainDateTime::month_code

    fn PlainDateTime::month_code(self : PlainDateTime) -> String

    Returns the calendar-independent month code.

    PlainDateTime::months_in_year

    fn PlainDateTime::months_in_year(_self : PlainDateTime) -> Int

    Returns the number of months in this year, always 12 in the ISO calendar.

    PlainDateTime::nanosecond

    fn PlainDateTime::nanosecond(self : PlainDateTime) -> Int

    Returns the nanosecond within the microsecond.

    PlainDateTime::new_with_overflow

    fn PlainDateTime::new_with_overflow(year : Int, month : Int, day : Int, hour : Int, minute : Int, second : Int, millisecond : Int, microsecond : Int, nanosecond : Int, overflow : Overflow, calendar : Calendar) -> PlainDateTime raise TemporalError

    Creates a date-time, handling out-of-range fields according to overflow.

    PlainDateTime::of_string

    fn PlainDateTime::of_string(source : String) -> PlainDateTime raise TemporalError

    Parses a PlainDateTime from an RFC 9557 string.

    test {
    inspect(
    @temporal.PlainDateTime::of_string("2025-03-01T11:16:10"),
    content="2025-03-01T11:16:10",
    )
    }

    PlainDateTime::round

    Rounds to a multiple of the given unit, which may be as large as a day.

    PlainDateTime::second

    fn PlainDateTime::second(self : PlainDateTime) -> Int

    Returns the second.

    PlainDateTime::since

    fn PlainDateTime::since(self : PlainDateTime, other : PlainDateTime, settings? : DifferenceSettings) -> Duration raise TemporalError

    Returns the duration from other until this date-time.

    PlainDateTime::subtract

    fn PlainDateTime::subtract(self : PlainDateTime, duration : Duration, overflow? : Overflow) -> PlainDateTime raise TemporalError

    Subtracts a duration.

    PlainDateTime::to_plain_date

    fn PlainDateTime::to_plain_date(self : PlainDateTime) -> PlainDate

    Returns the date part.

    PlainDateTime::to_plain_time

    fn PlainDateTime::to_plain_time(self : PlainDateTime) -> PlainTime

    Returns the time part.

    PlainDateTime::to_string

    fn PlainDateTime::to_string(self : PlainDateTime) -> String

    Renders the date-time as YYYY-MM-DDTHH:MM:SS.

    PlainDateTime::to_string_with_options

    fn PlainDateTime::to_string_with_options(self : PlainDateTime, options : ToStringRoundingOptions, display_calendar : DisplayCalendar) -> String raise TemporalError

    Renders the date-time in RFC 9557 form.

    PlainDateTime::try_new

    fn PlainDateTime::try_new(year : Int, month : Int, day : Int, hour? : Int, minute? : Int, second? : Int, millisecond? : Int, microsecond? : Int, nanosecond? : Int) -> PlainDateTime raise TemporalError

    Creates a date-time in the ISO calendar, rejecting invalid fields.

    test {
    inspect(
    @temporal.PlainDateTime::try_new(2025, 3, 1, hour=11, minute=16, second=10),
    content="2025-03-01T11:16:10",
    )
    }

    PlainDateTime::until

    fn PlainDateTime::until(self : PlainDateTime, other : PlainDateTime, settings? : DifferenceSettings) -> Duration raise TemporalError

    Returns the duration from this date-time until other.

    PlainDateTime::week_of_year

    fn PlainDateTime::week_of_year(self : PlainDateTime) -> Int

    Returns the ISO week number.

    PlainDateTime::with_fields

    fn PlainDateTime::with_fields(self : PlainDateTime, year? : Int, month? : Int, day? : Int, hour? : Int, minute? : Int, second? : Int, millisecond? : Int, microsecond? : Int, nanosecond? : Int, overflow? : Overflow) -> PlainDateTime raise TemporalError

    Returns a copy with the given fields replaced.

    PlainDateTime::year

    fn PlainDateTime::year(self : PlainDateTime) -> Int

    Returns the year.

    PlainDateTime::year_of_week

    fn PlainDateTime::year_of_week(self : PlainDateTime) -> Int

    Returns the year the ISO week belongs to.

    PlainMonthDay

    pub struct PlainMonthDay {
    iso : IsoDate
    calendar : Calendar
    } derive(Eq)

    A month and a day with no year, such as a recurring anniversary.

    A reference year is kept internally so the pair names a concrete date; 1972 is used because it is a leap year, so February 29 survives the round trip.

    PlainMonthDay::calendar

    fn PlainMonthDay::calendar(self : PlainMonthDay) -> Calendar

    Returns the calendar.

    PlainMonthDay::day

    fn PlainMonthDay::day(self : PlainMonthDay) -> Int

    Returns the day of the month.

    PlainMonthDay::equals

    fn PlainMonthDay::equals(self : PlainMonthDay, other : PlainMonthDay) -> Bool

    Returns whether both name the same month and day in the same calendar.

    PlainMonthDay::month

    fn PlainMonthDay::month(self : PlainMonthDay) -> Int

    Returns the month, 1-based.

    PlainMonthDay::month_code

    fn PlainMonthDay::month_code(self : PlainMonthDay) -> String

    Returns the calendar-independent month code.

    PlainMonthDay::of_string

    fn PlainMonthDay::of_string(source : String) -> PlainMonthDay raise TemporalError

    Parses a month-day from an RFC 9557 string.

    test {
    inspect(@temporal.PlainMonthDay::of_string("--02-29"), content="02-29")
    inspect(@temporal.PlainMonthDay::of_string("2024-02-29"), content="02-29")
    }

    PlainMonthDay::reference_year

    fn PlainMonthDay::reference_year(self : PlainMonthDay) -> Int

    Returns the internal reference year.

    PlainMonthDay::to_plain_date

    fn PlainMonthDay::to_plain_date(self : PlainMonthDay, year : Int, overflow? : Overflow) -> PlainDate raise TemporalError

    Combines this month-day with a year to produce a PlainDate.

    test {
    let leap_day = @temporal.PlainMonthDay::try_new(2, 29)
    // 2023 is not a leap year, so the day is constrained to the 28th.
    inspect(leap_day.to_plain_date(2023), content="2023-02-28")
    }

    PlainMonthDay::to_string

    fn PlainMonthDay::to_string(self : PlainMonthDay) -> String

    Renders the month-day as MM-DD.

    PlainMonthDay::to_string_with_options

    fn PlainMonthDay::to_string_with_options(self : PlainMonthDay, display_calendar : DisplayCalendar) -> String

    Renders the month-day as MM-DD.

    The reference year is included when a calendar annotation is present, since a non-ISO calendar needs it to reconstruct the same day.

    PlainMonthDay::try_new

    fn PlainMonthDay::try_new(month : Int, day : Int, reference_year? : Int, overflow? : Overflow, calendar? : Calendar) -> PlainMonthDay raise TemporalError

    Creates a month-day.

    test {
    inspect(@temporal.PlainMonthDay::try_new(2, 29), content="02-29")
    }

    PlainMonthDay::with_fields

    fn PlainMonthDay::with_fields(self : PlainMonthDay, month? : Int, day? : Int, overflow? : Overflow) -> PlainMonthDay raise TemporalError

    Returns a copy with the month or day replaced.

    PlainTime

    pub struct PlainTime {
    iso : IsoTime
    } derive(Compare, Eq)

    A wall-clock time with no date and no time zone, such as "07:30".

    impl Show for PlainTime

    PlainTime::add

    fn PlainTime::add(self : PlainTime, duration : Duration) -> PlainTime

    AddDurationToTime: adds a duration, wrapping around midnight.

    Calendar components are ignored, since a time has no date to hang them on.

    test {
    let t = @temporal.PlainTime::try_new(hour=23, minute=30)
    inspect(t.add(@temporal.Duration::of(hours=1)), content="00:30:00")
    }

    PlainTime::from_iso

    fn PlainTime::from_iso(iso : IsoTime) -> PlainTime

    Creates a time from an already-validated ISO time.

    PlainTime::hour

    fn PlainTime::hour(self : PlainTime) -> Int

    Returns the hour.

    PlainTime::iso

    fn PlainTime::iso(self : PlainTime) -> IsoTime

    Returns the underlying ISO time.

    PlainTime::microsecond

    fn PlainTime::microsecond(self : PlainTime) -> Int

    Returns the microsecond within the millisecond.

    PlainTime::millisecond

    fn PlainTime::millisecond(self : PlainTime) -> Int

    Returns the millisecond.

    PlainTime::minute

    fn PlainTime::minute(self : PlainTime) -> Int

    Returns the minute.

    PlainTime::nanosecond

    fn PlainTime::nanosecond(self : PlainTime) -> Int

    Returns the nanosecond within the microsecond.

    PlainTime::new_with_overflow

    fn PlainTime::new_with_overflow(hour : Int, minute : Int, second : Int, millisecond : Int, microsecond : Int, nanosecond : Int, overflow : Overflow) -> PlainTime raise TemporalError

    Creates a time, handling out-of-range fields according to overflow.

    PlainTime::of_string

    fn PlainTime::of_string(source : String) -> PlainTime raise TemporalError

    Parses a PlainTime from an RFC 9557 string.

    test {
    inspect(@temporal.PlainTime::of_string("12:30:45.5"), content="12:30:45.5")
    }

    PlainTime::round

    fn PlainTime::round(self : PlainTime, options : RoundingOptions) -> PlainTime raise TemporalError

    Rounds the time to a multiple of the given unit.

    Rounding that carries past midnight wraps, since a time has no date to carry into.

    test {
    let t = @temporal.PlainTime::try_new(hour=12, minute=34, second=56)
    let options = @temporal.RoundingOptions::new(smallest_unit=Minute)
    inspect(t.round(options), content="12:35:00")
    }

    PlainTime::second

    fn PlainTime::second(self : PlainTime) -> Int

    Returns the second.

    PlainTime::since

    fn PlainTime::since(self : PlainTime, other : PlainTime, settings? : DifferenceSettings) -> Duration raise TemporalError

    Returns the duration from other until this time.

    PlainTime::subtract

    fn PlainTime::subtract(self : PlainTime, duration : Duration) -> PlainTime

    Subtracts a duration, wrapping around midnight.

    PlainTime::to_string

    fn PlainTime::to_string(self : PlainTime) -> String

    Renders the time as HH:MM:SS, with as many fractional digits as it needs.

    PlainTime::to_string_with_options

    fn PlainTime::to_string_with_options(self : PlainTime, options : ToStringRoundingOptions) -> String raise TemporalError

    Renders the time as HH:MM:SS, extended with fractional digits as the options require.

    PlainTime::try_new

    fn PlainTime::try_new(hour? : Int, minute? : Int, second? : Int, millisecond? : Int, microsecond? : Int, nanosecond? : Int) -> PlainTime raise TemporalError

    Creates a time, rejecting out-of-range fields.

    test {
    inspect(@temporal.PlainTime::try_new(hour=7, minute=30), content="07:30:00")
    }

    PlainTime::until

    fn PlainTime::until(self : PlainTime, other : PlainTime, settings? : DifferenceSettings) -> Duration raise TemporalError

    Returns the duration from this time until other.

    PlainTime::with_fields

    fn PlainTime::with_fields(self : PlainTime, hour? : Int, minute? : Int, second? : Int, millisecond? : Int, microsecond? : Int, nanosecond? : Int, overflow? : Overflow) -> PlainTime raise TemporalError

    Returns a copy with the given fields replaced.

    PlainYearMonth

    pub struct PlainYearMonth {
    iso : IsoDate
    calendar : Calendar
    } derive(Eq)

    A year and a month with no day, such as "the October 2030 issue".

    A reference day is kept internally so that arithmetic and comparison have a concrete date to work from; it is never part of the type's identity.

    PlainYearMonth::add

    fn PlainYearMonth::add(self : PlainYearMonth, duration : Duration, overflow? : Overflow) -> PlainYearMonth raise TemporalError

    AddDurationToYearMonth: adds a duration of whole years and months.

    Weeks, days and time components are rejected: a year-month has no day to apply them to.

    test {
    let ym = @temporal.PlainYearMonth::try_new(2024, 1)
    inspect(ym.add(@temporal.Duration::of(months=13)), content="2025-02")
    }

    PlainYearMonth::calendar

    fn PlainYearMonth::calendar(self : PlainYearMonth) -> Calendar

    Returns the calendar.

    PlainYearMonth::days_in_month

    fn PlainYearMonth::days_in_month(self : PlainYearMonth) -> Int

    Returns the number of days in this month.

    PlainYearMonth::days_in_year

    fn PlainYearMonth::days_in_year(self : PlainYearMonth) -> Int

    Returns the number of days in this year.

    PlainYearMonth::equals

    fn PlainYearMonth::equals(self : PlainYearMonth, other : PlainYearMonth) -> Bool

    Returns whether both name the same month in the same calendar.

    PlainYearMonth::in_leap_year

    fn PlainYearMonth::in_leap_year(self : PlainYearMonth) -> Bool

    Returns whether this year is a leap year.

    PlainYearMonth::month

    fn PlainYearMonth::month(self : PlainYearMonth) -> Int

    Returns the month, 1-based.

    PlainYearMonth::month_code

    fn PlainYearMonth::month_code(self : PlainYearMonth) -> String

    Returns the calendar-independent month code.

    PlainYearMonth::months_in_year

    fn PlainYearMonth::months_in_year(_self : PlainYearMonth) -> Int

    Returns the number of months in this year, always 12 in the ISO calendar.

    PlainYearMonth::of_string

    fn PlainYearMonth::of_string(source : String) -> PlainYearMonth raise TemporalError

    Parses a year-month from an RFC 9557 string.

    test {
    inspect(@temporal.PlainYearMonth::of_string("2030-10"), content="2030-10")
    }

    PlainYearMonth::since

    fn PlainYearMonth::since(self : PlainYearMonth, other : PlainYearMonth, settings? : DifferenceSettings) -> Duration raise TemporalError

    Returns the duration from other until this year-month.

    PlainYearMonth::subtract

    fn PlainYearMonth::subtract(self : PlainYearMonth, duration : Duration, overflow? : Overflow) -> PlainYearMonth raise TemporalError

    Subtracts a duration.

    PlainYearMonth::to_plain_date

    fn PlainYearMonth::to_plain_date(self : PlainYearMonth, day : Int) -> PlainDate raise TemporalError

    Combines this year-month with a day to produce a PlainDate.

    PlainYearMonth::to_string

    fn PlainYearMonth::to_string(self : PlainYearMonth) -> String

    Renders the year-month as YYYY-MM.

    PlainYearMonth::to_string_with_options

    fn PlainYearMonth::to_string_with_options(self : PlainYearMonth, display_calendar : DisplayCalendar) -> String

    Renders the year-month as YYYY-MM.

    The reference day is included when a calendar annotation is present, since a non-ISO calendar needs it to reconstruct the same month.

    PlainYearMonth::try_new

    fn PlainYearMonth::try_new(year : Int, month : Int, reference_day? : Int, overflow? : Overflow, calendar? : Calendar) -> PlainYearMonth raise TemporalError

    Creates a year-month, rejecting one outside the supported range.

    reference_day chooses the internal reference day; it defaults to the first of the month.

    test {
    inspect(@temporal.PlainYearMonth::try_new(2030, 10), content="2030-10")
    }

    PlainYearMonth::until

    fn PlainYearMonth::until(self : PlainYearMonth, other : PlainYearMonth, settings? : DifferenceSettings) -> Duration raise TemporalError

    Returns the duration from this year-month until other.

    PlainYearMonth::with_fields

    fn PlainYearMonth::with_fields(self : PlainYearMonth, year? : Int, month? : Int, overflow? : Overflow) -> PlainYearMonth raise TemporalError

    Returns a copy with the year or month replaced.

    PlainYearMonth::year

    fn PlainYearMonth::year(self : PlainYearMonth) -> Int

    Returns the year.

    Precision

    pub(all) enum Precision {
    Auto
    Digit(Int)
    Minute
    } derive(Eq,
    Debug
    )

    The number of fractional-second digits toString should emit.

    RelativeTo

    pub(all) enum RelativeTo {
    DateRelative(PlainDate)
    ZonedRelative(ZonedDateTime)
    } derive(
    Debug
    )

    The point a duration's calendar units are measured against.

    Years, months, weeks and days have no fixed length, so rounding or totalling a duration that uses them needs a starting point to resolve them from.

    RelativeTo::of_string

    fn[P : TimeZoneProvider] RelativeTo::of_string(source : String, provider : P) -> RelativeTo raise TemporalError

    Parses a relativeTo value, preferring a zoned reading when the string carries a time zone annotation.

    test {
    let relative = @temporal.RelativeTo::of_string(
    "2020-01-01", @temporal.utc_only_provider,
    )
    inspect(relative is DateRelative(_), content="true")
    }

    ResolvedRoundingOptions

    type ResolvedRoundingOptions derive(
    Debug
    )

    Rounding options with every choice made, ready to drive an operation.

    RoundingIncrement

    pub struct RoundingIncrement(Int) derive(Compare, Eq,
    Debug
    )

    A validated rounding increment, in 1 ..= 10^9.

    RoundingIncrement::get

    fn RoundingIncrement::get(self : RoundingIncrement) -> Int

    Returns the numeric value of the increment.

    RoundingIncrement::try_new

    fn RoundingIncrement::try_new(increment : Int) -> RoundingIncrement raise TemporalError

    Creates a rounding increment, rejecting values outside 1 ..= 10^9.

    test {
    inspect(@temporal.RoundingIncrement::try_new(30), content="30")
    }

    RoundingMode

    pub(all) enum RoundingMode {
    Ceil
    Floor
    Expand
    Trunc
    HalfCeil
    HalfFloor
    HalfExpand
    HalfTrunc
    HalfEven
    } derive(Eq,
    Debug
    )

    The rounding mode applied when a value falls between two increments.

    RoundingMode::negate

    fn RoundingMode::negate(self : RoundingMode) -> RoundingMode

    NegateRoundingMode: mirrors the mode about zero, used to turn an until rounding mode into the since one.

    RoundingMode::of_string

    fn RoundingMode::of_string(s : String) -> RoundingMode raise TemporalError

    Parses a roundingMode option value.

    RoundingMode::to_unsigned

    fn RoundingMode::to_unsigned(self : RoundingMode, is_positive : Bool) -> UnsignedRoundingMode

    GetUnsignedRoundingMode: resolves a signed mode against the sign of the value being rounded.

    RoundingOptions

    pub struct RoundingOptions {
    largest_unit : DateTimeUnit?
    smallest_unit : DateTimeUnit?
    rounding_mode : RoundingMode?
    increment : RoundingIncrement?
    } derive(
    Debug
    )

    The options accepted by the round methods.

    RoundingOptions::new

    fn RoundingOptions::new(largest_unit? : DateTimeUnit, smallest_unit? : DateTimeUnit, rounding_mode? : RoundingMode, increment? : RoundingIncrement) -> RoundingOptions

    Builds rounding options; every field defaults to unset.

    Sign

    pub(all) enum Sign {
    Negative
    Zero
    Positive
    } derive(Compare, Eq,
    Debug
    )

    The sign of a duration or comparison.
    impl Default for Sign
    impl Show for Sign

    Sign::negate

    fn Sign::negate(self : Sign) -> Sign

    Flips the sign; zero stays zero.

    Sign::of_int

    fn Sign::of_int(value : Int) -> Sign

    Builds a sign from a signed number's sign.

    Sign::of_int64

    fn Sign::of_int64(value : Int64) -> Sign

    Builds a sign from a signed number's sign.

    Sign::to_int

    fn Sign::to_int(self : Sign) -> Int

    Returns -1, 0 or 1.

    Sign::to_multiplier

    fn Sign::to_multiplier(self : Sign) -> Int

    Returns 1 for a zero sign, so that multiplying by the result never annihilates a value. This is temporal_rs's as_sign_multiplier.

    TimeDuration

    type TimeDuration derive(Compare, Eq,
    Debug
    )

    The time portion of a duration, held as a single count of nanoseconds.

    Time components can be normalized against one another because their lengths are fixed, so the whole time part collapses to one integer. The magnitude never exceeds [max_time_duration].

    TimeZone

    pub(all) enum TimeZone {
    OffsetZone(UtcOffset)
    IanaZone(String)
    } derive(Eq,
    Debug
    )

    A time zone: either a fixed offset from UTC or a named IANA zone.

    Named zones are resolved through a [TimeZoneProvider], because the transition data they need is far larger than a date library should embed. The built-in [utc_only_provider] handles UTC and nothing else.
    impl Show for TimeZone

    TimeZone::epoch_nanoseconds_for

    fn[P : TimeZoneProvider] TimeZone::epoch_nanoseconds_for(self : TimeZone, local_iso : IsoDateTime, disambiguation : Disambiguation, provider : P) -> EpochNanosecondsAndOffset raise TemporalError

    GetEpochNanosecondsFor: resolves a local time to a single instant.

    TimeZone::identifier

    fn TimeZone::identifier(self : TimeZone) -> String

    Returns the time zone identifier, as toString would render it.

    TimeZone::offset_nanoseconds_for

    fn[P : TimeZoneProvider] TimeZone::offset_nanoseconds_for(self : TimeZone, epoch_nanoseconds :
    Int128
    , provider : P) -> Int64 raise TemporalError

    GetOffsetNanosecondsFor: the offset in force at the given instant.

    TimeZone::utc_offset_for

    fn[P : TimeZoneProvider] TimeZone::utc_offset_for(self : TimeZone, epoch_nanoseconds :
    Int128
    , provider : P) -> UtcOffset raise TemporalError

    Returns the offset in force at the given instant.

    ToStringRoundingOptions

    pub struct ToStringRoundingOptions {
    precision : Precision
    smallest_unit : DateTimeUnit?
    rounding_mode : RoundingMode?
    } derive(Default,
    Debug
    )

    The options controlling how toString renders sub-second precision.

    ToStringRoundingOptions::default

    ToStringRoundingOptions::new

    fn ToStringRoundingOptions::new(precision? : Precision, smallest_unit? : DateTimeUnit, rounding_mode? : RoundingMode) -> ToStringRoundingOptions

    Builds toString rounding options.

    UnitGroup

    pub(all) enum UnitGroup {
    Date
    Time
    DateTime
    } derive(Eq,
    Debug
    )

    UnsignedRoundingMode

    pub(all) enum UnsignedRoundingMode {
    Infinity
    Zero
    HalfInfinity
    HalfZero
    HalfEven
    } derive(Eq,
    Debug
    )

    A rounding mode with the sign of the operand already folded in.

    UtcOffset

    pub struct UtcOffset(Int64) derive(Compare, Eq,
    Debug
    )

    A fixed offset from UTC, stored in nanoseconds.

    Offsets used as time zone identifiers are restricted to minute precision; sub-minute offsets only arise when parsing an RFC 9557 string that carries one, and are rejected where the specification requires minute precision.
    impl Show for UtcOffset

    UtcOffset::from_minutes

    fn UtcOffset::from_minutes(minutes : Int) -> UtcOffset

    Creates an offset from whole minutes.

    test {
    inspect(@temporal.UtcOffset::from_minutes(-330), content="-05:30")
    }

    UtcOffset::from_nanoseconds

    fn UtcOffset::from_nanoseconds(nanoseconds : Int64) -> UtcOffset

    Creates an offset from nanoseconds.

    UtcOffset::from_seconds

    fn UtcOffset::from_seconds(seconds : Int64) -> UtcOffset

    Creates an offset from whole seconds.

    UtcOffset::is_sub_minute

    fn UtcOffset::is_sub_minute(self : UtcOffset) -> Bool

    Returns whether the offset carries finer detail than whole minutes.

    UtcOffset::minutes

    fn UtcOffset::minutes(self : UtcOffset) -> Int

    Returns the offset in whole minutes, truncated toward zero.

    UtcOffset::nanoseconds

    fn UtcOffset::nanoseconds(self : UtcOffset) -> Int64

    Returns the offset in nanoseconds.

    UtcOffset::seconds

    fn UtcOffset::seconds(self : UtcOffset) -> Int64

    Returns the offset in whole seconds, truncated toward zero.

    UtcOffset::to_string

    fn UtcOffset::to_string(self : UtcOffset) -> String

    Renders the offset as ±HH:MM, extending to seconds and fractions only when the offset needs them.

    test {
    inspect(@temporal.UtcOffset::from_minutes(0), content="+00:00")
    inspect(@temporal.UtcOffset::from_seconds(3661), content="+01:01:01")
    }

    UtcOnlyProvider

    pub struct UtcOnlyProvider {
    // private fields
    } derive(
    Debug
    )

    A provider that knows only UTC.

    It is enough for fixed-offset work and for the UTC zone itself; any other named zone raises a RangeError.

    ZonedDateTime

    pub struct ZonedDateTime {
    instant : Instant
    time_zone : TimeZone
    calendar : Calendar
    offset : UtcOffset
    } derive(Eq)

    An exact instant paired with a time zone and a calendar, so that it has a meaningful wall-clock reading.

    This is the only Temporal type that is both an exact time and a calendar date, which makes it the one where daylight-saving transitions are visible: a day may be 23 or 25 hours long, and adding "one day" is not the same as adding 24 hours.

    ZonedDateTime::add

    fn[P : TimeZoneProvider] ZonedDateTime::add(self : ZonedDateTime, duration : Duration, provider : P, overflow? : Overflow) -> ZonedDateTime raise TemporalError

    AddDurationToZonedDateTime: adds a duration.

    The calendar part is applied to the local wall-clock date and re-resolved through the time zone, so that "one day later" stays at the same local time even across a transition. The time part is then added as exact elapsed time.

    ZonedDateTime::calendar

    fn ZonedDateTime::calendar(self : ZonedDateTime) -> Calendar

    Returns the calendar.

    ZonedDateTime::compare_instant

    fn ZonedDateTime::compare_instant(self : ZonedDateTime, other : ZonedDateTime) -> Int

    Compares two zoned date-times by the instant they name, ignoring their time zones and calendars.

    ZonedDateTime::day

    fn ZonedDateTime::day(self : ZonedDateTime) -> Int

    Returns the local day of the month.

    ZonedDateTime::day_of_week

    fn ZonedDateTime::day_of_week(self : ZonedDateTime) -> Int

    Returns the local ISO day of the week, Monday = 1 through Sunday = 7.

    ZonedDateTime::day_of_year

    fn ZonedDateTime::day_of_year(self : ZonedDateTime) -> Int

    Returns the local 1-based day of the year.

    ZonedDateTime::epoch_milliseconds

    fn ZonedDateTime::epoch_milliseconds(self : ZonedDateTime) -> Int64

    Returns the milliseconds since the epoch.

    ZonedDateTime::epoch_nanoseconds

    Returns the nanoseconds since the epoch.

    ZonedDateTime::equals

    fn ZonedDateTime::equals(self : ZonedDateTime, other : ZonedDateTime) -> Bool

    Returns whether both name the same instant in the same zone and calendar.

    ZonedDateTime::hour

    fn ZonedDateTime::hour(self : ZonedDateTime) -> Int

    Returns the local hour.

    ZonedDateTime::hours_in_day

    fn[P : TimeZoneProvider] ZonedDateTime::hours_in_day(self : ZonedDateTime, provider : P) -> Double raise TemporalError

    Returns the number of hours in the local day, which is 23 or 25 across a daylight-saving transition.

    ZonedDateTime::microsecond

    fn ZonedDateTime::microsecond(self : ZonedDateTime) -> Int

    Returns the local microsecond within the millisecond.

    ZonedDateTime::millisecond

    fn ZonedDateTime::millisecond(self : ZonedDateTime) -> Int

    Returns the local millisecond.

    ZonedDateTime::minute

    fn ZonedDateTime::minute(self : ZonedDateTime) -> Int

    Returns the local minute.

    ZonedDateTime::month

    fn ZonedDateTime::month(self : ZonedDateTime) -> Int

    Returns the local month, 1-based.

    ZonedDateTime::nanosecond

    fn ZonedDateTime::nanosecond(self : ZonedDateTime) -> Int

    Returns the local nanosecond within the microsecond.

    ZonedDateTime::of_string

    fn[P : TimeZoneProvider] ZonedDateTime::of_string(source : String, provider : P, disambiguation? : Disambiguation, offset_option? : OffsetDisambiguation) -> ZonedDateTime raise TemporalError

    Parses a zoned date-time from an RFC 9557 string.

    The string must carry a time zone annotation, such as 2025-03-01T11:16:10Z[UTC].

    test {
    let zdt = @temporal.ZonedDateTime::of_string(
    "2025-03-01T11:16:10Z[UTC]", @temporal.utc_only_provider,
    )
    inspect(zdt.hour(), content="11")
    }

    ZonedDateTime::offset

    fn ZonedDateTime::offset(self : ZonedDateTime) -> UtcOffset

    Returns the UTC offset in force at this instant.

    ZonedDateTime::round

    fn[P : TimeZoneProvider] ZonedDateTime::round(self : ZonedDateTime, options : RoundingOptions, provider : P) -> ZonedDateTime raise TemporalError

    Rounds the zoned date-time to a multiple of the given unit.

    Rounding to whole days uses the actual length of the local day, which may be 23 or 25 hours across a daylight-saving transition.

    ZonedDateTime::second

    fn ZonedDateTime::second(self : ZonedDateTime) -> Int

    Returns the local second.

    ZonedDateTime::since

    fn[P : TimeZoneProvider] ZonedDateTime::since(self : ZonedDateTime, other : ZonedDateTime, provider : P, settings? : DifferenceSettings) -> Duration raise TemporalError

    Returns the duration from other until this zoned date-time.

    ZonedDateTime::start_of_day

    fn[P : TimeZoneProvider] ZonedDateTime::start_of_day(self : ZonedDateTime, provider : P) -> ZonedDateTime raise TemporalError

    Returns the instant at the start of the local day.

    This is usually midnight, but on a day whose midnight does not exist it is the first instant the day does reach.

    ZonedDateTime::subtract

    fn[P : TimeZoneProvider] ZonedDateTime::subtract(self : ZonedDateTime, duration : Duration, provider : P, overflow? : Overflow) -> ZonedDateTime raise TemporalError

    Subtracts a duration.

    ZonedDateTime::time_zone

    fn ZonedDateTime::time_zone(self : ZonedDateTime) -> TimeZone

    Returns the time zone.

    ZonedDateTime::to_instant

    fn ZonedDateTime::to_instant(self : ZonedDateTime) -> Instant

    Returns the underlying instant.

    ZonedDateTime::to_plain_date

    fn ZonedDateTime::to_plain_date(self : ZonedDateTime) -> PlainDate

    Returns the local date.

    ZonedDateTime::to_plain_date_time

    fn ZonedDateTime::to_plain_date_time(self : ZonedDateTime) -> PlainDateTime

    Returns the local wall-clock date and time.

    ZonedDateTime::to_plain_time

    fn ZonedDateTime::to_plain_time(self : ZonedDateTime) -> PlainTime

    Returns the local time.

    ZonedDateTime::to_string

    fn ZonedDateTime::to_string(self : ZonedDateTime) -> String

    Renders the zoned date-time in RFC 9557 form with default options.

    ZonedDateTime::to_string_with_options

    fn ZonedDateTime::to_string_with_options(self : ZonedDateTime, options : ToStringRoundingOptions, display_offset : DisplayOffset, display_time_zone : DisplayTimeZone, display_calendar : DisplayCalendar) -> String raise TemporalError

    Renders the zoned date-time in RFC 9557 form.

    ZonedDateTime::try_new

    fn[P : TimeZoneProvider] ZonedDateTime::try_new(epoch_nanoseconds :
    Int128
    , time_zone : TimeZone, provider : P, calendar? : Calendar) -> ZonedDateTime raise TemporalError

    Creates a zoned date-time from an instant and a time zone.

    test {
    let zdt = @temporal.ZonedDateTime::try_new(
    @int128.of_int64(1740827770000000000L),
    @temporal.TimeZone::OffsetZone(@temporal.UtcOffset::from_minutes(-360)),
    @temporal.utc_only_provider,
    )
    inspect(zdt.hour(), content="5")
    }

    ZonedDateTime::until

    fn[P : TimeZoneProvider] ZonedDateTime::until(self : ZonedDateTime, other : ZonedDateTime, provider : P, settings? : DifferenceSettings) -> Duration raise TemporalError

    Returns the duration from this zoned date-time until other.

    ZonedDateTime::with_time_zone

    fn[P : TimeZoneProvider] ZonedDateTime::with_time_zone(self : ZonedDateTime, time_zone : TimeZone, provider : P) -> ZonedDateTime raise TemporalError

    Returns a copy in a different time zone, naming the same instant.

    ZonedDateTime::year

    fn ZonedDateTime::year(self : ZonedDateTime) -> Int

    Returns the local year.

    MONTH_DAY_REFERENCE_YEAR

    let MONTH_DAY_REFERENCE_YEAR : Int

    The reference year the specification uses for a bare month-day.

    MS_PER_DAY

    let MS_PER_DAY : Int64

    Milliseconds in a 24-hour day.

    NS_PER_DAY

    let NS_PER_DAY : Int64

    Nanoseconds in a 24-hour day.

    duration_zero

    let duration_zero : Duration

    A duration of zero length.

    epoch_days_from_gregorian_date

    fn epoch_days_from_gregorian_date(year : Int, month : Int, day : Int) -> Int64

    Converts a Gregorian year/month/day to days since 1970-01-01.

    month is 1-based. The date need not be valid: an out-of-range day is simply carried, which is what the balancing operations rely on.

    test {
    inspect(@temporal.epoch_days_from_gregorian_date(1970, 1, 1), content="0")
    inspect(@temporal.epoch_days_from_gregorian_date(1969, 12, 31), content="-1")
    inspect(
    @temporal.epoch_days_from_gregorian_date(275760, 9, 14),
    content="100000001",
    )
    }

    instant_epoch

    let instant_epoch : Instant

    The Unix epoch, 1970-01-01T00:00:00Z.

    is_leap_year

    fn is_leap_year(year : Int) -> Bool

    Returns whether year is a leap year in the proleptic Gregorian calendar.

    test {
    inspect(@temporal.is_leap_year(2024), content="true")
    inspect(@temporal.is_leap_year(1900), content="false")
    inspect(@temporal.is_leap_year(2000), content="true")
    }

    is_valid_epoch_nanoseconds

    fn is_valid_epoch_nanoseconds(nanoseconds :
    Int128
    ) -> Bool

    Returns whether the count is inside the representable instant range.

    is_valid_iso_date

    fn is_valid_iso_date(year : Int, month : Int, day : Int) -> Bool

    Returns whether year-month-day names a day that exists.

    is_valid_iso_time

    fn is_valid_iso_time(hour : Int, minute : Int, second : Int, millisecond : Int, microsecond : Int, nanosecond : Int) -> Bool

    Returns whether the components name a valid wall-clock time.

    iso_date_unix_epoch

    let iso_date_unix_epoch : IsoDate

    The ISO date of the Unix epoch.

    iso_day_of_week

    fn iso_day_of_week(year : Int, month : Int, day : Int) -> Int

    Returns the ISO day of the week, Monday = 1 through Sunday = 7.

    test {
    // 1970-01-01 was a Thursday.
    inspect(@temporal.iso_day_of_week(1970, 1, 1), content="4")
    }

    iso_day_of_year

    fn iso_day_of_year(year : Int, month : Int, day : Int) -> Int

    Returns the 1-based day of the year.

    test {
    inspect(@temporal.iso_day_of_year(2024, 3, 1), content="61")
    }

    iso_days_in_month

    fn iso_days_in_month(year : Int, month : Int) -> Int

    Returns the number of days in the given ISO month.

    month is 1-based.

    test {
    inspect(@temporal.iso_days_in_month(2024, 2), content="29")
    inspect(@temporal.iso_days_in_month(2023, 2), content="28")
    inspect(@temporal.iso_days_in_month(2023, 12), content="31")
    }

    iso_days_in_year

    fn iso_days_in_year(year : Int) -> Int

    Returns the number of days in the given ISO year.

    iso_time_midnight

    let iso_time_midnight : IsoTime

    Midnight, 00:00:00.

    iso_week_of_year

    fn iso_week_of_year(year : Int, month : Int, day : Int) -> (Int, Int)

    Returns the ISO 8601 week-of-year number and the year that week belongs to.

    ISO weeks start on Monday, and week 1 is the week containing the first Thursday of the year, so days at either end of a year can belong to a week of the adjacent year.

    test {
    // 2021-01-01 was a Friday, falling in week 53 of 2020.
    debug_inspect(@temporal.iso_week_of_year(2021, 1, 1), content="(53, 2020)")
    debug_inspect(@temporal.iso_week_of_year(2024, 1, 1), content="(1, 2024)")
    }

    max_time_duration

    The largest magnitude a normalized time duration may take, in nanoseconds: (2^53 - 1) * 10^9 + (10^9 - 1).

    ns_max_instant

    The greatest number of nanoseconds an Instant may hold: 10^8 days after the epoch.

    ns_min_instant

    The least number of nanoseconds an Instant may hold: 10^8 days before the epoch.

    parse_time_zone_identifier

    fn parse_time_zone_identifier(identifier : String) -> TimeZone raise TemporalError

    Parses a time zone annotation body: either an offset or an IANA name.

    plain_time_midnight

    let plain_time_midnight : PlainTime

    Midnight.

    rounding_increment_one

    let rounding_increment_one : RoundingIncrement

    A rounding increment of one, meaning "round to the unit itself".

    time_zone_utc

    let time_zone_utc : TimeZone

    The UTC time zone.

    utc_offset_zero

    let utc_offset_zero : UtcOffset

    UTC itself, an offset of zero.

    utc_only_provider

    let utc_only_provider : UtcOnlyProvider

    The shared [UtcOnlyProvider] instance.

    ymd_from_epoch_days

    fn ymd_from_epoch_days(epoch_days : Int64) -> (Int, Int, Int)

    Converts days since 1970-01-01 to a Gregorian year/month/day triple.

    test {
    debug_inspect(@temporal.ymd_from_epoch_days(0), content="(1970, 1, 1)")
    debug_inspect(
    @temporal.ymd_from_epoch_days(-100000001),
    content="(-271821, 4, 19)",
    )
    }

    ymd_from_epoch_milliseconds

    fn ymd_from_epoch_milliseconds(epoch_ms : Int64) -> (Int, Int, Int)

    Converts epoch milliseconds to a Gregorian year/month/day triple.