Rails在DST边界上使用strftime给出了错误的时间



我有一个字符串"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

输出给出了错误的时间(似乎是因为它正在为夏令时进行调整)!我能做些什么来解决这个问题?

DateTime.strptime属于Ruby,而像"Eastern time(US&Canada)"这样的时区标识符仅由Rails通过ActiveSupport::TimeZone提供。

简单地说,DateTime根本不了解那个时区。您可以在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关于时区的想法(这也很可笑——请参阅时区标签wiki的底部)。

从逻辑上讲,代码示例中发生的情况是,该值是在东部标准时间解析的——尽管东部夏令时对您经过的时间有效。只是猜测,但解析器中的某些内容可能会选择"east"并假设EST。然后,它被错误地保存在数据库中,偏移量为-5。当Rails将其加载回并使用通用的"东部时间(美国和加拿大)"时区进行处理时,它意识到EDT正在生效,因此它使用正确的-4偏移量进行加载。偏移量的差异是你在一小时后看到结果的原因。

建议#1-放弃onRails时区标识符。请使用Ruby TZInfo gem,它会为您提供普通的IANA时区ID,如America/New_York

建议#2-如果必须使用Rails时区,则将其与Rails中的Time.zone.parse一起使用,而不是DateTime.strptime

(我对Ruby不是特别流利,或者我会给你举一个例子。也许有人可以编辑我的回复来提供一个,或者在自己的答案中提供一个。)

相关内容

  • 没有找到相关文章

最新更新