【问题标题】:Daylight Savings Time "bug"夏令时“错误”
【发布时间】:2011-04-26 17:53:09
【问题描述】:

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

(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”,结果证明这是一个问题,因为那是前一天。)

【问题讨论】:

  • 夏令时是一个可怕的、可怕的混乱,原则上它每年都会以不可预测的方式发生变化,具体取决于你住在哪里。您是否有机会更改规范表示以始终使用 UTC 并忽略 DST?
  • 我认为加入 Mathematica usenet 组可以找到更多答案
  • "AbsoluteTime[] 使用您计算机系统上设置的任何日期和时间。它不会对时区、夏令时等进行更正。"
  • (另外,你需要把减法用括号括起来。我试图修复它,但编辑必须至少有六个字符。)
  • (感谢@Brett;已修复。在测试时我只是在几秒钟内完成,因为我习惯了 86400 作为一天中的秒数。然后我想我在这方面可能很奇怪,并且认为我应该转换为小时。)

标签: datetime wolfram-mathematica


【解决方案1】:

您可以使用 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"

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

【讨论】:

  • 哈,我正在考虑对 Ruby 或 Perl 脚本进行系统调用。这比那好一点,我想!感谢提供完整代码;这非常有帮助。
【解决方案2】:

我于 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 中已解决,但我不确定。

【讨论】:

  • @Cassini 欢迎来到 StackOverflow!本网站的精神是尽可能使其内容独立。因此,如果可能,最好复制/粘贴而不是链接外部资源。这当然不是一个严格的规则,只是一个建议。享受这个网站。
  • @Cassini 对于that post 中的日期,Mathematica 7.01 我得到一小时的时差,如预期:(AbsoluteTime[{2016, 04, 13, 3, 0, 0}] - AbsoluteTime[{2016, 04, 13, 2, 0, 0}])/3600 返回1
  • @belisarius:明白。我以后会避免链接。
  • @Alexey:我相信这个错误是特定于 Mac OS 的。您使用的是什么操作系统?
  • 我刚刚确认该错误已在 Mac OS 版本的 M8 中修复。
【解决方案3】:

你可以试试这样的:

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

【讨论】:

    猜你喜欢
    • 2018-10-04
    • 2012-11-25
    • 2014-04-26
    • 2016-08-06
    • 2017-08-28
    • 2020-03-21
    • 2021-10-18
    • 2014-11-03
    • 2017-08-16
    相关资源
    最近更新 更多