2017-04-22 236 views
1

這個問題是關於未來的日期和時間(過去的值無疑是第一選擇)。如何將未來(!)日期保存在數據庫中


我不知道是否有人曾建議以「最佳」的方式保存在MySQL數據庫中的未來日期和時間(或爲此事也一般),特別是在列可以保存來自不同時區的時間的上下文。考慮到時區規則可能會改變UTC可能不是最好的選擇。

到目前爲止,我發現的最可行的選擇是將它作爲文本保存在位置當地時間以及位置(例如「America/*」)中。不幸的是,這個解決方案可能更容易發生數據損壞,對於計算而言絕對不方便。

有人能想到更好的東西嗎?

在此先感謝

+0

「考慮到時區的規則可能改變UTC可能不是最好的選擇」 - 我不能按照你的邏輯。任意時區的立法恰恰是UTC的一個論據。 –

+0

@ÁlvaroGonzález--它不那麼簡單。如果事件是在上午10點在7月1日在埃及開羅在2027年,我不能告訴你現在什麼UTC時間,這將是,因爲這將需要對我而言這樣的假設:埃及政府不會改變自己的時區現在和之後的規則。事實上,這已在過去[埃及特別](http://codeofmatt.com/2016/07/01/time-zone-chaos-inevitable-in-egypt/)和[其他時區的問題有一些規律性](http://codeofmatt.com/2016/04/23/on-the-timing-of-time-zone-changes/)。 –

回答

2

保存未來日戳的考慮是幾乎一樣的過去日戳。

(我稱他們爲日戳因爲無論DATETIMETIMESTAMP是保留字在MySQL。爲了討論起見,我想這並不意味着任何數據類型的字。)

如果你正在構建一個系統供多個時區的人使用,最好詢問每個用戶的時區偏好,並將其存儲在她的用戶個人資料中。然後,當她登錄您可以檢索它,然後做

SET time_zone = 'America/Halifax' 

或什麼的,命名了用戶的時區不同。

如果您的MySQL服務器在Linux,BSD或其他* nix系統上運行,則這些時區來自該機器上的zoneinfo subsystem。當不同的國家司法管轄區更改時區規則時,zoneinfo會更新。維護受歡迎的發行版的人經常將更新推送到zoneinfo,因此您將保持合理的最新狀態。 (如果你的MySQL服務器在Windows主機上運行,​​做一些閱讀有關該操作系統上的MySQL時區的東西。它更麻煩讓事情最新的。)

然後,如果你使用TIMESTAMP數據類型您的日期戳,任何時候您檢索值時,它都會在顯示之前從UTC自動轉換爲本地時區。任何時候您存儲一個值都會自動轉換爲UTC。在這方面,NOW()的值就像時間戳一樣。所以,如果你做,例如,

UPDATE appointment 
    SET datestamp = NOW() + INTERVAL 7 DAY 
    WHERE id = something 

你會存儲一個UTC時間,這是一個星期後這一刻。然後,如果你做

SELECT datestamp 
    FROM appointment 
WHERE id = something 

用戶會看到它們分別用SET timezone在她的本地時區的時間。

如果您爲日期戳使用DATETIME數據類型,則可以在存儲和檢索日期戳時自行抵消它們。存儲它們時,將它們從本地時區偏移到UTC。當你找回他們時,換個方式。 Use CONVERT_TZ() for that

UPDATE appointment 
    SET datestamp = CONVERT_TZ(NOW(), 'America/Halifax', 'UTC') + INTERVAL 7 DAY 
    WHERE id = something 

SELECT CONVERT_TZ(datestamp, 'UTC', 'America/Halifax') datestamp 
    FROM appointment 
WHERE id = something 

顯然,代替你的用戶的選擇時區,併爲這些查詢'America/Halifax'

如果您可能可以避免IT不參考當地時間存儲您的日期戳從夏時制改爲標準時間。如果你這樣做,你的應用程序的整個生命週期的轉換日將會持續出現問題。我知道這一點,因爲我繼承了一些以這種方式工作的系統。餿主意。 UTC:好主意。

+1

關於時間處理看到如此清晰無誤的解釋並不常見。 –

+1

我說'DATETIME'就像是拍一張時鐘的照片;你無法分辨TZ涉及什麼。 –

+1

這是放置它的好方法。麻煩的是,'TIMESTAMP'在2038年初發布,除非它們改變磁盤格式。 –

1

首先,我之前已經詳細地寫過這篇文章,所以請閱讀我的答案herehere以及this blog post by Lau Taarnskov

針對MySQL,您通常不希望在將來事件的本地時間使用TIMESTAMP字段,因爲它將在寫入時從會話的時區轉換爲UTC,並從UTC轉換回UTC在讀取時刻到會話的時區。即使這些都是同一個時區的IDS(他們不必須的),但也不能保證該時區的數據將不會爲一個或兩個時區,當你寫數據,並在事件之間切換髮生。

相反,使用DATETIME領域,這確實沒有隱時區轉換。你得到了你寫的確切的價值。存儲事件的本地時間,並存儲包含事件的時區標識符的字段VARCHAR。這是保留用戶原始意圖的唯一方法。

理由和邊緣情況在我以前給了答案,所有描述。

相關問題