How timezones work (I think)
Up until recently I had a very vague understanding of how timezones are standardised on computers. I was forced by a recent guix issue to understand them in a bit more detail. It seemed worth writing down.
What a time zone is
Everything is defined in terms of Coordinated Universal Time (UTC).
You have UTC offsets such as
UTC-04:00[1]
and UTC+08:45.[2]
Because the UTC offset might change, either due to predictable events (daylight savings time),
or unpredictable events (being invaded), we break the world up into
administrative regions that observe the same time. This is what a time zone actually is.
Examples include America/New_York and Europe/London. Usually you specify your time zone
when you install the operating system on your computer.
But what does your computer actually do when you select your time zone in the settings menu?
How your computer deals with time zones
Some obvious questions recommend themselves:
- Who manages the list of timezones and their offsets?
- How does that information get onto your computer?
- How is your timezone specifically stored?
There is a certain database, the Time Zone Database, published by IANA.
It is distributed as a bunch of plain text files, which contain encoded
definintions of the given timezones (and lots of comments explaining why
the definition is what it is).
For example, here is the start of the definition for the Europe/London zone:
# Zone NAME STDOFF RULES FORMAT [UNTIL]
Zone Europe/London -0:01:15 - LMT 1847 Dec 1
0:00 GB-Eire %s 1968 Oct 27
1:00 - BST 1971 Oct 31 2:00u
0:00 GB-Eire %s 1996
0:00 EU GMT/BSTThis database is then released every 3 months, compiled into a binary format
for rapid access, and packaged for linux distributions (usually named something
like tzdata). In most distributions, this means that a bunch of files
exist in /usr/share/zoneinfo, with familiar names:
λ. ls /usr/share/zoneinfo/Europe/
Amsterdam Belgrade Budapest Gibraltar Jersey Lisbon Malta Nicosia Riga Saratov Tallinn Vaduz Warsaw
Andorra Berlin Busingen Guernsey Kaliningrad Ljubljana Mariehamn Oslo Rome Simferopol Tirane Vatican Zagreb
Astrakhan Bratislava Chisinau Helsinki Kiev London Minsk Paris Samara Skopje Tiraspol Vienna Zaporozhye
Athens Brussels Copenhagen Isle_of_Man Kirov Luxembourg Monaco Podgorica San_Marino Sofia Ulyanovsk Vilnius Zurich
Belfast Bucharest Dublin Istanbul Kyiv Madrid Moscow Prague Sarajevo Stockholm Uzhgorod VolgogradThis is where applications will expect to find it. It's even mentioned in the
Filesystem Hierarchy Standard.
On distributions like Guix System, which do not adhere to FHS and have a nearly-empty /usr directory,
you can declare the $TZDIR environment variable to point to the installed zoneinfo database.
λ. echo $TZDIR
/home/daniel/.guix-profile/share/zoneinfoOf course there is nothing stopping an application from bundling its own version of the timezone database, and managing that itself, but such an application might end up being incompatible with other applications on the device.
Your specific timezone is often encoded by making the file /etc/localtime a symbolic link to one of these files.
If a particular process should use a different timezone, the $TZ environment variable can be used:
λ. stat /etc/localtime
File: /etc/localtime -> /gnu/store/6i4pg341jwzkpaci7d159vk705riwvlz-tzdata-2025a/share/zoneinfo/Europe/London
...
λ. date
Mon 20 Apr 11:45:49 BST 2026
λ. TZ="America/New_York" date
Mon 20 Apr 06:45:59 EDT 2026- also known as
EDT, the time in New York during the summer↩ - Australian Central Western Standard Time, observed by about a hundred people in "the Easternmost locality of Western Australia".↩