How to save datetimes for future events - (when UTC is not the right answer)
Imagine that it’s January 2015 and you’re making an appointment in a calendar application for a meeting that will take place in Santiago, Chile on the April 30th at 10:00 in the morning.
Your calendar software saves the appointment and you can see that it’s there with the description that you made. 2015-04-30 10:00 in Chile. You even checked the box to get a reminder and think to yourself: “What a time to be alive”. Software can remind us of meetings and keep track of timezones and we no longer have to carry around big bulky paper calendars.
Software saves the day?
April comes around and you are in Santiago and ready for the meeting you made. You forgot the exact time of the meeting so you check your trusty calendar software on your phone. “Ah yes, it’s at 11:00, exactly the time I saved.”
But when you show up for your meeting you are surprised that actually the meeting was at 10:00 and you are an hour late! How did that happen?
The deceit
The software did not actually save the time 10:00. Instead it converted the time to UTC (14:00) and saved that along with the timezone of Santiago/Chile.
But the software is smart and can convert it back from UTC right? Well that just so happens to be a falsehood. In most cases, yes, you can convert back from UTC to the original timezone. But when timezone rules change, converting back to the original timezone can mean that you get a different result.
And that is just what happens in this case. Because Chile has decided to stop using Daylight Saving Time. Good for them. Instead of going off of DST, Chile will essentially keep using the same offset as they are currently on and not set their clock back in the autumn. But back in the middle of January the rules were that they were supposed to go off of DST and set their clocks backward an hour in April.
So what happened was that your software got the newest timezone update. And then when converting back from UTC it used the new rules, while the saved UTC time (14:00) were based on the old rules. With the old rules you would have to subtract 4 hours, but with the new rules only 3. And subtracting 3 hours from 14:00 you get 11:00 instead of 10:00.
This story is not pure fantasy. You might not be going to Chile in April. But a lot of software actually works this way and the time zone in Chile is actually announced to be changing as described.
A solution
Instead of saving the time in UTC along with the time zone, developers can save what the user expects us to save: the wall time. Ie. what the clock on the wall will say. In the example that would be 10:00. And we also save the timezone (Santiago/Chile). This way we can convert back to UTC or any other timezone.
To avoid ambigiuty we also save a third piece of data: the UTC offset. Note that the UTC offset is only there for the rare tie-breaker cases when the timezone does not change, but when there is an ambiguity we know about at scheduling time - that will usually be when the timezone goes off of DST and a range of time (usually an hour) happens twice in autumn when clocks are set back. In this example though this third piece of data is not used for anything.
In the rare cases where the time zone rules change such that the saved wall time suddenly becomes ambiguous or non existant, the saved UTC offset will not help us. There is not much we can do about that though, since we cannot foresee the future. If the saved datetime becomes ambiguous or non existing, we will have to deal with that situation by alerting the user.
You could argue that converting to UTC and saving UTC you will never have an ambiguous or non-existing datetime. That is true, but you have to ask yourself whether it is better to tell the user something incorrect or tell the user the truth. If you want your software to provide the most correct answers, this method is superior to just saving UTC and a timezone.
This solution is implemented in Calecto: A Calendar-Ecto plugin made by yours truly for the Elixir language. If you use Elixir with PostgreSQL and Ecto you can use Calecto to avoid giving the wrong answers when timezone change. Just use the Calendar.DateTime type.
Rule of thumb
What if you are not saving a future time for a meeting? As a rule of thumb: events that have happened in the recent past can safely be saved as UTC. Examples are timestamps for when an email has been sent or a database record has been saved. Your system knows the time in UTC and can save it in UTC. And later you can always convert it to any other time zone.
But in the case of future datetimes such as meetings: converting to UTC and saving UTC + timezone name is not resistant to changes in time zone rules. And remember, time zone rules change all the time.
If you liked this post you might want to follow me on twitter for updates on new posts and more. Twitter handle: @laut