Arithmetic and comparison
Add a duration to an instant to get a later instant, and take one instant from another to get the time between them:
Instant + Duration,Duration + InstantandInstant - Durationgive anInstantof the instant's own named type, so you don't build it again.Instant - Instantgives theDurationbetween them, which is negative when the second is later.Duration + DurationandDuration - Durationgive aDuration.
As with numbers, both sides must be the same type after widening, or one
must be a literal. Two durations of the same named type give a plain
Duration.
Instants, dates and durations order with <, <=, > and >=, and
compare with == on the timeline, so 12:00Z equals 13:00+01:00.
A CalendarDate has no clock time, so a Duration doesn't move it. It
moves by calendar days with temporal.add_days. A ZonedTime moves on its
calendar the same way, or through its instant. *, / and % don't take
time values.
type DueAt = Instant {}type ReminderNotice = Duration { min: 1m max: 7d}type Lateness = Duration {}/// When to send a reminder: the notice before the due time. Taking a/// duration from a `DueAt` gives a `DueAt`.function reminder_time(due_at: DueAt, notice: ReminderNotice) -> DueAt { return due_at - notice}/// How late something done at `done_at` was: negative when it was early.function lateness(due_at: DueAt, done_at: DueAt) -> Lateness { return Lateness(done_at - due_at)}test "a duration moves an instant and keeps its type" { assert reminder_time("2026-10-25T09:00:00Z", 30m) == "2026-10-25T08:30:00Z" assert lateness("2026-10-25T09:00:00Z", "2026-10-25T11:15:00Z") == 135m assert lateness("2026-10-25T09:00:00Z", "2026-10-25T08:00:00Z") < 0s}test "instants compare on the timeline" { assert DueAt("2026-10-25T12:00:00Z") == DueAt("2026-10-25T13:00:00+01:00") assert DueAt("2026-10-25T12:00:00Z") < DueAt("2026-10-25T12:00:00.001Z")}
Markdown for agents: /docs/arithmetic-and-comparison.md.Built from Jadpo main at a707efb.