ZoneRules

ZoneRules :: # (opaque)

Immutable finite rules supplied by the caller; no registry or host lookup.

Example

Supply rules explicitly: use from_database with the optional zone-data package, or construct a bounded snapshot for an application's own clock schedule. Offsets are local minus timeline in seconds. A rules snapshot only interprets labels inside its declared validity; it never falls back to the machine's zone.

For an ambiguous label, RequireUnique returns an error; First, Last, or MatchingOffset select an occurrence. classification_cursor separates bounded interpretation from choosing a result. select instead finds all coverage of a local-label range, which may be disconnected.

import time.ZoneRules
import time.FixedOffset
import time.PosixSpan
import time.PosixBoundary
import time.GregorianDate
import time.CalendarDate
import time.ClockTime
import time.LocalDateTime

expect {
    validity = PosixSpan.from_seconds(-86400, 86400, RejectSubmicrosecond)?
    rules = ZoneRules.new_bounded(
        "UTC", "fixed", validity,
        FixedOffset.from_seconds(0), [],
        { minimum: 0, maximum: 0 },
    )?
    date = GregorianDate.from_fields({ year: 1970, month: 1, day: 1 })?
    clock = ClockTime.from_microseconds_since_midnight(0)?
    local = LocalDateTime.new(CalendarDate.from_gregorian(date), clock)
    resolved = ZoneRules.resolve_occurrence(rules, local, RequireUnique)
    resolved == Ok(PosixBoundary.from_microseconds(0))
}

When a batch returns Limited, process its partial output and resume the returned cursor with sufficient budgets. Increasing only the output cap does not fix a work or buffer limit.

new : Str, Str, PosixSpan, FixedOffset, List(Transition) -> Try(ZoneRules, [EmptyName, EmptyVersion, TransitionOutsideValidity, UnorderedTransitions, InvalidOffsetBounds, OffsetOutsideBounds, ..])
new_bounded : Str, Str, PosixSpan, FixedOffset, List(Transition), OffsetBounds -> Try(ZoneRules, [EmptyName, EmptyVersion, TransitionOutsideValidity, UnorderedTransitions, InvalidOffsetBounds, OffsetOutsideBounds, ..])

Bounds are a provider guarantee, including outside this finite table. Never infer global bounds merely from the offsets observed in the table.

definition : ZoneRules -> Definition

Constant-time projection. Transition/string storage may remain shared; names and version labels are not substitutes for the returned actual data.

from_definition : Definition -> Try(ZoneRules, [EmptyName, EmptyVersion, TransitionOutsideValidity, UnorderedTransitions, InvalidOffsetBounds, OffsetOutsideBounds, MissingProvenance, ProvenanceNameMismatch, InvalidDatabaseAlignment, ..])

Revalidate transported semantics using the same constructor invariants. O(n) transition work without copying the table. No provider lookup occurs. DatabaseSource retains the second-alignment invariant of from_database; Supplied rules retain the full microsecond domain. Provenance is asserted transport metadata, not authentication of an external database or digest.

from_database : Database -> Try(ZoneRules, [UnsupportedSchema(U16), UnsupportedAxis(Str), UnsupportedFutureHandling(Str), MissingProvenance, EmptyName, EmptyVersion, TransitionOutsideValidity, UnorderedTransitions, InvalidOffsetBounds, OffsetOutsideBounds, EmptySpan, ReversedBounds, OutOfRange, ..])

Versioned structural data: no nominal dependency on the supplying package.

offset_bounds : ZoneRules -> OffsetBounds

Authoritative global offset bounds supplied at construction, not merely the extrema observed inside this finite transition table.

offset_at : ZoneRules, PosixBoundary -> Try(FixedOffset, [OutsideValidity, ..])

A transition's new offset applies at its exact boundary.

resolve : ZoneRules, LocalDateTime -> Try(Resolution, [OutsideValidity, OutOfRange, ..])

Complete classification only when every possible candidate is covered.

resolve_occurrence : ZoneRules, LocalDateTime, OccurrencePolicy -> Try(PosixBoundary, [Gap, Ambiguous, OffsetConflict, OutsideValidity, OutOfRange, ..])

Choose explicitly; gaps never silently move to another local label.

appointment : ZoneRules, LocalDateTime, OccurrencePolicy, LocalDateTime, OccurrencePolicy -> Try(PosixSpan, [Gap, Ambiguous, OffsetConflict, OutsideValidity, OutOfRange, EmptySpan, ReversedBounds, ..])

Appointment between independently chosen occurrences, not a selection.

select : ZoneRules, LocalDateTime, LocalDateTime -> Try(Coverage, [EmptySelection, ReversedSelection, OutsideValidity, OutOfRange, ..])

Preimage of the half-open local selection; never an endpoint hull.

selection_cursor : ZoneRules, LocalDateTime, LocalDateTime -> Try(SelectionCursor, [EmptySelection, ReversedSelection, OutsideValidity, OutOfRange, ..])

Prove the full inverse range is covered before any segment is evaluated. The opaque cursor binds the immutable rules and original local selection.

Database : {
    schema : U16,
    axis : Str,
    requested_name : Str,
    canonical_name : Str,
    source_version : Str,
    source_digest : Str,
    profile : Str,
    future_handling : Str,
    start_second : I64,
    end_second : I64,
    initial_offset : I32,
    minimum_offset : I32,
    maximum_offset : I32,
    transitions : List({ second : I64, offset : I32 }),
}
Provenance : [Supplied, DatabaseSource({ requested_name : Str, canonical_name : Str, source_digest : Str, profile : Str })]
Transition : { at : PosixBoundary, offset : FixedOffset }
Definition : { name : Str, version : Str, validity : PosixSpan, initial : FixedOffset, bounds : OffsetBounds, provenance : Provenance, transitions : List(Transition) }

Semantic transport, not the opaque record representation or a codec. Boundaries and transition positions retain exact POSIX microseconds; offsets/bounds retain whole seconds. Provenance is preserved in full.

Resolution : [Gap, Unique(PosixBoundary), Fold(List(PosixBoundary))]
GapTransition : { at : PosixBoundary, before : FixedOffset, after : FixedOffset }
BoundaryChoice : { boundary : PosixBoundary, adjustment : [Exact, BeforeGap(GapTransition)] }

Classification

ZoneRules.Classification :: # (opaque)
rules : Classification -> ZoneRules
local : Classification -> LocalDateTime
gap_transitions : Classification -> List(GapTransition)

Forward transitions whose skipped local interval contains the label. A synthetic table can contain several; never silently select one.

choose : Classification, { occurrence : OccurrencePolicy, gap : [RejectGap, UseOffsetBeforeGap] } -> Try(BoundaryChoice, [Gap, Ambiguous, AmbiguousGap, OffsetConflict, OutOfRange, ..])

Apply explicit policies to complete evidence, without rescanning rules. First/last/gap choice is constant work; matching an asserted offset is O(log n) in fold occurrences. Gap adjustment retains its transition. MatchingOffset checks the pre-gap offset for an explicit gap adjustment.

ClassificationBatch : {
    segments : U64,
    buffered : U64,
    status : [Complete(Classification), Limited({ cursor : ClassificationCursor, reason : [WorkLimit, BufferLimit] })],
}

ClassificationCursor

ZoneRules.ClassificationCursor :: # (opaque)
collect : ClassificationCursor, ClassificationLimits -> Try(ClassificationBatch, [OutOfRange, ..])

One work unit visits one constant-offset segment and its ending transition. Capacity includes matches and forward-gap evidence. Shared cursor snapshots may copy retained buffers on append.

SelectionBatch : {
    segments : U64,
    buffered : U64,
    status : [Complete(Coverage), Limited({ cursor : SelectionCursor, reason : [WorkLimit, BufferLimit] })],
}

SelectionCursor

ZoneRules.SelectionCursor :: # (opaque)
context : SelectionCursor -> { rules : ZoneRules, start : LocalDateTime, end : LocalDateTime }
collect : SelectionCursor, SelectionLimits -> Try(SelectionBatch, [OutOfRange, ..])

One segment unit performs fixed offset arithmetic and one ordered builder append. Rejected/empty segments still consume work. Shared output appends can copy up to max_members retained spans. Zero budgets return Limited; no incomplete coverage is exposed as a complete value.