Properly calculating time differences in JavaScript
blog.synyx.de
blog.synyx.de
I'm a fairly intelligent guy, can follow the plots of Primer, Terminator, and other scifi time travel movies. I have a decent understanding of relativity, spatial reference frames, etc.
But any time I have to deal with slightly more-than-simple time issues in any language, my brain starts more or less falling to pieces. Python and js have good libraries that help, but its still a confounding bugger of an issue.
- Always store times and calculate differences/offsets in UTC.
- Never attempt to convert a local time to UTC (it is not a one-to-one mapping!).
- Depending on your application, convert any dates to a given timezone at the moment they are displayed.
Now Javascript throws a monkey-wrench into the whole affair, because it assumes Dates should be handled in the user's local timezone, which, if you're dealing with timezone issues, is certainly not what you want. So attempting to convert a Date object from one timezone to the next is surely impossible to do without introducing bugs unless you understand the rules for every timezone you're dealing with.
Luckily, a guy named Olson created a database of timezone rules for us mortals to use in our timezone-aware applications. In another stroke of good fortune, some smart people wrote a Javascript library [1] that parses this database for you and can convert your Javascript Date object between any timezone on the planet. So you do all your calculations using this Date object in UTC mode, then convert to the desired timezone at the time they are displayed.
Luckily, there is, and that place is UTC. UTC is a time measuring system that does not have daylight savings time and where midnights always are 24 hours apart.
isn't strictly true, at least in the sense that 24 hours isn't always the same length of time because of leap seconds.
http://www.ecma-international.org/ecma-262/5.1/#sec-15.9.1.1
Time is measured in ECMAScript in milliseconds since 01 January, 1970 UTC. In time values leap seconds are ignored. It is assumed that there are exactly 86,400,000 milliseconds per day.
Therefore, whenever we compute the difference between two UTC times, we should really account for any leap second.
You just have to keep in mind that JavaScript UTC != Real UTC
Edit: clarification
Only one Coordinated Universal Time exists: it is the UTC standard. ECMA-262 is the specification of a scripting language, with tons of interesting features but with a very poor understanding of what UTC is.
UTC is based on TAI. Whenever we need to compute time differences of UTC times, we need to account for leap seconds implementing TAI. Implementations are available in a number of languages and very easy to port: - C http://cr.yp.to/libtai.html - Haskell http://hackage.haskell.org/packages/archive/time/1.4/doc/htm... - Erlang https://github.com/secyoure/taider
Full disclosure: author of the Erlang TAI library here.
In Date.UTC, there are no leap seconds and therefore the Day == 862e5 assumption holds and we can use it to calculate the difference between two dates measured in days, which is the point of the blog post.
When doing arithmetic with real UTC, you are absolutely correct and we have to take leap seconds into account.
I've found that timezone-js [1] does the job.
Uhhhhh...