Java8中的時間處理
Java8提供了全新的時間處理框架,這裡就可以完全丟棄之前的Date、Calendar了。
具體的API的使用都是比較簡單的。這裡就不展開介紹了。
這裡主要介紹下一些主要的類
LocalDateTime
我們一般常用的就是這個了,用這個來表示日期時間。如LocalDateTime.now()
就可以基於當前預設時區得到當前的日期時間。
由於全球有好多時區,同一個日期時間,在不同的時區,反映到時間軸上是不同的。
LocalDateTime型別的日期時間是沒包含時區,所以它不能對應到時間軸上。說的直白點就是LocalDateTime不能轉換成自 1970-01-01T00:00:00Z 紀元以來的毫秒數。
ZonedDateTime
ZonedDateTime可以理解就是在LocalDateTime的基礎上新增上時區,所以它是可以反映到時間軸上的。
下面用夏令時舉個例子來看看LocalDateTime和LocalDateTime的區別。
夏令時是什麼這裡就不展開了,具體可以網上查下。看看我國1986開始的夏令時。
簡單來說就是在夏令時開始的時候,將時鐘向後撥1個小時。對應我國1986年開始的夏令時的做法,就是在每年四月中旬的第一個星期日當時鍾到達凌晨2點時,直接將時鐘撥到凌晨3點。也就是凌晨1點和凌晨3點之間之差1個小時。
由於1986年是開始實施的,所以1986年的夏令時是1986年5月4日開始的。
我們看看1987年的夏令時開始
根據我國當時的夏令時政策,1987年應該是1987年4月12日開始的。具體來說就是在1987-04-12 01:00:00 過一個小時後,時間應該是1987-04-12 03:00:00
LocalDateTime localDateTime = LocalDateTime.of(1987, 4, 12, 1, 0, 0, 0);
System.out.println(localDateTime);
System.out.println(localDateTime.plusHours(1));
執行上面的程式碼就可以看到當1987-04-12 01:00:00增加1小時後,時間是1987-04-12 02:00:00。
這個也好理解,因為LocalDateTime並沒有包含時區,1987-04-12 02:00:00這個夏令時只是中國的,並不是全球統一的,如果1987-04-12 02:00:00將直接變成1987-04-12 03:00:00放到中國以外的其他國家就是錯誤的。
ZonedDateTime zonedDateTime = ZonedDateTime.of(1987, 4, 12, 1, 0, 0, 0, ZoneId.systemDefault());
System.out.println(zonedDateTime);
System.out.println(zonedDateTime.plusHours(1));
執行上面的程式碼可以看到當1987-04-12 01:00:00增加1小時後,時間變成了是1987-04-12 03:00:00。這個也就能說明問題了。
同時從列印結果也能看到時區自動從+08:00[Asia/Shanghai]變成了+09:00[Asia/Shanghai]
Instant
Instant表示時間軸上的一個瞬時時間,簡單來說就是表示自 1970-01-01T00:00:00Z 紀元以來的秒數、毫秒數等等
ZonedDateTime和Instant都能對應到時間軸上,所以它們兩個是可以相互轉化的。
Instant instant = zonedDateTime.toInstant();
ZonedDateTime zonedDateTime1 = instant.atZone(zonedDateTime.getZone());
其他一些常用的各種型別之間轉化的API
//ZonedDateTime 轉 Instant
Instant instant = ZonedDateTime.now().toInstant();
//獲取UTC毫秒數
long epochMilli = instant.toEpochMilli();
//Instant 轉 ZonedDateTime
ZonedDateTime zonedDateTime = instant.atZone(ZoneId.systemDefault());
//字串 轉 ZonedDateTime
ZonedDateTime zonedDateTime2 = ZonedDateTime.parse(zonedDateTime.toString());
//基於UTC 偏移的毫秒數
int totalSeconds = zonedDateTime.getOffset().getTotalSeconds();
//Instant 轉 LocalDateTime
LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
//LocalDateTime 轉 ZonedDateTime
ZonedDateTime zonedDateTime1 = localDateTime.atZone(ZoneId.systemDefault());
ZoneRules zoneRules = ZoneId.systemDefault().getRules();
//判斷是否是夏令時時間
boolean daylightSavings = zoneRules.isDaylightSavings(instant);
Calendar calendar = Calendar.getInstance(TimeZone.getDefault());
//Calendar 轉 Instant
Instant instant1 = calendar.toInstant();
//Calendar 轉 ZonedDateTime
Calendar now = Calendar.getInstance();
ZonedDateTime zdt = ZonedDateTime.ofInstant(now.toInstant(), ZoneId.systemDefault()));
//Date 轉 Instant
Date date = new Date();
Instant inst = date.toInstant();
// Instant 轉 Date
Date newDate = Date.from(inst);
//GregorianCalendar 轉 ZonedDateTime
GregorianCalendar cal = GregorianCalendar.from(ZonedDateTime.now());
TimeZone tz = cal.getTimeZone();
ZonedDateTime zdt1 = cal.toZonedDateTime();
//ZonedDateTime 轉 GregorianCalendar
GregorianCalendar newCal = GregorianCalendar.from(zdt1);
LocalDateTime ldt = zdt.toLocalDateTime();
LocalDate date2 = zdt.toLocalDate();
LocalTime time2 = zdt.toLocalTime();
更詳細的資料,還是看官方的文件吧。https://docs.oracle.com/javase/tutorial/datetime/index.html