2014-03-02 20 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