Subscriber only

A brief guide to time for developers

Avatar of the author Willem Schots
4 Dec, 2023
~11 min.
RSS

Organisms have been measuring time long before humans walked this Earth, with sunlight driving their Circadian rhythms.

So it’s no surprise that even now, we still want our clocks to have a relationship with the Sun.

In most places solar noon falls somewhere around 12:00 - 13:00. However, the Sun can’t be everywhere at once, when it’s solar noon at one place, it’s solar midnight on the other side of the Earth.

We need a way to coordinate these clocks. We have worldwide social, commercial and technical systems we want to run!

A lot of these systems rely on computers. Which is where the focus of this guide will be.

First, we will look at some background on time:

  • Local time.
  • A worldwide time standard called UTC.
  • Time zones.

Then we will discuss how computers deal with time:

  • Clocks and system time.
  • Network Time Protocol (NTP).
  • Time zones.
  • Leap second handling.
  • Measuring time.
  • Calculating with time.

Guide overview

There are quite a lot of acronyms and different concepts at play in this guide.

I have created a little map that shows you how quickly how different subjects relate to each other. Click the picture below to open it in a new tab.

diagram highlighting the number of available elements in the array of a slice
How the concepts relate to each other (click to open in new tab)

Time is fuzzy

While time has a hard physics component to it, the understanding measurement and coordination is very much shaped by people.

There have been many different understandings and conventions around time, but this “fuzziness” is not just an historical thing:

  • Time zones change for political and social reasons.
  • The rules around Daylight Saving Time also change for the same reason.
  • Leap seconds are decided by a committee, not an algorithm.

So keep that in mind when thinking about time.

Local time / Wall clock time

The clock on your wall or your (old-school) watch tells you the local time or wall clock time.

If you were to travel and take the clock with you, you might need to adjust it read the correct local time again.

Possibly you might need to adjust your clock for daylight saving time as well, more on that later.

You will usually make this adjustment based on a reference clock. A clock that you know is correct in for this new location, maybe one on tv or at a nearby airport or train station.

But how does this reference clock know the correct time?

Well.. it’s based on another reference clock.

Coordinated Universal Time (UTC)

Maybe you’ve encountered the term UTC. It stands for Coordinated Universal Time (they compromised by combining the French and English acronyms).

It’s the primary standard for timekeeping worldwide. UTC combines two other standards:

  • TAI: International Atomic Time, a time scale that uses hundreds of atomic clocks around the world to measure time.
  • UT1: Universal Time, a time standard based on the Earth’s rotation.

UTC divides time into seconds, minutes, hours and days. These are defined as follows:

  • Second: Corresponds to a SI second, defined as a number of vibrations of a caesium atom.
  • Minute: Usually 60 seconds. But can be 59 or 61 seconds as well.
  • Hour: 60 minutes.
  • Day: 24 hours.

As you can see, minutes have a variable duration in UTC, and in turn so do hours and days.

This variability is due to leap seconds.

Leap seconds

Without leap seconds, an hour would always take 60*60=3600 seconds and a day would always take 24*3600=86400 seconds.

However, the time it takes for the Earth to rotate varies, it’s not exactly 86400 seconds. This difference needs to be corrected for, otherwise clocks would slowly drift out of alignment with the sun. Making UTC less useful for everyday applications.

The correction is done using leap seconds.

The UTC standard allows for a positive or negative leap second to be inserted at the end of specific months.

On a day without leap seconds, the last minute of a day will have 60 seconds. The end of that day looks like this:

...
23:59:58
23:59:59
00:00:00 <- new day begins
00:00:01
...

When a positive leap second is inserted, the last minute of that day will have 61 seconds:

...
23:59:58
23:59:59
23:59:60 <- leap second
00:00:00 <- new day begins
00:00:01
...

A negative leap second insertion will only have 59 seconds.

...
23:59:58
00:00:00 <- new day begins
00:00:01
...

At the time of writing 27 positive leap seconds have been inserted since UTC came into effect.

Unfortunately, the rotational speed of the Earth varies in an unpredictable way and leap seconds are inserted based on observations. We don’t have an algorithm or calculation that can give us the number of leap seconds for a specific date.

The decision to insert a leap seconde is made by a standards organization called the "International Earth Rotation and Reference Systems Service" or IERS for short. The decisions are announced twice per year.

This has consequences for calculating intervals using UTC:

  • You need to know how many leap seconds happened between two UTC times.
  • If one of the UTC times is far enough in the future, you can’t calculate the exact interval. You don’t know how many leap seconds may be inserted.

We come back to this in the section on Calculating with time.

As of 2022, there is a resolution to abolish leap seconds, but it’s unclear what they will be replaced with.

Leap years

Leap seconds are not the same thing as leap years. In the Gregorian Calendar, some years contain an additional day (29th of February) to keep the calendar synchronized with the seasons of the year.

Unlike leap seconds, leap years are predictable:

Every year that is exactly divisible by four is a leap year, except for years that are exactly divisible by 100, but these centurial years are leap years if they are exactly divisible by 400. For example, the years 1700, 1800, and 1900 are not leap years, but the year 2000 is.

Leap years are not a feature of UTC, but of the Gregorian Calendar. A way to organize the days of the year.

Time zones

Time zones are geographical areas that use the same time for legal, commercial and social purposes. They don’t strictly follow longitudes. Each country’s government decides how and what time zones apply within its borders.

Map of the time zones. Different colors use the same UTC offset.
Map of all time zones. Colors indicate UTC offsets. (see latest version on Wikipedia).

Time zones are defined using offsets from UTC.

For example:

  • Nigeria observes West Africa Time, which has offset UTC+1.
  • Iceland observes Western European Time, which has offset UTC+0.
  • Cape Verde observes Cape Verde Time, which has offset UTC-1.

So when it’s 16:00 in Lagos (Nigeria). It will be:

  • 15:00 in Reykjavík (Iceland).
  • 14:00 in Praia (Cape Verde).
The example above shown on a timeline
15:00 UTC in Nigera, Iceland and Cape Verde.

However, not every time zone is defined using a single offset.

Daylight saving time (DST)

Some time zones are defined using two offsets from UTC, one offset is used in the summer, the other in the winter.

This is known as daylight saving time, it’s used to maximize the number of daylight hours after a typical “nine to five” workday during the summer.

Map indicating which countries use DST
Blue and orange regions use DST (see latest version on Wikipedia).

If, when and how daylight saving time applies is again decided by the countries government.

Time and computers

Let’s take a look how our logic-loving pc’s, laptops, smartphones and other devices deal with time.

Clocks

A lot of systems have a hardware clock on their motherboard, called the “Real-Time Clock” (RTC). This is battery-powered and keeps track of time even when the system is powered off.

The RTC can be adjusted manually before system startup through the BIOS or UEFI settings.

Reading the RTC is somewhat slow. When an operating system (OS) boots up, it will read the time from the RTC once and maintain its own software based clock. This clock is called the system clock. Usually the system clock has a higher resolution as well.

The system clock can be adjusted by the user or other processes. The OS will adjust the RTC accordingly to ensure consistency during system reboots.

System loads time from RTC, user adjusts time by +8h and system shuts down.

If a system is not connected to a network, it’s up the user to make sure these times are correct. Just like with a regular clock.

However, when connected to a network there is a common protocol that allows systems to synchronize with UTC.

Network Time Protocol (NTP)

Network Time Protocol (NTP) uses a hierarchical network of servers to synchronize the system clocks of connected systems to UTC.

NTP is designed to mitigate the effects of network latency and is usually able to provide an accuracy within tens of milliseconds over the public internet.

There’s a decent chance that the device your reading this on uses a NTP client to synchronize its system time.

Time zones

Since NTP works with UTC, your system will need to know in which time zone it’s located so that it can display the correct local time (and adjust for DST).

This is why you need to select a time zone when setting up a new device.

The available time zones are stored in a database on your system and need to be updated when they change.

In many Linux distributions this data is sourced from the tzdata package. Windows stores time zone information in the registry.

It’s important to note that time zones are not UTC offsets (but they are defined using them). You can’t represent a time zone using only an UTC offset.

Leap second handling

NTP is able to announce leap seconds down the hierarchy of servers to each NTP client. The NTP client then usually passes this information to the OS.

Depending on the OS and configuration the leap second can be dealt with in different ways.

For example:

  • Windows 10+ has full support, the system time will show 23:59:60 before rolling over in 00:00:00.
  • Earlier Windows are not leap second aware, and would require a Windows update to correct the time.
  • By default Linux will step back when it reaches 00:00:00 UTC, and then repeat the 23:59:59 second.
  • Linux also has the option to “smear out” the leap second over a longer period. Which means that the passage of a second in the system doesn’t correspond to a “real second”.

Additionally, time representations deal with leap seconds in different ways. For example, In Unix Time a positive leap second shares the same value as the previous second. In other words, one Unix timestamp may represent two different UTC times.

Measure the passage of time

Using the system time to measure the passage of time in your programs will result in issues.

For example, let’s say you want to check how long a function takes, you:

  1. Read the system time at the start.
  2. Do the function call.
  3. Read the system again.
  4. Check the difference.

As long as the system time is not adjusted this will work fine. But as we have seen before, there is no guarantee. An user, other process or the OS can modify the system time at any point.

For this reason, many OSes also provide a monotonic clock. This is a clock that is guaranteed to return the same clock reading, or an increased clock reading. The monotonic clock is unaffected by adjustments to the system time.

However, the values returned by a monotonic clock have no meaning outside of the current instance of the system. They start at an arbitrary value during system boot, so can only be used to measure the passage of time.

Calculating with time

Almost all (standard) libraries for programming languages ignore leap seconds.

This makes calculating with time relatively straightforward, but not consistent with UTC. An interval between two time objects/structs/etc might be reported as being x seconds, while in UTC it will have been x + leap seconds.

If you do need calculations that are consistent with UTC, you will need to account for the known leap seconds yourself. IERS has a data file available here. As said before, it's not possible to know how many leap seconds will be inserted in the future.

Storing time

Storing time can be a bit of a challenge because the rules around time zones and DST might change underneath you.

For things like system logs and other meta data it’s usually a safe bet to store time in UTC, you can always convert it to a relevant time zone when required.

However, this won’t always work.

A relatively common case is when you need to schedule an event in local time. This event will happen at a specific local time, regardless of the relationship between UTC and local time.

If you store this time as UTC, and the time zone or DST changes the stored time will now be incorrect.

To store a time like this you will need to store both a location identifier and the local time, you can then recalculate the UTC time closer to the event if you do need an UTC time.

This stack overflow answer has more info regarding tricky situations.

Outro

I hope this guide gave you some insight into how all the different technologies and standards work together.

If you have any questions or comments, feel free to reach out.

Further reading and sources

Stack Overflow:

Wikipedia:

Linux System Administrators Guide:

David Madore’s blog:

Meinberg Global:

Microsoft.com

IERS:

Hello! I'm the Willem behind willem.dev

I created this website to help new Go developers, I hope it brings you some value! :)

You can follow me on Twitter/X, LinkedIn or Mastodon.

Thanks for reading!