Ruby on rails 3 Rails通过DST边界给出了错误的strftime时间

Ruby on rails 3 Rails通过DST边界给出了错误的strftime时间,ruby-on-rails-3,timezone,dst,Ruby On Rails 3,Timezone,Dst,我有一个字符串“东部时间2014-03-15下午3:30(美国和加拿大)”,我想将其转换为日期时间并存储在我的数据库中 这很简单: str = "3:30 PM 2014-03-15 Eastern Time (US & Canada)" event.starts_at = DateTime.strptime(str, "%l:%M %p %Y-%m-%d %Z") 这将创建具有正确时区的日期时间。但是,如果我将事件保存到数据库中,然后像这样将其读回: e.starts_at.in_t

我有一个字符串
“东部时间2014-03-15下午3:30(美国和加拿大)”
,我想将其转换为日期时间并存储在我的数据库中

这很简单:

str = "3:30 PM 2014-03-15 Eastern Time (US & Canada)"
event.starts_at = DateTime.strptime(str, "%l:%M %p %Y-%m-%d %Z")
这将创建具有正确时区的日期时间。但是,如果我将事件保存到数据库中,然后像这样将其读回:

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)!如何解决此问题?

DateTime.strtime
属于Ruby,而“东部时间(美国和加拿大)”等时区标识符仅由Rails通过提供

简单地说,
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的时区概念(这也很可笑,请看本书的最底层)

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

建议#1-放弃铁路时区标识符。改为使用Ruby,它提供了正常的ID,如
America/NewYork

建议#2-如果必须使用Rails时区,请将其与from Rails结合使用,而不是
DateTime.strtime


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

我最终使用了
Time.zone.parse
,目前它仍然有效,但我还没有完全测试它,因为DST边界已经过了。