Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Daylight Savings Time "bug"

Here's a calculation of the number of hours between two consecutive days:

(AbsoluteTime[{2011, 3, 14}] - AbsoluteTime[{2011, 3, 13}]) / 3600

So you might not be surprised that Mathematica returns 24. But it is surprising. Every other programming language will say 23 because March 13 was the start of Daylight Savings Time. I need my Mathematica program to be consistent with other languages in this regard. What would you recommend?

To be clear about the problem: AbsoluteTime[{2011,3,13}] gives 3508963200. Subtract the unix epoch and that's a unixtime of 1299988800. But give that unixtime to any other programming language and ask it what date it corresponds to and it will say March 12 instead of March 13. (The same thing will work fine for March 14.)

(OK, I know you're dying to know why I'd want to conform to all those clearly broken languages. Well, first of all, the other languages have a point: Thanks to "springing ahead", midnight on March 14 was 23 hours after midnight on March 13. Why I actually care: We use unixtime as the canonical representation for dates. So when I want to convey "2011-03-13 00:00 EST" to another program I send AbsoluteTime minus the unix epoch. That works fine within Mathematica. When I convert that unixtime back I get "2011-03-13 00:00 EST" again. But if I send that unixtime to another program it interprets it as "2011-03-12 23:00 EST" which turns out to be a problem, since that's the previous day.)

like image 815
dreeves Avatar asked Apr 26 '11 17:04

dreeves


1 Answers

You could use Java to convert back and forth from Unix time:

Needs["JLink`"]
LoadJavaClass["java.util.Calendar"]

ToUnixTime[year_, month_, day_, hour_:0, minute_:0, second_:0] :=
  JavaBlock[
    Module[{calendar}
    , calendar = java`util`Calendar`getInstance[]
    ; calendar@set[year, month - 1, day, hour, minute, second]
    ; Floor[calendar@getTimeInMillis[] / 1000]
    ]
  ]

FromUnixTime[time_Integer] :=
  JavaBlock[
    Module[{calendar}
    , calendar = java`util`Calendar`getInstance[]
    ; calendar@setTimeInMillis[time * 1000]
    ; calendar@getTime[]@toString[]
    ]
  ]

Sample use:

In[19]:= ToUnixTime[2011, 4, 26, 1, 2, 3]
Out[19]= 1303801323

In[20]:= FromUnixTime[1303801323]
Out[20]= "Tue Apr 26 01:02:03 MDT 2011"

As written, the preceding definitions will use your local time zone and locale settings in the conversions.

like image 120
WReach Avatar answered Sep 20 '22 10:09

WReach