More than just an interesting annoyance, DST can have important implications for programmers
It must be some kind of universal law that every year you will have a conversation with someone who is furious about Daylight Saving Time. Inevitably it will be someone who thinks it is a needless complication, a throwback to a time when the population was employed in agriculture and entirely irrelevant to the rhythms of modern life. Usually, this person has accidentally woken up an hour earlier than necessary that morning.
Daylight Saving Time (DST) as a concept was officially brought into use in Ontario, Canada in 1908 to make better use of daylight. The first country to use DST country-wide was Germany as a way to reduce the amount of artificial light used during WW1. Since then the reasons for using DST (or not) have become as varied as the countries using it. Some countries have never used DST, while some have and have since stopped.
What are the reasons for keeping daylight saving? There are still benefits to having daylight saving, such as reducing the number of road accidents due to more daylight, economic benefits due to people spending more time outside, and increased energy efficiency as we use less artificial light, although that one is often debated. However, there is also a cost to keeping daylight saving: there is an increase in road accidents in the period after DST changes, international teams can be spread across multiple time zones now with different DST rules, and of course, being an hour late for work.
To understand DST and how best to work with it from a technical perspective, there are three concepts to understand: Coordinated Universal Time (UTC) and UNIX timestamps, and how different countries utilize UTC offsets to set their own time. UTC is essentially the same as GMT (Greenwich Mean Time). A UTC offset is the number of hours plus or negative of UTC. The UNIX timestamp is the number of seconds since midnight of January 1st, 1970 (not including leap seconds), also known as Epoch. The UNIX timestamp for the 1st of January 1970 00:00:00 AM is 0 and the UNIX timestamp for the 1st of January 1970 at 0:01:00 AM is 60. The timestamp at time of writing is 1488973409. To add even more complexity, some systems store UNIX timestamps in microseconds instead of seconds.
Countries that use DST have two time zones: Summer Time and Winter Time. The United Kingdom is UTC+0 in winter and UTC+1 in summer. The time zones are GMT (Greenwich Mean Time) and BST (British Summer Time) respectively. Central European Time (GMT+1) and Central European Summer Time (GMT+2) is another example.
Here’s where things get confusing interesting: In the UK on March 26th 2017 at 01:00 AM the time zone will change from GMT to BST. In other words, going from UTC+0 to UTC+1, adding one hour onto the current time. 00:57, 00:58, 00:59, 02:00. Then, on October 29th 2017 at 02:00 AM the time zone will change from BST back to GMT, or UTC+1 back to UTC+0. One hour will be subtracted, setting the clocks back to 01:00 AM. 01:57, 01:58, 01:59, 01:00. Who said that time travel wasn’t real?
Seriously though, 01:00 – 01:59 just happened twice. The change in DST offset can cause problems when displaying time-related events. Say you developed a logging system: one event is logged at 00:30 GMT, then 45 minutes later a second event is logged at 01:15 GMT:
Event 1: 2017-10-29 00:30:00
Event 2: 2017-10-29 01:15:00
The UK just happened to change from Summer Time to Winter Time between those two events. So after applying Europe/London time zone to those dates:
Event 1: 2017-10-29 01:30:00
Event 2: 2017-10-29 01:15:00
Hold on! The second event shows as being before the first. To display this in a meaningful way we need to either stick to using GMT and have the user convert the time, or append the time zone or UTC offset to each event:
Event 1: 2017-10-29 01:30:00 (GMT+1)
Event 2: 2017-10-29 01:15:00 (GMT+0)
A common mistake when starting to work with date and time across time zones is taking only the DST setting of a date and not the date and time. It’s possible to have an event that spans Summer Time and Winter Time.
Take the following ISO 8601 date strings:
Start: 2017-10-29 00:00:00
End: 2017-10-29 02:00:00
Looking at those dates you would assume that the duration of the event is 2 hours. You could even get those dates in their respective UNIX timestamps and subtract the first from the second to get 7200 seconds or 2 hours. However, as soon as you apply the Europe/London time zone to them, the duration appears as 1 hour. The start time is within BST and the end time within GMT.
Let’s see this in action with a PHP example:
$date1 = new DateTime();
$date2 = new DateTime();
// get the duration in seconds
echo $date2->getTimestamp() – $date1->getTimestamp();
// format $date1
echo $date1->format(‘Y-m-d H:i’);
// format $date2
echo $date2->format(‘Y-m-d H:i’);
3600 // 1 hour
Another challenge when working with Daylight Saving Time is keeping up to date with changes. Actually this applies to time zones in general. Whether it be North Korea changing their UTC offset -30 minutes to create their own time zone (Pyongyang Time) or a government deciding last minute not to go back to Winter Time. In September 2016 the Turkish government announced they would not be reverting to Winter Time and would instead stay in Summer Time. The clocks were due to turn back an hour on October 30th, but instead, they stayed ahead. This is a real challenge for a developer! For most server-side development the programming language in use normally handles any changes to DST using the OS’s time data, synced to a Network Time Protocol (NTP) server. However, that isn’t always the same for frontend development. Say you are building an appointment booking system and you have an event stored in your database for October 30th 09:00 AM (Turkey time). Say you store dates in the ISO 8601 format. (The ISO 8601 string for that time is 2016-10-30T06:00:00 stored in GMT time zone.) To display that date and time to the user in the Europe/Istanbul time zone, you would look up the UTC offset for that particular time in a locally stored config and apply the offset to that date and time above to display it in the local time format: i.e. add 3 hours and format the time. If that config file had not been updated to reflect the new DST settings, you would be displaying the time one hour out. Someone’s missing an appointment!
As challenging as it is, the above scenario can be helped by using a DateTime library such as moment.js which hooks into a database of time zone data from the Internet Assigned Numbers Authority (IANA). But with such uncertainty around the use of DST, it’s important to keep those libraries updated as well.
Since we started Appointedd, we’ve learned a few lessons about Daylight Saving. Our booking software is the only solution that allows each staff member to be in a different time zone (and DST zone!) on different dates. We take the pain out of calculating UTC offsets by automatically determining your own time zone and the person or people you are booking with and doing the calculations for you.
Date and time formatting is seen as a right of passage for any developer and I’m sure most senior developers have a few stories to tell about DST. As well as just being a pain to work with, DST could introduce some serious issues if not handled correctly in mission critical systems. The argument on whether or not to abandon DST tends not to reference the technical issues. The next time you’re having a DST rant, spare a thought for all the developers out there learning the nuances of DST for the first time.