tantek.com

Why You Should Use Timezone Offsets Not Timezone Names

on (ttk.me b/4cZ1) using BBEdit

Timezones are one of the quirkiest things any programmer has and will ever have to code, because they’re a political construct. They were and are decided by largely non-scientific non-technical politicians. But it’s worse than that, timezones themselves change over time. What timezone a place is in, and worse, daylight savings time, and when daylight savings time starts and stops all change, pretty much every year some place on earth.

Thus the moment you depend on a timezone in your data format, database, storage, files, your persistent canonical copy of your information, you’ve made your data fragile and vulnerable to passive corruption over time. Fragile to programmer errors (programmers get quirky things wrong all the time), and vulnerable to its meaning being changed by political bodies you have no (or nearly no) control over.

Solution one: UTC all the times

There are two solutions programmers have adopted to avoid political and temporal timezone problems, the first is to always store times (and dates!) as UTC, or "Z" time.

The problem with this “UTC all the times” approach is that it makes harder for humans (including yourself) to inspect & verify stored times.

Data that’s harder for humans to inspect and verify is also more prone to errors, especially small passive errors that go unnoticed. Programmers who have to debug such data are humans. Harder for them means harder to debug, means more bugs that survive longer. QED.

Solution two: local time & UTC offset

Rather than UTC all the things (or at least times), the second approach is to store precisely what the local time was at that time, with a time offset to UTC. This way the time (and date) is inspectable and verifiable as what you saw on a clock at that time. What you remembered seeing.

Times with offsets are also automatically convertible from local observed time to UTC and thus machine-processable into a universal timeline, regardless of past or future timezone changes. It’s the approach we’ve taken in microformats for quite some time and found that it helps keep data DRYer.

One possible exception to this “use an offset to UTC” approach are times for things that happen purely online. Web servers have their own clocks, likely set to UTC, and independent of any daylight time savings changes etc. When such servers receive messages, like a webmentions, or other HTTP requests, it makes sense to store them in the same “offset” as the server’s own time, UTC.

Here’s both an offset and exceptional UTC time from an actual email I received.


... 08:34:12 -0700
... 15:34:41 UTC 

The first time shows when a user (in a physical timezone) sent an email. The second shows when an email server (set to UTC) received it 29 seconds later (assuming synchronized clocks).

I’m not going to provide complete examples of the bad approaches because I don’t want you to even think of using them. I’ll just leave you with this, if you see things like:

... America/Los Angeles ...

in your data, you’re depending on named timezones and making a mistake.

The best you can do to avoid this problem, or to “clean” such data is if you have access to it close to the time of creation (when it is unlikely there have been any timezone changes between when the data was created and your present time), automatically convert the named timezone reference into an absolute time +/- numerical hours (and minutes) offset from UTC, and then store that with the time, instead of the named timezone.

Bonus: “Set Automatically” Breaks Your Clock

Here’s a bonus problem. That seemingly useful “Set [timezone] Automatically” feature in computers, phones, works reasonably well on land, sometimes fails briefly when flying across timezones.

However, on a ship that’s nearly completely off the grid, “Set [timezone] Automatically” fails epically.

Say if you’re taking a cruise from Seattle to Alaska, and hit the open ocean, far out of the reach of any landbased wifi or cell towers that “Set Automatically” depends on. It may fallback to shipboard wifi or perhaps even a shipboard cell tower. But “Set Automatically” based on wifi SSID databases or cell tower triangulation assumes that neither of those things move.

Actual result: as we traveled up to Alaska and now back, anyone using “Set Automatically” in their iPhones etc. found their clocks automatically bouncing between an hour more forward than they should be (based on Seattle) and back. Their smarter devices were dumber at the simple task showing the time. I didn’t see anyone with an Apple Watch to see how good it was at telling time on a ship.

Future vs Past Times

Addendum 2015-08-13: James Socol pointed out to me that future dates are more problematic since they are subject to possible timezone/DST definition changes, whereas such definitions appear to be frozen for past times. The techniques in this post are for storing past times, which was implied above when I said:

…what you saw on a clock at that time. What you remembered seeing.

Emphasis added for the deliberately past tense in the text.

How to store future times is left as an exercise for the reader, though you may want to consider different use-cases differently (e.g. future human events where they assume what local clocks will show will match the future time they were shown, vs. again, servers, perhaps coordinating with other servers.) and take a look at this recent article: 2015-03-19 Lau Taarnskov: How to save datetimes for future events, also passed along by James.