2013-10-28 23 views
26

我在我的數據庫中存儲事件。我有'開始'和'結束'日期時間,'tickets_start'和'tickets_end'(用於門票銷售實際開始/結束時 - 與實際活動的開始/結束相反)。如何存儲重複日期銘記夏令時

到目前爲止,我已經建立的方法是做所有有趣的東西,如保存前的日期/時間轉換爲GMT,然後回到各自的時區顯示。

我將時區存儲在類似「America/New_York」的值的varchar字段中。

但是 - 現在我需要開始處理,如果用戶想要允許重複事件。我之前就已經完成了,這並不是什麼大不了的事情,但從來沒有跨越多個時區。起初,我認爲這沒什麼大不了的,但後來才意識到 - 如果最初的開始日期是在七月(例如),並且它每年重複一年,在某個時間點,夏令時時間將使得格林威治標準時間的轉換會有所不同。一個月,當轉換12:00時,它會將其更改爲-5,接下來,由於DST,它會將其更改爲-4。

我目前的想法是,我將存儲一個'dst'tinyint(1),以確定在DST期間是否輸入了開始/結束日期,然後創建一種方法在必要時將時間改變一小時。

但是 - 想我會在這裏提問,希望也許有一個「正常」這個或一個簡單的東西,我沒有想到的。

(CakePHP中的2.4.x)

+0

可能重複(http://stackoverflow.com/questions/2532729/daylight-saving-time-and-time-zone-best-practices) – vascowhite

回答

76

首先,請認識到,在現代術語,你應該說UTC而不是GMT。除了UTC更精確的定義外,它們大部分是等效的。保留GMT這一術語是指冬季月份在UTC + 0偏移時有效的英國時區部分。

現在你的問題。 UTC不一定是存儲所有日期和時間值的最佳方式。它工作得特別好爲過去事件,或對未來絕對事件,但它並不適用於未來當地事件工作如此之大 - 尤其是未來重複事件。

我最近寫了一篇關於這個on another answer,並且是爲數不多的例外情況下,本地時間更有意義比UTC之一。主要論點是「鬧鐘問題」。如果您按UTC設置鬧鐘,則您將在DST轉換當天早或晚醒來一小時。這就是爲什麼大多數人在當地時間設置鬧鐘的原因。

當然,你不能只是存儲當地時間,如果你正在使用來自世界各地的數據。你應該保存了幾個不同的事情:

  • 重複事件的本地時間,如「08:00」
  • 本地時間表示的時區,如「美國/紐約」
  • 重複模式,以任何格式對您的應用程序有意義,例如每日,每兩週或本月的第三個星期四等。
  • 下一個直接 UTC日期和時間相當於最好的,你可以預測它。
  • 或許(但並非總是)未來事件UTC日期和時間的列表,預測出未來的某個預定義時間段(可能爲一週,也許爲6個月,也可能爲一年或兩年,具體取決於您的需要)。

對於最後兩個,如果負責該時區的政府決定更改任何內容,則任何本地日期/時間的UTC等效值都會發生變化。由於每年都有多個時區數據庫更新,因此您需要定期制定計劃subscribe to announcements of updatesupdate your timezone database。無論何時更新您的時區數據,您都需要重新計算所有未來事件的UTC等效時間。

如果您打算顯示任何種類的跨越多個時區的事件列表,那麼具有UTC等效性非常重要。這些是你將要查詢的建立該列表的值。

另一個要考慮的問題是,如果事件安排在DST回退轉換期間發生的本地時間,則必須決定事件是發生在第一個實例上(通常)還是第二個實例(有時)或兩者(很少),並在你的應用程序中構建一個機制來確保事件不會兩次觸發,除非你想要。

如果您正在尋找一個簡單的答案 - 抱歉,但沒有一個。跨時區調度未來事件是一項複雜的任務。

另類視角

我有幾個人給我的技術,他們調度,這是他們選擇在本地時間起始日期做使用UTC時間,將其轉換成UTC是存儲並存儲時區ID。然後在運行時,他們應用時區將原始UTC時間轉換回當地時間,然後使用該當地時間計算其他重現,就好像它是原始存儲的一樣。

雖然這種技術將工作的缺點是:

  • 如果有正在運行的第一個實例之前,改變了本地時間時區更新,它會拋出全部安排了。這可以通過爲「第一」實例選擇過去的時間來減輕,使得第二個實例是第一個實例。

  • 如果時間真的是一個應該跟隨用戶周圍(例如在手機上的鬧鐘)的「浮動時間」,您仍然必須存儲它最初的區域的時區信息創建 - 即使這不是你想要運行的區域。

  • 它增加了額外的複雜性,沒有任何好處。我會保留這種技術,您可能已經有一個UTC時間表的調度程序,您正試圖將時區支持加入。

的[夏令時時間和時區的最佳做法]
+0

是有一個很好的方法來處理檢查日期是否過去,或其他簡單的「檢查」?以前,如果以UTC來存儲所有日期,那很簡單,因爲我可以檢查服務器時間。但現在,它似乎需要額外的步驟......任何建議? – Dave

+1

如果您存儲下一個立即預測的UTC時間,則可以使用它來查詢事件是否即將到來或已經過去。如果通過,那麼您可能需要爲其他表中的過去事件編寫新記錄,然後將您的UTC時間更新爲下一個重複實例。 –

+0

您可以使用本地時間安排定期事件,並使用UTC中的每個事件的過去實例。但請嘗試將這些視爲您網域中的獨立實體。 –