開發項目過程中經常會出現服務器的時區設置爲UTC,而開發機則爲GMT+8的情況,這種時候,程序運行就會存在問題,比如數據的插入時間不正確,與舊系統通信時,時間戳轉化不正確等等異常情況,排查起來較爲費勁,爲了解決時區問題,在Java中,jdk8提供了java.time包的LocalDateTime和ZoneDateTime解決方案
LocalDateTime不帶有時區信息,而ZoneDateTime帶有時區信息
jshell> ZonedDateTime.now()
$6 ==> 2018-08-01T12:51:04.006387+08:00[Asia/Shanghai]
jshell> LocalDateTime.now()
$7 ==> 2018-08-01T12:51:14.459202
在jackson框架對LocalDateTime的補丁:
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
</dependency>
下,LocalDateTime將會被解析成爲類似
"2018-08-30T11:20:20"//當服務器的時間爲GMT+8時
"2018-08-30T03:20:20"//當服務器的時間爲UTC時
而ZoneDateTime將會被解析成爲類似
"2018-08-30T11:20:20+08:00" //當服務器的時間爲GMT+8時
"2018-08-30T03:20:20Z"//當服務器的時間爲UTC時
可以看出,時間在ZoneDateTime類中將會以帶有時區信息的格式出現
這種數據在與前端進行交互時,一般使用Date.parse方法,如下所示:
Date.parse('2018-08-30T03:20:20Z')
1535599220000
Date.parse('2018-08-30T11:20:20+08:00')
1535599220000
var a=new Date(1535599220000)
Thu Aug 30 2018 11:20:20 GMT+0800 (中國標準時間)
可以看出來,js直接將時間轉換成了本地瀏覽器時區的時間戳。
對於LocalDateTime來說,顯示如下:
Date.parse('2018-08-30 03:20:20')
1535570420000
Date.parse('2018-08-30T03:20:20')
1535570420000
var b=new Date(1535570420000)
Thu Aug 30 2018 03:20:20 GMT+0800 (中國標準時間)
可以看出來,用LocalDateTime方式在前端parse出來,再進行new Date的對象b的時區存在問題,不能再進行時區調整。
所以在此推薦前後端交互時,嚴格使用帶有時區的datetimeString形如"2018-08-30T03:20:20Z",
即在java中通過ZoneDateTime進行時間相關的處理。
在數據庫中,則使用帶有時區信息的類型去處理時間,比如在postgreSQL中的timestamptz字段。MySQL中無法做時區處理,推薦使用統一時區:UTC時區,在程序中做相關處理。
如此可以省去部署過程中對機器的時區做調整的步驟。