3 回答

TA貢獻(xiàn)1821條經(jīng)驗(yàn) 獲得超5個(gè)贊
坦率地說,MySQL的日期類型已損壞,無法正確存儲(chǔ)所有時(shí)間,除非將系統(tǒng)設(shè)置為恒定的偏移時(shí)區(qū),例如UTC或GMT-5。(我正在使用MySQL 5.0.45)
這是因?yàn)槟鸁o法在夏令時(shí)結(jié)束前的一個(gè)小時(shí)內(nèi)存儲(chǔ)任何時(shí)間。無論您如何輸入日期,每個(gè)日期函數(shù)都會(huì)將這些時(shí)間視為在切換后的一小時(shí)內(nèi)。
我的系統(tǒng)的時(shí)區(qū)為America/New_York。讓我們嘗試存儲(chǔ)1257051600(星期日,2009年11月1日06:00:00 +0100)。
這里使用專有的INTERVAL語法:
SELECT UNIX_TIMESTAMP('2009-11-01 00:00:00' + INTERVAL 3599 SECOND); # 1257051599
SELECT UNIX_TIMESTAMP('2009-11-01 00:00:00' + INTERVAL 3600 SECOND); # 1257055200
SELECT UNIX_TIMESTAMP('2009-11-01 01:00:00' - INTERVAL 1 SECOND); # 1257051599
SELECT UNIX_TIMESTAMP('2009-11-01 01:00:00' - INTERVAL 0 SECOND); # 1257055200
甚至FROM_UNIXTIME()不會(huì)返回準(zhǔn)確的時(shí)間。
SELECT UNIX_TIMESTAMP(FROM_UNIXTIME(1257051599)); # 1257051599
SELECT UNIX_TIMESTAMP(FROM_UNIXTIME(1257051600)); # 1257055200
奇怪的是,DSTTIME 仍將在DST開始的“丟失”時(shí)間內(nèi)存儲(chǔ)和返回(僅以字符串形式?。r(shí)間(例如2009-03-08 02:59:59)。但是在任何MySQL函數(shù)中使用這些日期都是有風(fēng)險(xiǎn)的:
SELECT UNIX_TIMESTAMP('2009-03-08 01:59:59'); # 1236495599
SELECT UNIX_TIMESTAMP('2009-03-08 02:00:00'); # 1236495600
# ...
SELECT UNIX_TIMESTAMP('2009-03-08 02:59:59'); # 1236495600
SELECT UNIX_TIMESTAMP('2009-03-08 03:00:00'); # 1236495600
要點(diǎn):如果您需要在一年中的每個(gè)時(shí)間進(jìn)行存儲(chǔ)和檢索,則有一些不受歡迎的選擇:
將系統(tǒng)時(shí)區(qū)設(shè)置為GMT +一些恒定的偏移量。例如UTC
將日期存儲(chǔ)為INT(如Aaron發(fā)現(xiàn)的,TIMESTAMP甚至不可靠)
假設(shè)DATETIME類型具有一些恒定的偏移時(shí)區(qū)。例如,如果您在使用America/New_York,請(qǐng)將日期轉(zhuǎn)換為MySQL之外的 GMT-5 ,然后將其存儲(chǔ)為DATETIME(事實(shí)證明這很重要:請(qǐng)參閱Aaron的回答)。然后,您必須格外小心地使用MySQL的日期/時(shí)間函數(shù),因?yàn)槟承┖瘮?shù)假設(shè)您的值是系統(tǒng)時(shí)區(qū),而其他函數(shù)(尤其是時(shí)間算術(shù)函數(shù))則是“時(shí)區(qū)不可知的”(它們的行為就像是UTC一樣)。
Aaron和我懷疑自動(dòng)生成的TIMESTAMP列也已損壞。兩者2009-11-01 01:30 -0400和2009-11-01 01:30 -0500將被存儲(chǔ)為模棱兩可2009-11-01 01:30。

TA貢獻(xiàn)1801條經(jīng)驗(yàn) 獲得超16個(gè)贊
由于我們使用TIMESTAMP帶有On UPDATE CURRENT_TIMESTAMP(即:)的列recordTimestamp timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP來跟蹤更改的記錄和ETL到數(shù)據(jù)倉(cāng)庫(kù),所以這個(gè)線程讓我感到異常。
如果有人懷疑這種情況下的TIMESTAMP行為正確,并且可以通過將TIMESTAMPunix時(shí)間戳轉(zhuǎn)換為兩個(gè)相似的日期來區(qū)分它們:
select TestFact.*, UNIX_TIMESTAMP(recordTimestamp) from TestFact;
id recordTimestamp UNIX_TIMESTAMP(recordTimestamp)
1 2012-11-04 01:00:10.0 1352005210
2 2012-11-04 01:00:10.0 1352008810
添加回答
舉報(bào)