mysql日期可以保存时区_数据库存储时间的时区问题
先說一下mysql中DATETIME和TIMESTAMP的區(qū)別
TIMESTAMP是標(biāo)準(zhǔn)的unix timestamp,它存儲(chǔ)的是1970-1-1到現(xiàn)在經(jīng)過的秒數(shù),4字節(jié)存儲(chǔ)。mysql用這個(gè)類型還蠻方便的,一個(gè)是有很多內(nèi)置的函數(shù)和trigger來處理它,比如CURRENT_TIMESTAMP宏,最關(guān)鍵的是在取數(shù)據(jù)的時(shí)候mysql會(huì)自動(dòng)幫你處理DST和時(shí)區(qū)的問題。
DATETIME的范圍更大,好像可以從0000-00-00 00:00:00到9999-12-31 23:59:59,8字節(jié)存儲(chǔ),當(dāng)然mysql內(nèi)部肯定也是用整數(shù)而不是字符串的(說了是8字節(jié)了),所以效率不是大問題。但DATETIME不帶時(shí)區(qū),比如我在程序里生成了一個(gè)2015-05-07 15:26:00的時(shí)間(實(shí)際上是+8時(shí)區(qū)的,但這個(gè)對(duì)象可能是timezone naive)的,存到mysql里,再從不同時(shí)區(qū)的地方拿出來,這個(gè)時(shí)間可能就混了。
但TIMESTAMP也有兩個(gè)很大的問題:
4字節(jié)長(zhǎng)度限制,它只能到2038年
很多時(shí)候我們希望根據(jù)用戶所在地的時(shí)區(qū)顯示時(shí)間而不是光顯示一個(gè)服務(wù)器時(shí)間
所以比較好的做法是,數(shù)據(jù)庫中使用DATETIME,然后存時(shí)間的時(shí)候一律用程序生成UTC時(shí)間(而不是local時(shí)區(qū)的時(shí)間)存進(jìn)去,取出來的時(shí)候不管想顯示服務(wù)器時(shí)間還是顯示用戶的時(shí)間都可以處理。
順便提一句,根據(jù)用戶所在地時(shí)區(qū)顯示時(shí)間有兩種做法:
當(dāng)用戶第一次訪問網(wǎng)站的時(shí)候,用js獲取時(shí)區(qū)發(fā)送到服務(wù)器上存到session里
用js處理時(shí)間的顯示(我覺得這種比較方便一點(diǎn),畢竟不用改服務(wù)端代碼)
Java獲取當(dāng)前UTC時(shí)間戳(毫秒)
public static String getUTCTimeStr() throws Exception {
Calendar cal = Calendar.getInstance();
return String.valueOf(cal.getTimeInMillis() / 1000);// 返回的就是UTC時(shí)間
}
使用這種做法的唯一缺點(diǎn)是sqlite3沒有internal的DATETIME類型,所以在ORM框架如sqlalchemy中,它會(huì)直接存字符串進(jìn)去。(sqlite3的文檔也說,你要么存成int要么real要么字符串)。盡管這可能帶來一些不方便和性能的下降,但我認(rèn)為還是符合“keep it simple and stupid”的原則。
至于用INT存時(shí)間,是另一種可行的方法,參見http://www.liaoxuefeng.com/article/0014132675721847f569c3514034f099477...
我個(gè)人不是很喜歡這么做,因?yàn)檫@樣你必須把模型中表示時(shí)間的成員聲明為int類型。這樣是比較不符合邏輯的(那些Date呀Datetime之類的類就沒有用了呀,最多就有個(gè)Dateutil就好了),而且會(huì)使得程序不易讀(臥槽這個(gè)publishedDate為什么是int,它到底表示的是時(shí)間嗎?)。總之見仁見智。
總結(jié)
以上是生活随笔為你收集整理的mysql日期可以保存时区_数据库存储时间的时区问题的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PHP + NGINX 控制视频文件播放
- 下一篇: Centos下安装mysql(二进制版)