Java時區問題

時間格式

UTC是以原子時計時,更加精準,適應現代社會的精確計時。不過通常使用不須要精確到秒時,視爲等同。GMT是前世界標準時,UTC是現世界標準時。每一年格林尼治天文臺會發調時信息,基於UTC。
GMT和 UTC能夠視爲幾乎是等同的,UTC更精準,有閏秒的概念。前端

//世界標準時間UTC,其中T表示時分秒的開始(或者日期與時間的間隔),Z表示這是一個世界標準時間
String utcStr = "2010-10-12T15:24:22Z";
//本地時間,也叫不含時區信息的時間,末尾沒有Z
String localStr = "2010-10-12T15:24:22";
//含有時區的時間,+08:00表示該時間是由世界標準時間加了8個小時獲得的,[Asia/Shanghai]表示時區 
String zoneStr = "2017-12-13T09:47:07.153+08:00[Asia/Shanghai]";

表示時間相關的類

表示時間的類主要有個:String、Instant、LocalDateTime、ZonedDateTime,
String是字符串形式的時間,Instant是時間戳,LocalDateTime是不含時區信息的時間,ZonedDateTime是含有時區信息的時間。java

LocalDateTime

符合格式的String 能夠直接轉換爲LocalDateTime數據庫

System.out.println(LocalDateTime.parse("2019-12-15 10:10:10", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

LocalDateTime字面意思是本地時間,實際上它能夠理解爲不含時區信息的時間,只儲存了年月日時分秒,要表達是哪裏的時間須要時區解釋。後端

Instant與ZonedDateTime

Instant是時間戳,是指世界標準時格林威治時間1970年01月01日00時00分00秒(北京時間1970年01月01日08時00分00秒)起至如今的總秒數,Instant自己已經攜帶了時區信息,默認是0時區。
ZonedDateTime是含有時區信息的時間,能夠理解爲它是Instant的格式化對象,
JDK 8之前的時區是用TimeZone,TimeZone ID是在java裏ZoneInfoFile類加載的。在jvm初始化的時候,會讀取jdk安裝目錄下的 ${ java.home } /jre/lib/tzdb.dat,放到其成員變量爲zones的ConcurrentHashMap裏。當調用TimeZone.getTimeZone(id)方法時,會用id到這個map裏進行匹配獲取到指定id的時區。其中TimeZone.getTimeZone("Asia/Shanghai")和TimeZone.getTimeZone("GMT+8")是相同的,能夠相互替換使用。瀏覽器

System.out.println(ZonedDateTime.ofInstant(Instant.now(),ZoneId.systemDefault()).toInstant());
System.out.println(ZonedDateTime.ofInstant(Instant.now(),"Australia/Darwin").toInstant());

相同的Instant,在不一樣的時區有不一樣的展現時間,因此在用Instant構造ZonedDateTime的時候須要傳入時區;ZonedDateTime能夠直接轉化爲Instant,而且不一樣的ZonedDateTime可能會生成一樣的Instant服務器

時區轉換

用戶輸入的String類型的時間是沒有時區信息的,須要人爲指定時區再解析。
解析的步驟分2步: 先肯定用戶時區
1.把用戶輸入的時間轉化爲世界標準時間;//Instant.parse("2010-10-12T15:24:22Z")
2.再把世界標準時間轉爲須要的時區的時間。//ZonedDateTime.ofInstant(instant,ZoneId.systemDefault());jvm

不一樣地區的服務器統一時間的解決方案

首前後端封裝一個接口後獲取服務器相對GMT(格林尼治標準時間)時間的偏移量:code

TimeZone zone = TimeZone.getDefault(); 
System.out.println(zone.getRawOffset());

這段代碼放在不一樣時區的服務器上執行結果會不一樣(前提是服務器的時區設置跟本地時區一致)。若是在泰國執行結果爲25200000ms,換算成小時爲7,說明泰國的時區的偏移量相對於GMT標準時間相差7小時。下文簡稱「時區偏移量」。orm

前端首先調用該接口獲取服務器的時區偏移量,再在瀏覽器上獲取本地的時區偏移量,計算出兩個偏移量的差值。本地瀏覽器上獲取當前的時間戳,減去上一步計算出來的差值便可獲得服務器這個時間的時間戳,把這個時間戳傳給後端 再轉換成時間,就是服務器對應的時間,存入數據庫便可。
前端:server

//服務的時區偏移量,經過接口得到,注意換成負值 
var serveroffset=-25200000; 
var d = new Date(); 
//獲取本地瀏覽器的時區偏移量 
var localOffset = d.getTimezoneOffset() * 60000; 
//的到本地和偏移量的差值 
var deffoffset=localOffset-(serveroffset); 
//獲取本地瀏覽器時間戳 
var localTime = d.getTime(); 
//計算出傳到服務器的時間戳 
var servertime=localTime+deffoffset;

經過上述方式,能夠實現服務器全球各地部署,系統均可以正常使用。

相關文章
相關標籤/搜索