Time zone handling is the part of date-and-time programming that trips up even experienced developers, because the rules it depends on are not physics but politics. A time zone is not a fixed offset from Coordinated Universal Time; it is a jurisdiction’s evolving set of decisions about what its clocks should read. Offsets change, daylight saving time switches twice a year in many places but not all, the dates of those switches move, and governments occasionally redraw or abolish zones outright. A correct conversion between local time and UTC depends on knowing exactly which rules were in force at a particular instant in a particular place.
The authoritative record of these rules is the IANA Time Zone Database, often called the tz database or zoneinfo. The IANA describes it as “code and data that represent the history of local time for many representative locations around the globe,” and notes that it is “updated periodically to reflect changes made by political bodies to time zone boundaries, UTC offsets, and daylight-saving rules.” The project’s own “Theory and pragmatics” documentation explains the scope it commits to: it “attempts to record the history and predicted future” of civil time scales, partitioning the world into zones whose clocks agree about timestamps after the POSIX Epoch of 1970-01-01 00:00:00 UTC, while candidly admitting that fully accurate handling of all pre-1970 local time everywhere “would take far too much effort and guesswork.”
The classic bugs come from treating local time as if it were simple. Storing a wall-clock time without its zone makes it ambiguous: during the autumn daylight saving rollback, a local hour repeats, and the same wall-clock value can name two different instants; during the spring jump forward, an hour does not exist at all. Hard-coding an offset such as “UTC minus five for Eastern time” silently breaks half the year and breaks again whenever a legislature changes the rules. Computing a duration by subtracting two local times across a daylight saving boundary yields an answer off by an hour.
The discipline that grew out of these failures is summarized in one rule of thumb: always store UTC. An instant in time should be recorded as an unambiguous UTC value, and the conversion to a human-facing local time should happen only at the boundary of the system, at display, using the current tz database rules for the relevant zone. Local time is treated as a presentation concern, not as the canonical form in which time is stored or compared.
Time zone handling also interacts with the other clock problems in this library. Conversions still rest on an underlying count of seconds that is subject to the Year 2038 limit on 32-bit systems, and on a UTC scale that is itself adjusted by leap seconds. The IANA database removes one large source of error, the ever-shifting political rules, but it does so only for software that uses it correctly and keeps its copy up to date, since a stale zone database will confidently apply yesterday’s rules to today’s dates.