By Ether DataRequest data sample
All sections

Timezone Database

The IANA tz database is the versioned source of truth for zone offsets and DST rules; an offset is not a zone, and the database itself changes roughly ten times a year.

stable5 min read
Source time
iana_zone
Destination time
instant

Purpose

Every local-to-UTC conversion in this KB — timestamp-to-slot, broadcast day, daypart-to-slots — ultimately depends on one shared resource: the IANA time zone database (also called tzdata or the Olson database). It is the versioned record of every zone's current and historical UTC offset, DST start/end rules, and transition history. This page states what the database actually is, why "an offset" and "a zone" are different things, and why the database's own version number is provenance data that belongs in every conversion's output.

Zones are Area/Location, not offsets

An IANA zone id has the form Area/LocationAmerica/New_York, Europe/London, Asia/Kolkata, Pacific/Auckland — named after a representative location, not a fixed offset. A zone id encodes a complete history of offsets and DST rules for that location, including every past change, so that resolving a timestamp from 1985 or a projected timestamp from 2030 both use the correct rules for that instant. This KB's tz engine is luxon, which reads its rules from the runtime's ICU/tzdata bundle.

An offset is not a zone

Storing "UTC+2" instead of "Europe/Kyiv" looks equivalent for a single instant but is not, because a fixed offset has no DST rule and no future. Europe/Kyiv observed UTC+2 in January and UTC+3 in July prior to Ukraine's 2024 DST discontinuation; a system that persisted "UTC+2" at any point would resolve every subsequent summer timestamp one hour wrong. The rule: persist the zone id, derive the offset per instant — never the reverse, and never treat an offset as a substitute for a zone in storage.

import { DateTime } from "luxon";

// WRONG: a fixed offset has no DST rule and silently drifts across a transition.
const bad = DateTime.fromObject({ year: 2026, month: 7, day: 15, hour: 9 }, { zone: "UTC+2" });

// RIGHT: the IANA zone carries the correct offset for whichever date is given.
const good = DateTime.fromObject({ year: 2026, month: 7, day: 15, hour: 9 }, { zone: "Europe/Kyiv" });

Abbreviations are ambiguous

Three-letter zone abbreviations do not uniquely identify a zone: IST is India Standard Time, Irish Standard Time, or Israel Standard Time; CST is US Central, China Standard Time, or Cuba Standard Time; EST is used by both the US and parts of Australia. None of these carry DST rules, and several collide across completely unrelated regions. This KB's timestamp-to-slot conversion requires a canonical IANA zone id and rejects bare abbreviations or numeric offsets at the input boundary rather than guessing.

Windows zone ids are a different vocabulary

Windows identifies zones by display name — "Eastern Standard Time", "Pacific Standard Time" — which do not match IANA ids 1:1 and, confusingly, Windows' "Eastern Standard Time" actually covers the same DST-observing region as IANA's America/New_York, not literally standard-time-only. Translating between the two vocabularies requires the CLDR windowsZones mapping table (a many-to-one map, since several IANA zones can share one Windows display name); never attempt a string-similarity guess between them.

The database changes — pin and record the version

The tz database is not static: the IANA maintainers cut a new release roughly ten times a year, almost always in response to a government changing an offset, DST rule, or zone boundary with real-world effective dates (historically: Lebanon's abrupt 2023 DST delay, Ramadan-linked DST pauses in Egypt and Morocco, Chile and Fiji adjusting DST windows). A political change frequently arrives with only days of public notice, so there is always a window where the deployed tzdb has not yet caught up to reality — an unavoidable lag, not a bug, but one that must be surfaced rather than hidden. Two systems pinned to different tzdb releases can resolve the identical (wall time, zone) pair to two different UTC instants near any changed transition — the direct temporal analog of a stale administrative-boundary vintage in the geo KB. The mitigation is the same pattern used throughout this KB's provenance model: record the tzdb version actually used (ConversionProvenance.tzdbVersion in lib/time/provenance.ts) on every conversion, and re-resolve any wall time near a known transition once the runtime's tzdb is bumped.

Historical offsets are not today's offset

Zones changed their base offset long before modern DST existed, and some still do: Samoa moved its date-line side in 2011, skipping December 30 entirely to switch from UTC-11 to UTC+13; Venezuela shifted by 30 minutes in 2007 and reverted in 2016; North Korea briefly ran 30 minutes off its neighbors from 2015-2018. A conversion for a historical instant must use the offset that was actually in force then, not the zone's current offset — luxon (via the full tzdata history) resolves this correctly by construction as long as the zone id, not a cached offset, is what was stored.

Edge cases

Tzdb vintage mismatch, political change with short notice, ambiguous zone abbreviations, offset is not a zone, Windows vs IANA ids, and historical offset changes are all direct instances of the hazards above; see Timestamp to Slot for how they surface in the core local-to-UTC conversion, and DST Handling for the gap/fold behavior the database's DST rules produce.

Python parity

Python's standard library zoneinfo module (3.9+) reads the same IANA tz database — either from the operating system's copy or, if absent, from the tzdata PyPI package — so a correctly configured Python runtime resolves zone ids identically to luxon, provided both are running the same tzdb release. Checking that release:

import zoneinfo
print(zoneinfo.TZPATH)         # where the OS/package tzdata is being read from

There is no cross-language guarantee of matching tzdb versions without explicit alignment — pin tzdata to the same release the Node/luxon runtime uses if exact cross-system agreement near a recent transition matters.

Edge cases affecting this page

Timestamp to SlotCanonical slotDST HandlingTime systems & zones