2016-11-29 38 views
1

我不知所措,試圖做到這一點:我們有服務器位於十幾個時區,其中Apache和MySQL運行在所有或部分時區,如以及在Amazon RDS上託管的MySQL。Web和數據庫服務器設置以獲得UTC時區「正確」

我想知道「最佳實踐」,或者如何以其他方式配置每個MySQL和PHP安裝,以便當從PHP添加一行到數據庫時,我確信實際上這個值是UTC時間事件發生時,無論其中服務器發生何時發生。在任何給定的時區將其呈現給用戶不是問題 - 我只想知道datetime列實際上是存儲發生事件時的實際時刻。

現在,Web服務器被設置爲任何本地時區是由於計劃的事件等,我不知道該謎題的哪些部分使用哪些設置從哪裏得出什麼是寫入數據庫。

我很抱歉如果這個問題看起來不清楚,在這一點上我不知道我不知道什麼,所以得到一個確切的問題甚至是具有挑戰性的。此外,我們所有的日期都作爲日期時間字段存儲在數據庫中,因此不可能存儲時間戳。

回答

1

如果您將自己限制爲MySQL的DATE和DATETIME類型,則可以在很大程度上忽略MySQL本身中的時區問題。你要避免MySQL的TIMESTAMP類型,因爲:

的MySQL從當前時區轉換TIMESTAMP值以UTC進行存儲,並從UTC回到當前時區進行檢索。 (對於其他類型(如DATETIME),不會發生這種情況。)默認情況下,每個連接的當前時區是服務器的時間。

https://dev.mysql.com/doc/refman/5.7/en/datetime.html

至於讀/寫DATETIME值,你會得到你把什麼的,這是很好的。

這留下了始終確保將UTC值寫入數據庫的問題。

確保PHP使用UTC的最佳方式是使用date_default_timezone_set()在應用程序中明確設置它。這將確保諸如date('Y-m-d H:i:s')之類的電話將爲您提供UTC值。它也將確保像(new \DateTime('now'))->getTimezone()這樣的東西將返回一個UTC \ DateTimeZone實例。

當然,當您存儲從用戶獲取的日期/時間值時,事情會變得更加困難。在這些情況下,您需要以某種方式確定用戶所在的時區,並在保存值之前處理到UTC的轉換。假設你的用戶有一些每個用戶的時區設置,你基本上做的是這樣的:

/** @var \DateTimeZone $userTZ */ 
$userTz = getUserTimezone(); 
$dateTime = new \DateTime($user_submitted_date_string, $userTz); 
$dateTime->setTimezone(new \DateTime('UTC')); 
$dateTimeStr = $dateTime->format('Y-m-d H:i:s'); 
+0

這就是我正在尋找的......「確保PHP使用UTC ...」,並且我/我們可以在應用程序級別控制它。只要我知道UTC正在進入數據庫,其他一切都是小菜一碟。謝謝 – GDP

+0

最後一個問題......似乎MySQL中的默認時區對任何PHP都沒有影響,除了使用NOW(),CURDATE()等的SQL之外。是這樣嗎? – GDP

+0

@GDP - 我很謹慎地做出這樣的分類陳述。但我會說是。只要你避免依賴於MySQL內部默認時區設置的MySQL函數,你就很好。特別是,INSERT/SELECT行爲與VARCHAR列的行爲不可區分。 – timdev

2

非常簡單,總是將unix time存儲在數據庫中(或者如果您希望microtime具有微秒精度)。然後,無論您的每個Web服務器的時區是多少,如果其中兩個同時收到請求,它將是保存在數據庫中的相同整數值(數據庫字段顯然是int(或大int微時間))

以及如何顯示?容易與JavaScript。

new Date(unix_timestamp); 

這會在用戶的時區中產生日期和時間。

+1

不能一致認同。唯一的日期和時間應該被表示爲字符串在用戶屏幕上的薄層像素上。 – Jerry

+0

我很抱歉...我會澄清所有關心的數據都存儲爲MySQL日期時間類型 – GDP

+0

此外,不關心顯示,這是「簡單」。它知道PHP使用date()vs的時候,MySQL默認使用時間戳,與整個網絡中各種服務器應用程序中設置的時區一致。 – GDP

相關問題