Time-Zone Database Provenance Conformance
When to Use
- A named-zone wall time is converted in more than one browser, mobile runtime, container, library, or server.
- A client-computed UTC instant can be persisted by a runtime with different civil-time rules.
- A recent rule change, DST gap, or repeated time produces runtime-dependent offsets.
- A deployment needs evidence that time-zone data sources agree before writes resume.
Do not activate for epoch-only values or fixed offsets with no named-zone conversion, nor for simple formatting where no future wall-clock intent crosses a trust boundary.
Prerequisites
- The original wall time, IANA zone, and explicit fold/disambiguation choice.
- Runtime/provider identity for every conversion boundary.
- Synthetic dates safe to evaluate offline. Do not use production records in fixtures.
- Python 3.9+ only when using the optional offline comparator.
Quick Reference
| Question |
Required evidence |
| Which rules ran? |
runtime, provider/source path or package, declared tzdb version when exposed |
| Do rules agree? |
gap, fold variants, recent-rule boundary, offset and resulting UTC instant |
| Version unavailable? |
Record null; never infer a release from one matching result |
| May a write proceed? |
Only after the selected policy and all transition probes allow it |
| Recovery |
Preserve wall + zone + fold, align the intended data source, rerun identical probes |
Procedure
- Classify the value. Stop with
not_applicable for epoch/fixed-offset-only data. For named zones, preserve the wall fields, IANA zone, and fold/disambiguation separately from any computed instant.
- Inventory every boundary. Record runtime/version, provider, selected source path or package, and declared tzdb version. Use
unknown, not a guessed release, when the runtime does not expose one.
- Freeze probes before comparing. Include one known nonexistent wall time (
gap), both alternatives of one repeated wall time (fold), and a date spanning the rule change relevant to the incident (recent-rule). Add an ordinary control.
- Observe each runtime independently. For every probe record validity, offset seconds, and UTC instant. Do not let one runtime generate another runtime's expected values.
- Compare behavior and provenance separately. Equal outputs are behavioral evidence, not proof that providers or releases are identical. Divergent validity, offset, or instant is a violation. Unknown provenance is an observation unless project policy explicitly requires a declared version.
- Gate persistence. Block writes whenever required transition coverage is missing, a probe diverges, or a provenance requirement fails. Preserve the user's wall time, zone, and fold for review; do not silently replace them with the server's current conversion.
- Recover non-destructively. Pin or update the application/container dependency through normal deployment controls, or route conversion to the selected authoritative runtime. Never rewrite host tzdata in place. Rerun the exact frozen probes before allowing writes.
Offline comparator
Prepare a synthetic JSON document with two or more observations:
{
"schema_version": 1,
"mode": "named-zone",
"policy": {"require_declared_version": true},
"observations": [
{
"runtime_id": "browser-a",
"provider": "Intl",
"version": null,
"zone": "America/Vancouver",
"probes": [
{"id":"gap","kind":"gap","wall":"2026-03-08T02:30:00","fold":null,"valid":false,"offset_seconds":null,"utc":null}
]
}
]
}
A complete document must include matching gap, fold, and recent-rule probe IDs in every observation. Run:
python3 scripts/tzdb_compare.py observations.json
Exit 0 means allow or not_applicable; 1 means policy blocked; 2 means invalid input; 74 means output could not be written. The helper is offline, rejects unknown fields and non-finite JSON, and never loads zone files or changes system state.
Pitfalls and Safety
- A zone name is not a version.
America/Vancouver can resolve through different rule sets.
- One matching present-day offset does not cover future transitions, historical corrections, gaps, or folds.
- Do not call a client wrong merely because its source differs; identify the product's selected authority and compare frozen behavior.
- Never auto-update host files, rewrite stored instants, or probe production writes. Use normal package/image rollout and rollback.
- Hashes can identify byte equality but do not reveal a release; log only non-sensitive source metadata.
Verification
Completion requires all of the following:
- provenance is explicit or honestly
unknown for every boundary;
- gap, both fold choices, and a relevant rule boundary were observed independently;
- offsets and resulting instants were compared;
- an unresolved mismatch demonstrably blocks persistence;
- recovery reruns the unchanged probes and reaches
allow without mutating host data.
Run packaged tests from the installed skill directory:
PYTHONDONTWRITEBYTECODE=1 python3 tests/test_tzdb_compare.py
Evaluation Prompts
- Normal: Browser-to-server named-zone persistence where tzdb versions may differ; require provenance, transition probes, and a write gate.
- Difficult edge: Android APEX versus system fallback and a container with no exposed release; require
unknown provenance plus gap/fold/recent-rule evidence.
- Should not activate: Epoch seconds with fixed
+00:00 and no named-zone wall-clock conversion.
Sourced Facts and Recommendations
Sourced facts: Android can update time-zone rules independently of a full system update; the IANA tz database records historical and predicted civil-time rules; independent Jiff and Event Espresso reports show stale-source and browser/server divergence failures.
Recommendations: the exact probe set, require_declared_version policy, persistence gate, and non-destructive recovery sequence above are conservative project controls synthesized for this skill.
Sources
1---2name: timezone-database-provenance-conformance3description: Use when named-zone wall times cross browsers, mobile runtimes, containers, or servers and stale or divergent tzdb rules could change offsets or persisted UTC instants.4license: MIT5---67# Time-Zone Database Provenance Conformance89## When to Use1011- A named-zone wall time is converted in more than one browser, mobile runtime, container, library, or server.12- A client-computed UTC instant can be persisted by a runtime with different civil-time rules.13- A recent rule change, DST gap, or repeated time produces runtime-dependent offsets.14- A deployment needs evidence that time-zone data sources agree before writes resume.1516Do **not** activate for epoch-only values or fixed offsets with no named-zone conversion, nor for simple formatting where no future wall-clock intent crosses a trust boundary.1718## Prerequisites1920- The original wall time, IANA zone, and explicit fold/disambiguation choice.21- Runtime/provider identity for every conversion boundary.22- Synthetic dates safe to evaluate offline. Do not use production records in fixtures.23- Python 3.9+ only when using the optional offline comparator.2425## Quick Reference2627| Question | Required evidence |28| --- | --- |29| Which rules ran? | runtime, provider/source path or package, declared tzdb version when exposed |30| Do rules agree? | gap, fold variants, recent-rule boundary, offset and resulting UTC instant |31| Version unavailable? | Record `null`; never infer a release from one matching result |32| May a write proceed? | Only after the selected policy and all transition probes allow it |33| Recovery | Preserve wall + zone + fold, align the intended data source, rerun identical probes |3435## Procedure36371. **Classify the value.** Stop with `not_applicable` for epoch/fixed-offset-only data. For named zones, preserve the wall fields, IANA zone, and fold/disambiguation separately from any computed instant.382. **Inventory every boundary.** Record runtime/version, provider, selected source path or package, and declared tzdb version. Use `unknown`, not a guessed release, when the runtime does not expose one.393. **Freeze probes before comparing.** Include one known nonexistent wall time (`gap`), both alternatives of one repeated wall time (`fold`), and a date spanning the rule change relevant to the incident (`recent-rule`). Add an ordinary control.404. **Observe each runtime independently.** For every probe record validity, offset seconds, and UTC instant. Do not let one runtime generate another runtime's expected values.415. **Compare behavior and provenance separately.** Equal outputs are behavioral evidence, not proof that providers or releases are identical. Divergent validity, offset, or instant is a violation. Unknown provenance is an observation unless project policy explicitly requires a declared version.426. **Gate persistence.** Block writes whenever required transition coverage is missing, a probe diverges, or a provenance requirement fails. Preserve the user's wall time, zone, and fold for review; do not silently replace them with the server's current conversion.437. **Recover non-destructively.** Pin or update the application/container dependency through normal deployment controls, or route conversion to the selected authoritative runtime. Never rewrite host tzdata in place. Rerun the exact frozen probes before allowing writes.4445### Offline comparator4647Prepare a synthetic JSON document with two or more observations:4849```json50{51 "schema_version": 1,52 "mode": "named-zone",53 "policy": {"require_declared_version": true},54 "observations": [55 {56 "runtime_id": "browser-a",57 "provider": "Intl",58 "version": null,59 "zone": "America/Vancouver",60 "probes": [61 {"id":"gap","kind":"gap","wall":"2026-03-08T02:30:00","fold":null,"valid":false,"offset_seconds":null,"utc":null}62 ]63 }64 ]65}66```6768A complete document must include matching `gap`, `fold`, and `recent-rule` probe IDs in every observation. Run:6970```bash71python3 scripts/tzdb_compare.py observations.json72```7374Exit `0` means `allow` or `not_applicable`; `1` means policy blocked; `2` means invalid input; `74` means output could not be written. The helper is offline, rejects unknown fields and non-finite JSON, and never loads zone files or changes system state.7576## Pitfalls and Safety7778- A zone name is not a version. `America/Vancouver` can resolve through different rule sets.79- One matching present-day offset does not cover future transitions, historical corrections, gaps, or folds.80- Do not call a client wrong merely because its source differs; identify the product's selected authority and compare frozen behavior.81- Never auto-update host files, rewrite stored instants, or probe production writes. Use normal package/image rollout and rollback.82- Hashes can identify byte equality but do not reveal a release; log only non-sensitive source metadata.8384## Verification8586Completion requires all of the following:8788- provenance is explicit or honestly `unknown` for every boundary;89- gap, both fold choices, and a relevant rule boundary were observed independently;90- offsets **and** resulting instants were compared;91- an unresolved mismatch demonstrably blocks persistence;92- recovery reruns the unchanged probes and reaches `allow` without mutating host data.9394Run packaged tests from the installed skill directory:9596```bash97PYTHONDONTWRITEBYTECODE=1 python3 tests/test_tzdb_compare.py98```99100## Evaluation Prompts1011021. **Normal:** Browser-to-server named-zone persistence where tzdb versions may differ; require provenance, transition probes, and a write gate.1032. **Difficult edge:** Android APEX versus system fallback and a container with no exposed release; require `unknown` provenance plus gap/fold/recent-rule evidence.1043. **Should not activate:** Epoch seconds with fixed `+00:00` and no named-zone wall-clock conversion.105106## Sourced Facts and Recommendations107108**Sourced facts:** Android can update time-zone rules independently of a full system update; the IANA tz database records historical and predicted civil-time rules; independent Jiff and Event Espresso reports show stale-source and browser/server divergence failures.109110**Recommendations:** the exact probe set, `require_declared_version` policy, persistence gate, and non-destructive recovery sequence above are conservative project controls synthesized for this skill.111112## Sources113114- [Android time-zone rules](https://source.android.com/docs/core/permissions/timezone-rules)115- [IANA Theory and pragmatics of the tz code and data](https://data.iana.org/time-zones/tzdb/theory.html)116- [Jiff issue 582: Android stale tzdata source](https://github.com/BurntSushi/jiff/issues/582)117- [Event Espresso issue 4197: stale browser database changes persisted instants](https://github.com/eventespresso/event-espresso-core/issues/4197)