What a consumer (a Rust crate, a test fixture, an embedded bundle) may rely on when it ingests output produced by zic-rs. This is the bridge between the compiler and its downstream users; it states guarantees and — honestly — current limits.
For every zone zic-rs compiles (it fails closed rather than emit anything it cannot produce correctly):
- Valid TZif per RFC 9636. The full layout —
v1 (32-bit) block + v2+ (64-bit) block + footer, big-endian, with header counts that match
the data. We round-trip our own output through a reader (
tzif::validate) as a self-check. - Semantic match against reference
zic/zdumpover a declared year horizon (thecompare --mode zdump --horizon LO,HIoracle): same UT instants, UT offsets, DST flags, and abbreviations within the window. Behaviour outside the declared window is not asserted. (Byte-parity is additionally pinned only for fixed-offset fixtures with a checked-in reference blob.) - Deterministic output. The same source + selection yields identical bytes; nothing depends on wall-clock time or unordered iteration reaching the output.
- Safe layout. Output lands strictly under the explicit
--outroot; zone/link names are validated against traversal (ZIC008); writes are atomic and never clobber without--force. See security.md.
A consumer that needs traceability can request, alongside the tree:
- an alias/canonical manifest —
compile --alias-map <path>writesalias-map.json(schemazic-rs-alias-map-v1): which identifiers are canonical zones vs links, link targets, per-file SHA-256, and a summary withidentifiers/canonical_zones/linksandduplicated_byte_links(links materialised as byte copies — answers jiff#258's alias-duplication accounting); - a compile-provenance manifest —
compile --manifest <path>writeszic-rs-manifest.json(schemazic-rs-compile-manifest-v8):zic_rs_version; atzdbblock (detected-vs-claimed version +version_status, source path + SHA-256); asource_inputsblock (structuralkind- ordered per-file list with hashes + order-sensitive
aggregate_hash, T12.3); abuild_profileblock (emit_style/range/redundant_until/link_mode/output_tree/leap_source— as of T12.5d it carries no source-variant placeholders); alink_profileblock (link counts +alias_map_sha256 - selected/omitted link hashes, T12.4b); a
source_profileblock withbackward_evidence(T12.4d) +backzone_evidence(T12.5b, hash-anchored to the pinned reference release) +packratlist_evidence(T12.5c, backzone scope from an admitted generation-policy input — never from compilesource_inputs) +dataform_evidence(T12.5d, encoding form hash-matched against the pinned 2026b.ziartifacts, +recipe_hash/generated_from) axes — detected/claimed/status, hash-backed-or-claim-only, never inferred; the zones/links touched; and anoracleblock.
- ordered per-file list with hashes + order-sensitive
The manifest describes this invocation, not the repo's test status. A bare compile
does not run the oracle, so its oracle block is {"mode":"not-run","result":"not-run"} —
it never infers a match from the test suite. tzdb version detection and an IANA release URL
are still future work (recorded as unknown today); per-fixture pins also live in
fixtures/MANIFEST.toml.
- The declared subset only: unsupported constructs (inline-save eras with a
%s/slashFORMAT,24:00/negative compiled times, recurring rules whoseONis a fixed numeric day (no weekday), and leap seconds) fail closed — they are never silently approximated. See unsupported-syntax.md. (Compatibility/breadth features now supported:FROM = minimum→1900, inline-save literal/%z, negative inline SAVE (law 7),Sun<=N/Sat<=NrecurringON(law 10), and genuinely mixed-in-era finite+recurring final eras — see supported-syntax.md.) - The footer is not prophetic — it projects current rules; it is not a prediction of future civil-time law. See tzif-notes.md.
- zic-rs is a producer/build tool, not a datetime library. To read local time, use a consumer (tz-rs/jiff); see rust-ecosystem.md.
tz-rs (reads TZif), TZif reader crates, embedded bundles, and test fixtures. Optional
ecosystem smoke tests (roadmap T3.4d, behind a feature flag) will demonstrate that a real
Rust reader loads zic-rs-generated TZif.