
What every developer should know about time - fogus
http://blogs.windwardreports.com/davidt/2009/11/what-every-developer-should-know-about-time.html
======
mseebach
I hate to be pedantic, but:

> .. UTC (also known as Greenwich Mean Time)...

> (Interesting note, UTC only matches the time in Greenwich during standard
> time. When it is DST there, Greenwich and UTC are not identical.)

Time is really really hard, and I don't claim to understand it, but going
lightly with basic facts is a bad idea.

First, GMT != UTC. UTC observes leap seconds, GMT don't. That doesn't matter,
right up until when it suddently does matter.

Second, it's grossly confusing to talk about "Greenwich time", i.e. the time
at the location, when you don't mean GMT. Neither UTC nor GMT observes DST,
Britain, in which Greenwich is located, does.

~~~
notauser
If you have a good reference for leap seconds and platform implementations
thereof I would love to read it.

~~~
mseebach
Leap seconds aren't implemented, they're announced:

 _The International Earth Rotation and Reference Systems Service (IERS)
announces the insertion of a leap second whenever the difference between UTC
and UT1 approaches 0.6 s, to keep the difference between UTC and UT1 from
exceeding 0.9 s._

<http://en.wikipedia.org/wiki/Leap_second>

UT1 is the astronomical time. So far, there are 24 leap seconds.

Also, I got it wrong: Leap seconds aren't the difference between GMT and UTC,
but between UTC and e.g. GPS or International Atomic Time.

------
spuz
I can't stress enough how important it is to get dates, times and timezones
correct in your code to avoid embarrassment or worse. Just yesterday, just
when we thought we'd ironed out all the timezone issues in our production
code, our system rejected a bunch of customer data thinking the current time
was actually an hour ahead of what it was. It turns out to be a bug in the
Oracle JDBC driver that happens when connections are kept open while DST flips
the clocks back but it goes to show that you can never be too careful when
dealing with times and timezones.

~~~
willwagner
And don't forget the Zune time bug which caused a bit of embarrassment for
Microsoft last year/beginning of this year. It's hard to test every boundary
and edge condition, especially if you are relying on black box testing to
catch bugs.

------
mrduncan
Fun story regarding the UTC abbreviation: English speakers wanted it to be CUT
(coordinated universal time), while French speakers wanted TUC (temps
universel coordonné). They compromised on UTC.

[http://en.wikipedia.org/wiki/Coordinated_Universal_Time#Abbr...](http://en.wikipedia.org/wiki/Coordinated_Universal_Time#Abbreviation)

------
camccann
Correct handling of dates and times in the general case (i.e, arbitrary time
zones and arbitrary dates in the past, including calendar and time zone
changes) is one of those things that I have tentatively filed under "too
complicated for me to hope to get right", along with "correct handling of
Unicode"[0] and "concurrency with fully shared mutable state"[1].

In practice, my rule is that if you can avoid dealing with the full complexity
of date/time, such as by working in absolute time as much as possible and
explicitly restricting the allowed date range, then do so; anywhere you have
to work with dates/times as non-opaque values, always prefer library functions
that _explicitly say they conceptually do what you want_ , not ones that
provide low level operations that let you do what you want, probably, at least
in your own locale, for now. If your platform provides only a broken date/time
implementation, use a third-party library.

Fun anecdote time! When an international group pushed for a standardized,
absolute time, the English and French both wanted it to be named in their own
language, "coordinated universal time" vs. "temps universel coordonné". The
compromise of UTC provided an "acronym" that, by design, didn't make sense to
anyone, which I think is somewhat telling about the whole issue. The blog post
here gives a good overview of fundamental difficulties, though doesn't really
convey the true horror of the subject; I often suspect that a full and
complete description of the proper handling for date/times can be found only
in an appendix of the Necronomicon, serving as a final deathblow to any last
scraps of the reader's sanity.

[0] cf. Michael Kaplan's MSDN blog for a glimpse at all the ways Unicode can
go wrong. See how many entries you can read successively until starting to
doubt whether written communication was ever actually a good idea! I think my
personal record is 14 or so.

[1] cf. anyone who's ever tried. I don't think I need to justify this one.

------
autarch
His suggestion that storing datetimes in UTC may be a problem is only half-
correct. If you have access to an accurate historical record of rules for a
given zone, then you _can_ always store UTC.

On Unixen, this data is typically stored somewhere like /usr/share/zoneinfo,
and is called the zoneinfo or Olson database (Arthur David Olson is the
original creator and maintainer of this database).

Using this database, you will always get the right conversion, even for
datetimes that predate recent shift in DST rules.

OTOH, if you're on a crippled system that assumes the most recent rules extend
indefinitely back in time, then storing data in UTC only will be problematic.

------
jbert
Storing as localtime+timezone is asking for bugs since most people shift
timezone twice a year. That makes testing a real problem.

Store times internally as UTC (time_t epoch is a good representation, or the
DateTime object of your preference), convert as needed at the boundaries of
your app for display/persistent storage purposes.

~~~
spuz
I think the article was trying to point out that it is not possible to use UTC
for everything. If for example you store in your database an event to occur in
the distant future (e.g. opening ceremony of the 2016 Olympics) in UTC, then
the time that that represents can change as rules about timezones, leap
seconds and daylight savings change.

Also there is the possibility that you actually want to store the timezone
information at write-time, rather than assuming a timezone at read-time. For
example if you have multiple records storing event times (say the working
hours of all your global employees) then storing them only using UTC, you will
not be able to retrieve the actual time in the timezone of each event
individually. You can only assume a global timezone to apply to all events.

When storing localtime+timezone, do as the article recommends. Store the
timezone, not the offset from UTC. Store "New York time" not EST or EDT.

~~~
jbert
> When storing localtime+timezone, do as the article recommends. Store the
> timezone, not the offset from UTC. Store "New York time" not EST or EDT.

The problem is that that isn't well defined, as I point out here:
<http://news.ycombinator.com/item?id=919407>

There are two UTC times corresponding to each moment from 00:00->01:00 25th
Oct 2009 "London Time". There are no UTC times corresponding to 01:00->02:00
29th March 2009 "London Time".

> Also there is the possibility that you actually want to store the timezone
> information at write-time, rather than assuming a timezone at read-time.

Whether a given time should be displayed in the viewer's localtime or another
time is a display issue (I may want to switch between seeing my plane arrival
time in localtime of the destination and localtime of my body clock). I don't
think it should affect the internal storage format as without help from a
strong type system (or some strong coding conventions) coders _will_
intermingle the two types and miss errors in testing either due to
geographical proximity or lack of testing over daylight savings boundaries.

[All the above saud, the problem of changing DST parameters and future event
times is problematic. I think it depends on what you want to be doing with
such a time. Note that you'd have the opposite bug if you were storing pre-
calculated sunrise time in various locales, so it's an issue of the semantic
meaning of the timestamp.]

~~~
texel
I've dealt with this quite a bit, and you're right- it's difficult to deal
with the conceptual impedance mismatch between the concept of a time, and its
discrete meaning in persistent storage.

I wrote a blog post about a month ago that talks about some issues surrounding
the concept of "all-day" events which, by definition, are conceptually
ambiguous.

<http://onehub.com/past/2009/9/28/the_joy_of_calendars/>

Ah, good times.

------
Kirby
I've had more traumatic code errors due to times than I care to admit.

The bottom line: Learn from Unix. Store everything in epoch time (even if
you're in Windows.) Do all your math in that. Showing local time is for
display _only_. You won't ever regret it. (Well, hardly ever.)

~~~
whatusername
And retire before 2038.

~~~
agazso
And retire before 2038 if you still define time_t as a 32 bit signed integer.

------
wglb
Every programmer working with dates should read <http://naggum.no/lugm-
time.html> \- "A Long Painful history of time". And also the Dave Olson paper
referenced therein.

------
jmagar
Jon Udell had a very interesting article recently on a related topic:
[http://blog.jonudell.net/2009/10/23/a-literary-
appreciation-...](http://blog.jonudell.net/2009/10/23/a-literary-appreciation-
of-the-olsonzoneinfotz-database/)

Jon's particular slant was reading the comments in the timezone database and
reflecting on the political influences captured within. A fun read.

------
gcv
Great article. The author suggests saving time in two formats, (1) UTC and (2)
local date-time with a geographical time zone. The app would then pick the
right one to use depending on context.

BTW, let me take the opportunity to praise the Joda Time library for JVM
languages. First time I've ever seen date and time primitives implemented
well. It can be used for the scheme suggested in the article.

~~~
jbert
> (2) local date-time with a geographical time zone.

Note that timezones aren't just geographical. In London, you'll be in timezone
GMT (+0000) for half the year and timezone BST (+0100) for half the year.

If you think instead that you're in a single timezone, then you need to know
that your "timezone" isn't linear, it contained 00:00->01:00 twice on 25th
October 2009 this year (when the clocks go back).

So "what was the UTC time for 00:30 on 25th October 2009 in London" isn't a
question with a well-defined (or unique) answer.

~~~
arohner
> Note that timezones aren't just geographical. In London, you'll be in
> timezone GMT (+0000) for half the year and timezone BST (+0100) for half the
> year.

You're comparing apples and oranges. There are two different concepts here: 1)
the name of a UTC offset for a given period of time in a given region i.e.
BST. 2) the geographic area that has a set of rules about when to change the
UTC offset.

In the US, we call #1 "Central Standard Time or Central Daylight Time" and #2
"Central Time". #1 means "UTC -6", and #2 means "convert UTC according to
whatever the current rule is".

The author's point is to store local time + concept #2.

EDIT: ok, I see what you mean. If the user types in "send me a reminder at
12:30 Oct 25 London time, you don't know whether they're talking about pre-
DST, or post-DST. Interesting.

------
DanielStraight
Perfect article. Short and to the point, and even though it's something I've
thought about before, I learned something new.

------
euroclydon
So, if I asked you to meet me for coffee at 5:00 PM EST, and I showed up when
my watch said 5:00, I would be an hour early, b/c we're in DST right now.

I though that was interesting, b/c I will put EST in an email to people in
another timezone, just thinking it means "Eastern Time Zone" or something like
that.

