微信公衆號「後端進階」,專一後端技術分享:Java、Golang、WEB框架、分佈式中間件、服務治理等等。
老司機傾囊相授,帶你一路進階,來不及解釋了快上車!
我發現數據庫有些日期竟然用字符串保存?因而跟幾個小夥伴討論了關於數據庫的日期應該要怎麼保存的問題,其實我一直都建議直接用數值保存時間戳,爲何我要這麼建議呢?前端
如下,我會從時區的概念來跟大家解釋一下,爲何用數值保存時間戳是最好的方案,同時也爲了分享出來,讓更多開發小夥伴留意這些細節性的東西。sql
相信時區對於不少人來講的很熟悉,由於地球是圓的,在地球上不一樣角落看到的太陽上升的角度都是不一樣的,即每一個人對於時間的顯示都是不同的,數據庫
舉個例子:編程
此時處於東 8 區的咱們北京時間是 10 點,那麼處於東 1 區的時間就是 3 點,可是他們的時間是等價的:後端
"2019-06-20 10:00 +8:00" = "2019-06-20 3:00 +1:00"
因此說,對於不一樣時區的人來講,顯示的時間是不同的,那麼此時你是如何將將時間保存到數據中的呢?服務器
我姑且假設你用的是 new Date() 方法來保存當時日期,但據我所知道的,數據庫的 DateTime 類型是沒有時區信息的,若是你此時用 DateTime 格式保存日期,就會丟失時區信息,若是你的服務器更該地址,從數據庫讀出來的日期數據就是錯誤的!微信
可能你會說,那我用 timeStamp 類型保存總不會丟失時區信息了吧?確實沒丟失,沒毛病。可是據我所知道的,timeStamp 保存的時間最長不能超過 2037 年,並且你要考慮每一個數據的 timeStamp 類型都有可能不同。框架
至於用字符串來存儲時間,就更加不推薦了,姑且不從時區來講,你比較日期大小也是個問題,我舉個例子:編程語言
to_char(SYSDATE, 'yyyy-MM-dd') > START_TIME
要比較一個時間大小,我須要這麼作,還須要將系統時間轉成字符串來給你對比,並且在轉換成字符串比較時,數據庫內部也會將其轉換成時間來比較,你以爲這種查詢條件會好到哪裏去?分佈式
咱們也知道在 JDK8 中新的時間 API LocalDateTime 中,有着豐富的時區轉換的方法可用,但即使你說你精通 LocalDateTime 的各類花式用法,你也不得不面對繁雜的轉換。
因此,咱們須要一個擁有「絕對是時間」,來幫助咱們記錄日期,幫咱們節省下轉換的時間,這個「絕對時間」就是時間戳,時間戳的定義是從一個基準時間開始算起,這個基準時間是「1970-1-1 00:00:00 +0:00」,從這個時間開始,用整數表示,以秒計時,隨着時間的流逝這個時間整數不斷增長。這樣一來,我只須要一個數值,就能夠完美地表示時間了,並且這個數值是一個絕對數值,即不管的身處地球的任何角落,這個表示時間的時間戳,都是同樣的,生成的數值都是同樣的,而且沒有時區的概念,因此在系統的中時間的傳輸中,都不須要進行額外的轉換了,只有在顯示給用戶的時候,才轉換爲字符串格式的本地時間。
並且很重要的一點就是,在現有的編程語言中,都提供了方法來獲取時間戳,這對於咱們不一樣語言的項目交互來講,不要太方便!因此在這裏我強烈建議先後端關於時間的交互,都用時間戳來交互。
這時,可能有同窗又來槓一波,你用一個出數值來表示時間,我查數據庫時,以個人眼力和口算,根本不知道時間是多少,我以爲這個根本不須要擔憂啊,你查數據庫無非是查看須要的數據而已,你在 sql 裏面對時間戳個時間轉換函數就行了,好比:
from_unixtime(1561053690000)
若是你還要繼續槓,說我就是要在數據庫表中看到時間,我以爲若是你要這樣,爲何還須要前端,直接拿數據庫當前端展現就行了。
我總結一下數據庫用數值保存時間戳的諸多好處: