What every developer should know about time
blogs.windwardreports.com
blogs.windwardreports.com
> .. 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.
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.
http://en.wikipedia.org/wiki/Coordinated_Universal_Time#Abbr...
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.
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.
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.
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.
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.]
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.
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.)
Embarrassing, that one.
Jon's particular slant was reading the comments in the timezone database and reflecting on the political influences captured within. A fun read.
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.
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.
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.
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.