2014-03-02 21 views
4

我有一个字符串"3:30 PM 2014-03-15 Eastern Time (US & Canada)",我想将其转换为DateTime并存储在我的数据库中。Rails给出了跨DST边界strftime的错误时间

这是非常简单的:

str = "3:30 PM 2014-03-15 Eastern Time (US & Canada)" 
event.starts_at = DateTime.strptime(str, "%l:%M %p %Y-%m-%d %Z") 

会创建一个与正确的时区一个DateTime。但是,如果我在事件保存到数据库中,然后读出来了,像这样:

e.starts_at.in_time_zone("Eastern Time (US & Canada)") 
    .strftime("%l:%M %p") => #outputs 4:30 PM, when I want it to say 3:30 PM 

输出给错误的时间(好像是​​因为它是在调整了DST)!我能做些什么来解决这个问题?

回答

3

DateTime.strptime属于红宝石,而时区标识符,如“东部时间(美国&加拿大)”仅由导轨通过ActiveSupport::TimeZone提供。

简而言之,DateTime完全不理解该时区。你可以找到in the docs for DateTime%z%Z令牌定义如下:

Time zone: 
    %z - Time zone as hour and minute offset from UTC (e.g. +0900) 
      %:z - hour and minute offset from UTC with a colon (e.g. +09:00) 
      %::z - hour, minute and second offset from UTC (e.g. +09:00:00) 
      %:::z - hour, minute and second offset from UTC 
               (e.g. +09, +09:30, +09:30:30) 
    %Z - Time zone abbreviation name or something similar information. 

%z定义是有道理的,但%Z定义是可笑的。它并没有真正说出允许或预期的内容。也许它正在寻找像“EST”或“EDT”这样的缩写,或者它可能会允许一些关键字如“东方”。我真的不确定,但我不认为它可能完全知道Rails的时区概念(这也是可笑的 - 请参见the timezone tag wiki的最底部)。

从逻辑上讲,代码示例中发生的情况是,该值在东部标准时间被解析 - 即使东部夏令时在您传递的时间内有效。只是一个猜测,但解析器中的东西可能是“东部”,并假设EST。然后将它以-5偏移量错误地保存在数据库中。当Rails将其加载并使用“东部时间(美国&加拿大)”时区对其进行处理时,它知道EDT已生效的事实,因此它使用正确的-4偏移量加载它。偏移量的差异就是为什么你会在一个小时内看到结果。

建议#1 - 放弃Rails时区标识符。改为使用Ruby TZInfo gem,这会为您提供正常的IANA time zone ID,例如America/New_York

建议#2 - 如果你必须使用Rails的时区,然后用Time.zone.parse Rails中结合使用它们,而不是DateTime.strptime

(我不是特别流利的Ruby或者我会为您提供一个例子。也许有人可以修改我的反应,以提供一个或一个自己的答案提供了一个。)

+0

我结束了使用现在可用的'Time.zone.parse',但是由于DST边界已经通过,我还没有彻底测试过它。 – you786