Dealing with time on computers is so much fun

When a computer boots up, the operating system typically takes it’s current idea of what time it is from the hardware clock. On shutting down, it typically pushes back it’s own idea of what time it is back to the BIOS so that the clock is up-to-date relative to what time the operating system thinks it is.

The operating system while running tries to keep the concept of what time it is by having a counter it increments based on the kicking of some interval timer (on newer operating systems this is not strictly how it works, but the idea is similar).

The problem is, of course, that the thing that generates the timer isn’t completely accurate. As a result, over time, the operating system clock drifts in relation to what the real time is. This drift depends on the quality of the hardware going into the computer. Some are more expensive and thus don’t drift as much, some are cheap and drift quite a lot (some are so bad as to cause a drift of many minutes over the course of a day).

This is generally undesirable, I want to be reminded that I have a meeting before it actually starts so I can load up on a cup of coffee beforehand. How do we fix this?

The answer is to ask another computer and hope that it has a better idea of what time it is than this current one.

The most common protocol used for getting time over a network is the Network Time Protocol (NTP). In it’s simplest mode, you ask the remote system what time it is and then shift your time to match the time from the remote system by adjusting the time of your local system over time (to prevent confusing jumps in time where it goes from 9am to 8.15 instantly confusing you no end). The fancier methods involve asking multiple systems for the time, constructing a model of how crap your clock is relative to their clock and using that to constantly adjust your time to try to keep it in sync with the remote system. You periodically ask the remote systems for the time and use it to update your model. With this you can typically keep your clock within ~100ms of the time that’s considered ‘now’.

This is fine, we now have a relatively accurate clock which we can ask what time it is. The only problem is that depending on where you are in the world, your idea of what time it is has been altered by the wonderful concept of the timezone.

A properly written operating system should keep time without caring about what timezone you belong to. When you ask for a time it gives you a number which is unambiguous. This is vitally important when it comes to trying to perform operations on the time. If it’s unambiguous, then you can use it for mathematical operations such as determining the difference between two times. If it’s ambiguous then you’ll have trouble trying to do anything with it.

When you introduce the possibility of ambiguity into the representation of time, problems arise. For example, if I ask you how many minutes are there between 01:30 and 01:35, the obvious answer of 5 minutes my be incorrect because 01:30 is BST and 01:35 is GMT, which means the difference is 65 minutes; plus if I just showed you that time the day after a daylight savings transition without telling you what timezone it was in you wouldn’t be able to tell.

But what does this actually mean? For most developers, you should follow two cardinal rules:

  • Avoid changing the date from it’s unambiguous form until the last possible moment.
  • Always store the date in it’s unambiguous form.

If you have to store a date with a timezone, store the timezone as separate information to the actual unambiguous date, that way you can easily perform operations on the unambiguous time, and display the original time relative to the timezone it was supplied.

This doesn’t even get into the complexities of calendars. While the West generally uses on the Gregorian calendar, many other places in world don’t use that calendar (there are a lot of them).

Standard C (POSIX) is poorly supplied with an API for dealing with dates and times, especially in relation to timezones. You can generally set the timezone of the application, but it’s a thread-unsafe abomination that really should DIAF.

Most of the newer languages have significantly better date/time support. I’ll go through them in a series of posts, starting with C#.