資料庫儲存時間的時區問題

2021-09-20 03:06:28 字數 1240 閱讀 8463

先說一下mysql中datetime和timestamp的區別

timestamp是標準的unix timestamp,它儲存的是1970-1-1到現在經過的秒數,4位元組儲存。mysql用這個型別還蠻方便的,乙個是有很多內建的函式和trigger來處理它,比如current_timestamp巨集,最關鍵的是在取資料的時候mysql會自動幫你處理dst和時區的問題。

datetime的範圍更大,好像可以從0000-00-00 00:00:00到9999-12-31 23:59:59,8位元組儲存,當然mysql內部肯定也是用整數而不是字串的(說了是8位元組了),所以效率不是大問題。但datetime不帶時區,比如我在程式裡生成了乙個2015-05-07 15:26:00的時間(實際上是+8時區的,但這個物件可能是timezone *****)的,存到mysql裡,再從不同時區的地方拿出來,這個時間可能就混了。

但timestamp也有兩個很大的問題:

4位元組長度限制,它只能到2023年

很多時候我們希望根據使用者所在地的時區顯示時間而不是光顯示乙個伺服器時間

所以比較好的做法是,資料庫中使用datetime,然後存時間的時候一律用程式生成utc時間(而不是local時區的時間)存進去,取出來的時候不管想顯示伺服器時間還是顯示使用者的時間都可以處理。

順便提一句,根據使用者所在地時區顯示時間有兩種做法:

當使用者第一次訪問**的時候,用js獲取時區傳送到伺服器上存到session裡

用js處理時間的顯示(我覺得這種比較方便一點,畢竟不用改服務端**)

使用這種做法的唯一缺點是sqlite3沒有internal的datetime型別,所以在orm框架如sqlalchemy中,它會直接存字串進去。(sqlite3的文件也說,你要麼存成int要麼real要麼字串)。儘管這可能帶來一些不方便和效能的下降,但我認為還是符合「keep it ****** and stupid」的原則。

至於用int存時間,是另一種可行的方法,參見

我個人不是很喜歡這麼做,因為這樣你必須把模型中表示時間的成員宣告為int型別。這樣是比較不符合邏輯的(那些date呀datetime之類的類就沒有用了呀,最多就有個dateutil就好了),而且會使得程式不易讀(臥槽這個publisheddate為什麼是int,它到底表示的是時間嗎?)。總之見仁見智。

資料庫如何儲存時間

主要會有下面兩個問題 字串占用的空間更大 字串儲存的日期比較效率比較低 逐個字元進行比對 無法用日期相關的 api 進行計算和比較。datetime 和 timestamp 是 mysql 提供的兩種比較相似的儲存時間的資料型別。通常我們都會首選 timestamp。原因如下 2.1 datetim...

設定資料庫時區

1 mysql安裝目錄下my.ini配置檔案中新增 需要修改資料庫配置 設定預設時區 default time zone 08 00 此方法針對前台到後台時使用 spring.jackson.time zone gmt 8 增加 servertimezone gmt 2b8例如 spring.dat...

修改MySql資料庫時區

先檢查mysql的時區,開啟一台mysql時區正確的機器,然後開啟有問題的機器,確認是時區錯誤。先開啟時區正確的機器 進入mysql,在命令列輸入 mysql uroot p root的密碼 進去之後輸入show variables like time zone 然後回車,得到如下的顯示 varia...