一個時間字段引發的血案
本文轉載自微信公眾號「六脈神劍的程序人生」,作者六脈神劍小六六 。轉載本文請聯系六脈神劍的程序人生公眾號。
hi ,大家好,我是三天打魚,兩天曬網的小六六
前言
文本已收錄至我的GitHub倉庫,歡迎Star:https://github.com/bin392328206/six-finger
種一棵樹最好的時間是十年前,其次是現在
之前因為存儲時間的原因導致了一些Bug,然后發現自己對這塊的知識也比較薄弱,所以系統的跟大家一起來學習學習。
Bug回顧
就是比如訂單哈,我們一般會有這么幾個時間,第一個是下單時間,第二個是訂單更新時間,第三個是我方的完成時間,第四個是渠道的完成時間,但是當初設計的時候呢?我們的下單時間用了字符串去表示,這樣就有一個問題,你用字符串表示,說明你當時存儲的時候就已經默認了時區了,所以當前端去用這個時間的時候,就會和用戶的本地時間去做比較,然后我這邊又有做的是一些海外項目,那么就有這樣一種可能就是你付款的時間比你訂單的下單時間還早,因為渠道的完成時間可能用的是他們自己渠道的時區,而我們的服務器默認用的東八區的時區的字符串。
UTC時間
UTC時間又稱協調世界時 協調世界時,又稱世界統一時間、世界標準時間、國際協調時間。由于英文(CUT)和法文(TUC)的縮寫不同,作為妥協,簡稱UTC。協調世界時是以原子時秒長為基礎,在時刻上盡量接近于世界時的一種時間計量系統。中國大陸采用ISO 8601-1988的《數據元和交換格式信息交換日期和時間表示法》(GB/T 7408-1994)稱之為國際協調時間,代替原來的GB/T 7408-1994;中國臺灣采用CNS 7648的《資料元及交換格式–資訊交換–日期及時間的表示法》,稱之為世界統一時間。
時區
地球的自轉運動產生了太陽東升西落現象,日出為晝、日落為夜。世界各地以晝夜交替現象為基礎確定日期變化和時間推移。
然而各地位置不同時間標準不一造成了時間上的混亂。為了克服這種局面,1884年,各國在華盛頓召開國際經度會議,與會國家創立了通用的標準時間制度——以180°經線為理論上的日界線,經度每隔15°,地方時相差1小時。
雖然我國橫跨多個時區,但只采用了一個標準時區,這也是長期實踐得來的結果。中美時區制度不同的根本原因在于人口分布的區別。受制于地形和經濟發展水平問題,美國的大城市和人口聚集區在中部和東西海岸;而中國的人口分布相對集中,絕大多數在“黑河騰沖線”以東。
現在我們談到的“北京時間”,并不是真正意義上的北京時間,而是以陜西省渭南市蒲城縣授時中心發出的東八區時間(東經120度)作為統一稱呼的“北京時間”。
時間戳
“時間戳是指格林威治時間自1970年1月1日(00:00:00GMT)至當前時間的總秒數。通俗的講,時間戳是一份能夠表示一份數據在一個特定時間點已經存在的完整的可驗證的數據。”
在計算機中,「時間戳」一般是指 Unix 時間戳,即自從 Unix 紀元(格林威治時間 1970 年 1 月 1 日 00:00:00)到當前時間的秒數。
時間戳是可以轉換成任何時區的時間
數據庫如何存儲時間
字符串存儲日期
想必大家在剛開始接觸開發的時候,這種做法是可取的,簡單,容易上手,可識別性比較高,一看就懂
- 字符串占用的空間更大
- 字符串存儲的日期比較效率比較低(逐個字符進行比對),無法用用日期相關的API進行計算比較。
- 時區問題 你存字符串是你沒辦法存儲時區的,如果是海外項目會有很多的問題,所以對于一些項目來說存它是非常不適合的
Datetime和Timestamp
Datetime 和 Timestamp 是 MySQL 提供的兩種比較相似的保存時間的數據類型。他們兩者究竟該如何選擇呢?
首選TimeStamp。
datetime 更像日歷上面的時間和你手表的時間的結合,就是指具體某個時間。
timestamp 更適合來記錄時間,比如我在東八區時間現在是 2016-08-02 10:35:52, 你在日本(東九區此時時間為 2016-08-02 11:35:52),我和你在聊天,數據庫記錄了時間,取出來之后,對于我來說時間是 2016-08-02 10:35:52,對于日本的你來說就是 2016-08-02 11:35:52。所以就不用考慮時區的計算了。
時間范圍是 timestamp 硬傷(1970-2038),當然 datetime (1000-9999)也記錄不了劉備什么時候出生(161 年)。
DateTime類型沒有時區信息的(時區無關) DateTime 類型保存的時間都是當前會話所設置的時區對應的時間。這樣就會有什么問題呢?當你的時區更換之后,比如你的服務器更換地址或者更換客戶端連接時區設置的話,就會導致你從數據庫中讀出的時間錯誤。不要小看這個問題,很多系統就是因為這個問題鬧出了很多笑話。
數值型時間戳是更好的選擇嗎
很多時候,我們也會使用 int 或者 bigint 類型的數值也就是時間戳來表示時間。
這種存儲方式的具有 Timestamp 類型的所具有一些優點,并且使用它的進行日期排序以及對比等操作的效率會更高,跨系統也很方便,畢竟只是存放的數值。缺點也很明顯,就是數據的可讀性太差了,你無法直觀的看到具體時間。
總結
推薦 Timestamp,原因是數值表示時間不夠直觀
每種方式都有各自的優勢,根據實際場景才是王道。下面再對這三種方式做一個簡單的對比,以供大家實際開發中選擇正確的存放時間的數據類型:
好了今天的分享就到這了,我是小六六,三天打魚,兩天曬網。