我有一个字符串"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)!我该怎么做才能解决这个问题?
答案 0 :(得分:3)
DateTime.strptime
属于Ruby,而“东部时间(美国和加拿大)”等时区标识符仅由Rails通过ActiveSupport::TimeZone提供。
简单来说,DateTime
根本不了解该时区。您可以找到%z
和%Z
令牌定义的in the docs for DateTime
,如下所示:
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时区,请将其与Rails中的Time.zone.parse
结合使用,而不是DateTime.strptime
。
(我不是特别流利的Ruby,或者我会给你一个例子。也许有人可以编辑我的回复来提供一个,或者提供一个回答他们自己。)