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:

  1. Who manages the list of timezones and their offsets?
  2. How does that information get onto your computer?
  3. 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/BST

This 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   Volgograd

This 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/zoneinfo

Of 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
  1. also known as EDT, the time in New York during the summer
  2. Australian Central Western Standard Time, observed by about a hundred people in "the Easternmost locality of Western Australia".