夏令时“bug”

发布于 2024-11-03 21:37:28 字数 826 浏览 1 评论 0原文

以下是连续两天之间的小时数的计算:

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

因此,您可能不会对 Mathematica 返回 24 感到惊讶。 但这是令人惊讶的。其他所有编程语言都会说 23,因为 3 月 13 日是夏令时的开始。 我需要我的 Mathematica 程序在这方面与其他语言保持一致。 你会推荐什么?

为了清楚地说明问题:AbsoluteTime[{2011,3,13}] 给出 3508963200。减去 unix 纪元,即为 1299988800 的 unixtime。但是将 unixtime 提供给任何其他编程语言并询问它对应的日期,它会说 3 月 12 日而不是 3 月 13 日。 (同样的事情在 3 月 14 日也能正常工作。)

(好吧,我知道你很想知道为什么我想要遵守所有那些明显不完整的语言。 好吧,首先,其他语言都有一个观点:由于“向前推进”,3 月 14 日午夜比 3 月 13 日午夜晚了 23 个小时。 为什么我真正关心:我们使用 unixtime 作为日期的规范表示。因此,当我想将“2011-03-13 00:00 EST”传达给另一个程序时,我发送 AbsoluteTime 减去 unix 纪元。 这在 Mathematica 中工作得很好。当我将 unixtime 转换回来时,我再次得到“2011-03-13 00:00 EST”。 但是,如果我将该 unixtime 发送到另一个程序,它会将其解释为“2011-03-12 23:00 EST”,这结果是一个问题,因为那是前一天。)

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

撩动你心 2024-11-10 21:37:28

您可以使用 Java 在 Unix 时间之间来回转换:

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[]
    ]
  ]

示例使用:

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"

如所写,前面的定义将在转换中使用您的本地时区和区域设置。

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.

孤者何惧 2024-11-10 21:37:28

我于 2010 年 8 月 4 日在 comp.soft-sys.math.mathematica 中发布了一个相关问题:

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

事实证明,有(是?)Mac 版本的 M7 中存在一个错误,该错误本质上忽略了调用 AbsoluteTime 时的时区规范。我认为这个问题在 M8 中已得到解决,但我不确定。

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.

最单纯的乌龟 2024-11-10 21:37:28

你可以尝试这样的事情:

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   

在下面的例子中你可以看到DS的效果。我们绘制 DST 边界上固定日期的时差:

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]]

在此处输入图像描述

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]]

enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文