LocalDateTime
LocalDateTime
本身不包含時區信息,它存儲的是年、月、日、時分秒,納秒這樣的數字。
在不同的時區下,這樣的數字代表不同的時間。
比如一個LocalDateTime存儲2020-01-01 08:00:00
,這里省略納秒。
對北京和東京的人來看這個時間,都認為是本地時間的話,在真實時間上,因為時區的差異,其實是相差1個小時的時間的。
構造函數
既然不帶時區,那么考慮LocalDateTime的構造函數:
LocalDateTime dtUtc = LocalDateTime.now(ZoneOffset.UTC);
為什么這里又有時區了呢?其實這是一個方便的方法:
如果只是為了獲取當前系統所在默認時區的一個本地時間,那么用LocalDateTime.now()
無參數構造方法即可,而如果我想知道現在在UTC時區那里本地顯示的是什么時間,就可以用LocalDateTime.now(ZoneOffset.UTC)
這個構造方法了。
所以對於我們東八區來說:
//假如這個時間是:2020-01-01 10:00:00
LocalDateTime dtLocal = LocalDateTime.now();
//那么這個時間就會存儲:2020-01-01 02:00:00,提前8個小時
LocalDateTime dtUtc = LocalDateTime.now(ZoneOffset.UTC);
在構造后,LocalDateTime
同樣不攜帶時區信息,仍然只是表示一個顯示時間而已。
Date
Date
存儲的是一個毫秒數,准確說是從1970-01-01 00:00:00到現在經過的毫秒數。
而這個毫秒數是有時區的,它存儲的永遠是現在針對UTC時區時的1970年零點,經過的毫秒數。怎么理解?
比如兩個程序員在同一時刻,一個在英國,一個在中國,同時調用new Date()
,那么此時Date
中存儲的毫秒數是完全相同的(當然是理想情況的同時,以及系統沒有誤差)。所不同的是在輸出時,GMT0時區,直接使用這個毫秒數計算得到顯示時間,而北京GMT+8顯示時,會在這個時間上增加8小時,即時區偏移。
所以如下兩個格式化類型,在當前東八區的使用場景,輸出實際是一樣的:
SimpleDateFormat bjSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 北京
bjSdf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); // 設置北京時區
SimpleDateFormat dftSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); // 不設置時區
構造
因為Date
有時區信息,所以構造Date
也就需要時區信息。
因此,不能直接從LocalDateTime
轉換成Date
,因為無法確定這個LodalDateTime究竟是哪個時區的這個時間。
而要借助Instant
,因為Instant
也代表從UTC開始的一個偏移時間。
LocalDateTime dt = LocalDateTime.now();
Date dt2 = Date.from(dt.toInstant(ZoneOffset.of("+8"))); //東八區