开发者

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.)


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.


I posted a related question in comp.soft-sys.math.mathematica on 8/4/10:

http://groups.google.com/group/comp.soft-sys.math.mathematica/browse_thread/thread/6f50f6930f1ac325/

It turns out that there is (was?) a bug in the Mac version of M7 which essentially disregarded the Timezone specification in calls to AbsoluteTime. I think the problem was fixed in M8, but I'm not certain.


You may try something like this:

tzDreeves = {"Buenos Aires", "13 March", "13 September", 3, 4};

tZone[date_, tz_] := 
 Piecewise[{{tz[[4]],
   First@
    DateDifference[tz[[2]]<>" "<>DateString[date,"Year"], date, "Second"] > 0 &&
   First@
    DateDifference[tz[[3]]<>" "<>DateString[date,"Year"], date, "Second"] < 0}},
 tz[[5]]];

myTimeDif[d1_, d2_, tz_] := 
 DateDifference[DateList@AbsoluteTime[d1, TimeZone -> tZone[d1, tz]], 
                DateList@AbsoluteTime[d2, TimeZone -> tZone[d2, tz]], "Second"]


myTimeDif["March 13, 2011", "March 14, 2011", tzDreeves]
myTimeDif["March 12, 2011", "March 13, 2011", tzDreeves]  

->

{82800,Second}  -> 23 hours
{86400,Second}  -> 24 hours   

In the following example you can see the effect of the DS. We plot the time difference to a fixed date across the DST frontier:

data = Table[{
         DateList@DatePlus["March 12, 2011, 11PM", {i 10, "Minute"}], 
         First@myTimeDif[DatePlus["March 12, 2011, 11PM", {i 10, "Minute"}], 
                         "March 14, 2011, 2 AM", tzDreeves]},
       {i, 1, 13}];

DateListPlot[data, 
 DateTicksFormat -> {"MonthNameShort", " ", "Day", "\n ", "Time"}, 
 GridLines -> {{{{2011, 3, 13}, Red}}, None}, 
 PlotStyle -> PointSize[Large]]

Daylight Savings Time "bug"

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜