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
moon add marianoguerra/temporal@0.1.0
Download zip
Version
0.1.0
License
Apache-2.0
Last updated
3 hours ago
Downloads
2
README

#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.

#
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::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::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::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::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::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::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::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::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::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.