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_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.
provenance : ZoneRules -> Provenance
validity : ZoneRules -> PosixSpan
offset_bounds : ZoneRules -> OffsetBounds
Authoritative global offset bounds supplied at construction, not merely the extrema observed inside this finite transition table.
A transition's new offset applies at its exact boundary.
Complete classification only when every possible candidate is covered.
classification_cursor : ZoneRules, LocalDateTime -> Try(ClassificationCursor, [OutsideValidity, OutOfRange, ..])
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 }
OffsetBounds : { minimum : I32, maximum : I32 }
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))]
OccurrencePolicy : [RequireUnique, First, Last, MatchingOffset(FixedOffset)]
GapTransition : { at : PosixBoundary, before : FixedOffset, after : FixedOffset }
BoundaryChoice : { boundary : PosixBoundary, adjustment : [Exact, BeforeGap(GapTransition)] }
Classification
ZoneRules.Classification :: # (opaque)
resolution : Classification -> Resolution
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.
to_inspect : Classification -> Str
ClassificationLimits : { max_segments : U64, max_candidates : U64 }
ClassificationBatch : {
segments : U64,
buffered : U64,
status : [Complete(Classification), Limited({ cursor : ClassificationCursor, reason : [WorkLimit, BufferLimit] })],
}
ClassificationCursor
ZoneRules.ClassificationCursor :: # (opaque)
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.
to_inspect : ClassificationCursor -> Str
SelectionLimits : { max_segments : U64, max_members : U64 }
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 }
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.
to_inspect : SelectionCursor -> Str