服務端時區問題

這是我參與8月更文挑戰的第3天,活動詳情查看:8月更文挑戰mysql

關於時區,咱們先聊一下這樣場景:程序員

咱們有一個商城系統,當用戶在 2021-08-03 晚上8點時下了一筆單,這筆訂單的下單時間能夠記做 2021-08-03 20:00:00 或1627992000000(時間戳)。咱們並把這個時間儲存到數據庫,之後用戶查詢訂單記錄時,這筆訂單的下單時間都爲 2021-08-03 20:00:00sql

當咱們這個商城系統面向全球時,在上面所說的同一時刻,有一個美國用戶在美國當地也下單了,那這個下單時間應該記爲何呢?仍是 2021-08-03 20:00:00 嗎?但衆所周知,美國當地時間顯然不是晚上8點,而是 2021-08-03 08:00:00(東部時間),若是用戶在查詢訂單時,看到下單的時間是 2021-08-03 20:00:00,他必定會以爲這是系統bug。數據庫

那咱們有什麼解決方法呢,最直接的方法就是增長兩個下單時間字段:中國下單時間(下單時在中國屬於什麼時間),美國下單時間(下單時在美國屬於什麼時間)。這樣咱們能夠把中國下單時間和美國下單時間都記下來,美國用戶查詢訂單時,就用美國下單時間。雖然這能暫時解決咱們的問題,可是若是真的這樣設計,程序員必定會瘋的,由於除了中國時間、美國時間,還有全球各地的時間。其實,最正確的處理方式就是給咱們的時間,增長時區概念。windows

時區:因爲世界各國家與地區經度不一樣,地方時也有所不一樣,所以會劃分爲不一樣的時區。爲了照顧到各地區的使用方便,又使其餘地方的人容易將本地的時間換算到別的地方時間上去,有關國際會議決定將地球表面按經線從東到西,劃成一個個區域,而且規定相鄰區域的時間相差1小時,現今全球共分爲24個時區。服務器

回到上面的問題,下單時間2021-08-03 20:00:00,咱們把這個時間設定爲北京時間(東八區),咱們能夠根據時區對應關係,算出對應各地的時間,如此時美國東部時間爲2021-08-03 08:00:00。markdown

MySQL時區相關問題

查看mysql當前時區
show variables like'%time_zone';
複製代碼

查詢結果(MySQL版本:5.5.20):oop

image.png

說明當前MySQL的時區根據系統時區決定。post

數據庫時區變化

當咱們有以下數據:spa

// 表結構
CREATE TABLE `t_order` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
)
// 表數據
id      create_time`
1	2021-08-03 20:00:00
複製代碼

修改系統時區,將北京時間改成美國東部時間(win1o系統可參考:如何更改 Windows 10 系統時區設置的 4 種簡單方法),並重啓MySQL服務器, 數據將會變爲:

id      create_time`
1	2021-08-03 08:00:00
複製代碼
數據庫連接配置項serverTimezone

使用Mybatis查詢數據庫數據庫時,咱們能夠指定serverTimezone配置來控制日期對應的時區

一般的配置:

serverTimezone=GMT%2B8  // 時區爲GMT+8,東八區時間,即北京時間。 說明:%2B爲「+」的URL轉碼
serverTimezone=Asia/Shanghai // 上海時區,也爲北京時間。 
複製代碼

若是須要修改時區,只須要修改配置,如serverTimezone=GMT%2B9東九區時間;serverTimezone=America/Chicago美國芝加哥時間。城市可參考:全球地區時區代碼

LocalDateTime 和 Date

Java的LocalDateTime和Date類均可以表示時間,但它們仍是有區別的。其中一個區別就是時區:

LocalDateTime 本地時間,當咱們查詢數據庫時間數據時,無論serverTimezone配置成哪一個時區,若是咱們LocalDateTime接收數據,時間都是同樣的。

Date 時間,當咱們查詢數據庫時間數據時,Date接收的時間會根據serverTimezone配置的時區而變化。

Java根據時區格式化時間

用法:

Long t = 1627992000000L;

SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 指定時區
df.setTimeZone(TimeZone.getTimeZone("GMT+8"));
System.out.println(df.format(t));


SimpleDateFormat df1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 指定時區
df1.setTimeZone(TimeZone.getTimeZone("GMT+7"));
System.out.println(df1.format(t));

SimpleDateFormat df2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// 使用系統默認時區,可經過TimeZone.setDefault()方法修改系統默認時區(全局生效)
System.out.println(df2.format(t));

// 輸出結果:
2021-08-03 20:00:00
2021-08-03 19:00:00
2021-08-03 20:00:00
複製代碼
相關文章
相關標籤/搜索