鑒於《網路新詞網路熱詞大全ACCESS資料庫》幾百條的記錄數太少,於是找了找網路上的一些流行熱詞網站,挑了個數據量大的採集了下來,經過整理(去除重覆、去除詞長超過10字)共得到1萬4千多條記錄。 熱詞:做完核酸可以領豆油解釋:疫情期間民眾耳朵不好使現狀。其實是“做完核酸不要逗留”。源自海南某地一排隊 ...
JDBC連接時有個TimeZone配置,這玩意到底有用嗎?我是使用Postgresql和Mysql兩個資料庫驗證的。結果如下:
資料庫 | 部署方式 | 版本 | JDBC連接TimeZone參數 | JDBC連接serverTimezone參數 | 總結 |
Mysql | docker | 8.0 | 沒用 | 有用,會使用客戶端時區與設置的參數時區比較,並返回客戶端時區對應的時間,詳見實例1 | Mysql使用JDBC連接時可以配置serverTimezone參數告訴客戶端伺服器的時區,因為Mysql的TimeStamp類型是沒有時區概念的,且沒有timestamp with time zone數據類型,只能通過連接時配置資料庫server的時區,並通過兩時區的對比,返回正確的客戶端時區的時間 |
Postgresql | docker | 15.3 | 沒用 | 沒用 | Postgresql使用JDBC連接時,時區參數均無效,但Postgresql有timestamp with time zone數據類型,使用該數據類型時不管資料庫是什麼時區設置,也不管客戶端是什麼時區設置,只要你的客戶端時區不變,你存取得到的都是同一個時間,該時間的時區取決於客戶端的時區。資料庫中存儲的是對應的UTC時區時間,比如:2023-05-24 00:51:24.578703 +00:00,詳見實例2 |
實例1:
使用Mysql資料庫,建表DDL如下:
create table test ( a int null, b timestamp null );
資料庫中存儲的數據:
使用JDBC連接,不配置serverTimezone參數,客戶端時區為東八區,執行以下SQL並用Java Date類型接收輸出:
SELECT b FROM test WHERE a = 1; SELECT now();
輸出結果,註意Java的Date類型本身是沒有時區屬性的,這裡之所以輸出了CST可以自行研究Date的toString方法:
Tue May 23 15:13:46 CST 2023 Wed May 24 01:11:17 CST 2023
使用JDBC連接,配置serverTimezone參數為serverTimezone=UTC,客戶端時區為東八區,執行上面的SQL並用Java Date類型接收輸出:
Tue May 23 23:13:46 CST 2023 Wed May 24 09:12:52 CST 2023
總結:
當不使用serverTimezone配置時,JDBC連接中伺服器時區被認為與客戶端時區相同,因此資料庫中存儲的時間返回時被認為是東八區時間,無需變動,但SELECT now();返回的是Mysql伺服器時間,即UTC時間。配置serverTimezone參數後,JDBC連接中伺服器時區為UTC,客戶端時區為東八區,查詢資料庫中時間被認為是UTC時間,返回給客戶端時進行+8小時操作,同時SELECT now();返回值經過時區轉換,正確的返回了東八區時間。
實例2:
使用Postgresql資料庫,建表DDL如下:
create table test ( a integer, b timestamp with time zone );
客戶端時區為東八區,分別執行以下SQL:
INSERT INTO test VALUES (2, now()); SELECT b FROM test WHERE a = 2; SELECT now();
查詢結果如下:
Wed May 24 09:39:39 CST 2023 Wed May 24 09:39:39 CST 2023
資料庫中存儲結果:
修改客戶端時區為東九區,重新執行以上SQL:
Wed May 24 10:42:17 KST 2023 Wed May 24 10:42:17 KST 2023
資料庫中存儲結果:
總結:
使用Postgresql的timestamp with time zone數據類型時,不管資料庫是什麼時區設置,也不管客戶端是什麼時區設置,只要你的客戶端時區不變,你存取得到的都是同一個時間,該時間的時區取決於客戶端的時區。資料庫中存儲的是轉換後的UTC時間。
綜上:
使用Mysql時,JDBC連接中應正確配置serverTimezone參數;使用Postgresql時,使用timestamp with time zone數據類型。來保證獲取時間時時區的正確性。
另外,建議能不用資料庫的now()就別用了,資料庫時區會搞得你頭疼;更近一步,能別用時間(Date)就別用了,時間戳沒有時區的概念,當前端需要顯示的時候再通過DateFormat或Json轉換配置時區即可,可以省去很多需要考慮時區的工作。
以上是我自己的實驗結果,如果你有不同的結論,歡迎一起探討。