在 LocalDateTime 和 ZonedDateTime 之間轉換
一、概述
Java LocalDateTime
API 表示和操作日期和時間的組合。 ZonedDateTime
是一個不可變的對象,它包含精度為納秒的日期時間值、基於ISO 8601 日曆系統的時區值,以及用於處理不明確的本地日期時間的ZoneOffSet
。
在本教程中,我們將了解如何將LocalDateTime
轉換為ZonedDateTime
,反之亦然。
2. 將LocalDateTime
轉換為ZonedDateTime
讓我們首先將LocalDateTime
的實例轉換為ZonedDateTime.
2.1.使用atZone()
方法
LocalDateTime
實例中的atZone()
方法執行到ZonedDateTime
的轉換並保持相同的日期時間值:
LocalDateTime localDateTime = LocalDateTime.of(2022, 1, 1, 0, 30, 22);
ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.of("Canada/Atlantic"));
assertEquals(localDateTime.getYear(), zonedDateTime.getYear());
assertEquals(localDateTime.getMonth(), zonedDateTime.getMonth());
assertEquals(localDateTime.getDayOfMonth(), zonedDateTime.getDayOfMonth());
assertEquals(localDateTime.getHour(), zonedDateTime.getHour());
assertEquals(localDateTime.getMinute(), zonedDateTime.getMinute());
assertEquals(localDateTime.getSecond(), zonedDateTime.getSecond());
atZone()
方法接收ZoneId
值,該值指定基於 ISO 8601 日曆系統的時區。
調用withZoneSameInstant()
方法使用ZoneOffSet
時差轉換為實際的日期時間值:
LocalDateTime localDateTime = LocalDateTime.of(2022, 1, 1, 0, 30, 22);
ZonedDateTime zonedDateTime = localDateTime.atZone(ZoneId.of("Africa/Lagos")).withZoneSameInstant(ZoneId.of("Canada/Atlantic"));
assertEquals("2021-12-31T19:30:22-04:00[Canada/Atlantic]", zonedDateTime.toString());
assertEquals("-04:00", zonedDateTime.getOffset().toString());
我們可以通過調用靜態ZoneId.getAvailableZoneIds()
方法來獲取可用的ZoneId
。此方法返回一組所有可用的基於區域的 ID,作為String
s,我們可以從中選擇以創建ZoneId
對象。
此外,使用atZone()
進行的轉換還帶有一個ZoneOffSet
值,該值提供ZonedDateTime
對象與 UTC (GMT) 之間的時差(上例中的-04:00
)。
2.2.使用ZonedDateTime.of()
方法
ZonedDateTime
類還提供了一個靜態of()
方法來創建ZonedDateTime
對象。該方法接受LocalDateTime
和ZoneId
的實例作為參數並返回ZonedDateTime
對象:
LocalDateTime localDateTime = LocalDateTime.of(2022, 11, 5, 7, 30, 22);
ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, ZoneId.of("Africa/Accra")).withZoneSameInstant(ZoneId.of("Africa/Lagos"));
assertEquals("2022-11-05T08:30:22+01:00[Africa/Lagos]", zonedDateTime.toString());
assertEquals(localDateTime.getYear(), zonedDateTime.getYear());
在這種情況下,正如我們之前看到的,我們也可以通過調用withZoneSameInstant()
方法來獲取給定區域的實際日期時間值。
2.3.使用ZonedDateTime.ofInstant()
方法
我們還可以結合使用ZoneOffSet
對象和LocalDateTime
來創建ZonedDateTime
對象。
靜態ofInstant()
方法接受LocalDateTime
、 ZoneOffSet
和ZoneId
對像作為參數:
LocalDateTime localDateTime = LocalDateTime.of(2022, 1, 5, 17, 30, 22);
ZoneId zoneId = ZoneId.of("Africa/Lagos");
ZoneOffset zoneOffset = zoneId.getRules().getOffset(localDateTime);
ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(localDateTime, zoneOffset, zoneId);
assertEquals("2022-01-05T17:30:22+01:00[Africa/Lagos]", zonedDateTime.toString());
ZonedDateTime
對像是從通過組合LocalDateTime
和ZoneOffSet
對象隱式形成的Instant
對象創建的。
2.4.使用ZonedDateTime.ofLocal()
方法
靜態的ofLocal()
方法從LocalDateTime
對象創建一個ZonedDateTime
,並將首選的ZoneOffSet
對像作為參數傳遞:
LocalDateTime localDateTime = LocalDateTime.of(2022, 8 , 25, 8, 35, 22);
ZoneId zoneId = ZoneId.of("Africa/Lagos");
ZoneOffset zoneOffset = zoneId.getRules().getOffset(localDateTime);
ZonedDateTime zonedDateTime = ZonedDateTime.ofLocal(localDateTime, zoneId, zoneOffset);
assertEquals("2022-08-25T08:35:22+01:00[Africa/Lagos]", zonedDateTime.toString());
通常,本地日期時間只存在一個有效偏移量。當發生時間重疊時,將有兩個有效偏移量。
如果作為參數傳遞的首選ZoneOffset
是有效偏移量之一,則使用它。否則,轉換將保持先前的有效偏移量。
2.5.使用ZonedDateTime.ofStrict()
方法
同樣,靜態ofStrict()
方法通過嚴格驗證LocalDateTime
、 ZoneOffSet
和ZoneID
參數的組合返回一個ZonedDateTime
對象:
LocalDateTime localDateTime = LocalDateTime.of(2022, 12, 25, 6, 18, 2);
ZoneId zoneId = ZoneId.of("Asia/Tokyo");
ZoneOffset zoneOffset = zoneId.getRules().getOffset(localDateTime);
ZonedDateTime zonedDateTime = ZonedDateTime.ofStrict(localDateTime, zoneOffset, zoneId);
assertEquals("2002-12-25T06:18:02+09:00[Asia/Tokyo]", zonedDateTime.toString());
如果我們提供無效的參數組合,該方法將拋出DateTimeException
:
zoneId = ZoneId.of("Asia/Tokyo");
zoneOffset = ZoneOffset.UTC;
assertThrows(DateTimeException.class, () -> ZonedDateTime.ofStrict(localDateTime, zoneOffset, zoneId));
上面的示例表明,當我們嘗試使用Asia/Tokyo
的ZoneId
和表示默認 UTC ( GMT + 0
) 的ZoneOffSet
值的組合創建ZonedDateTime
對象時,會拋出異常。
3. 將ZonedDateTime
轉換為LocalDateTime
ZonedDateTime
對象維護三個不同的對象: LocalDateTime
、 ZoneId
和ZoneOffset
。
我們可以使用toLocalDateTime()
方法將ZonedDateTime
的實例轉換為LocalDateTime
:
ZonedDateTime zonedDateTime = ZonedDateTime.of(2011, 2, 12, 6, 14, 1, 58086000, ZoneId.of("Asia/Tokyo"));
LocalDateTime localDateTime = zonedDateTime.toLocalDateTime();
assertEquals("2011-02-12T06:14:01.058086+09:00[Asia/Tokyo]", zonedDateTime.toString());
此方法檢索作為ZonedDateTime
屬性的一部分存儲的LocalDateTime
對象。
4。結論
在本文中,我們了解瞭如何將LocalDateTime
的實例轉換為ZonedDateTime
,反之亦然。
與往常一樣,這些示例的源代碼可在 GitHub 上獲得。