【问题标题】:Rails gives wrong time with strftime across DST boundaryRails 跨 DST 边界使用 strftime 给出错误时间
【发布时间】:2014-03-02 22:07:44
【问题描述】:

我有一个字符串 "3:30 PM 2014-03-15 Eastern Time (US & Canada)",我想将其转换为 DateTime 并存储在我的数据库中。

这很简单:

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)!我可以做些什么来解决这个问题?

【问题讨论】:

    标签: ruby-on-rails-3 timezone dst


    【解决方案1】:

    DateTime.strptime 属于 Ruby,而诸如“东部时间(美国和加拿大)”之类的时区标识符仅由 Rails 通过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”这样的缩写,或者它可能会允许一些像“Eastern”这样的关键字。我真的不确定,但我认为它不太可能完全了解 Rails 的时区概念(这也很可笑 - 请参阅the timezone tag wiki 的最底部)。

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

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

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

    (我对 Ruby 不是特别流利,否则我会为您提供一个示例。也许有人可以编辑我的回复以提供一个,或者在他们自己的答案中提供一个。) p>

    【讨论】:

    • 我最终使用了Time.zone.parse,它现在可以使用,但由于 DST 边界已经过去,我还没有彻底测试它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-06-29
    • 2020-03-07
    • 1970-01-01
    • 2011-11-14
    • 2016-07-12
    • 2013-11-27
    相关资源
    最近更新 更多