Java新的時間API究竟怎麼用
- 2019 年 10 月 7 日
- 筆記
Java新時間API中有三個特別重要的類,分別是Instant、LocalDateTime、ZonedDateTime,它們分別對應到上一篇文章中講到的時間概念為:機器時間、無時區的本地時間、有時區的本地時間。
機器時間其實可以理解為UTC時間的另一種表現形式,其可以唯一確定時間線上的某一時刻。
無時區的本地時間因為沒有時區信息,所以其無法唯一確定時間線上的某一時刻。
有時區的本地時間其實是在UTC時間的基礎上加一些時間偏移,所以也是可以唯一確定時間線上的某一時刻。
Java的新時間API其實都是圍繞這三個類來實現的,所以,徹底理解這三個類的目的及使用場景對於靈活使用Java新時間API來說非常重要。
下面我們用示例來講解下Java的新時間API究竟怎麼用。
1. 獲取當前時間的年月日等信息。
static void t1() { LocalDateTime ldt = LocalDateTime.now(); System.out.println(ldt.getYear()); ZonedDateTime zdt = ZonedDateTime.now(); System.out.println(zdt.getYear()); // 對於獲取當前時刻的human time信息(年月日時分秒)來說 // 用LocalDateTime或者ZonedDateTime都是一樣的 // 他們的底層都是先獲取machine time,然後再按照所在時區 // 將machine time轉成human time // ZonedDateTime比LocalDateTime的唯一區別就是攜帶了時區信息 // 但如果只是為了獲取年月日等信息,時區是沒用的 }
2. 獲取某一機器時間的年月日等信息。
static void t2() { long millis = System.currentTimeMillis(); Instant instant = Instant.ofEpochMilli(millis); LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneId.systemDefault()); System.out.println(ldt.getYear()); ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, ZoneId.systemDefault()); System.out.println(zdt.getYear()); // 機器時間要先轉成Instant實例後,才能被Java新時間API使用 }
3. 人類時間轉機器時間。
static void t3() { // 由於LocalDateTime沒有時區信息,所以它無法直接轉成機器時間 // 只能通過主動提供時區信息的方式才可以 LocalDateTime ldt = LocalDateTime.now(); long millis = ldt.toInstant(ZoneOffset.of("+08:00")).toEpochMilli(); System.out.println(millis); // 由於ZonedDateTime內已經有時區信息了,所以它可以直接轉成機器時間 ZonedDateTime zdt = ZonedDateTime.now(); millis = zdt.toInstant().toEpochMilli(); System.out.println(millis); // 還需要注意的是,代表人類時間的類並不是直接轉成的機器時間,而是通過Instant類間接完成 }
4. 解析時間字符串。
static void t4() { // 被解析的字符串不能有時區信息 LocalDateTime ldt = LocalDateTime.parse("2019-09-25T16:32:42"); System.out.println(ldt); // 被解析的字符串必須有時區信息 ZonedDateTime zdt = ZonedDateTime.parse("2019-09-25T16:32:42+08:00"); System.out.println(zdt); }
5. 時間的運算。
static void t5() { // LocalDateTime的時間加減就是純粹的加減 LocalDateTime ldt = LocalDateTime.parse("2019-03-10T01:59:59"); System.out.println(ldt.plusHours(1).getHour()); // 輸出:2 // ZonedDateTime的時間加減還會考慮時區信息 // 比如2019-03-10T02:00:00開始,美國開始施行 daylight saving time (夏令時) // 他們的本地時間會向後撥一個小時,即:凌晨2點會變成凌晨3點 // 有關 daylight saving time 更多信息,請看以下文章: // https://en.wikipedia.org/wiki/Daylight_saving_time ZonedDateTime zdt = ldt.atZone(ZoneId.of("America/New_York")); System.out.println(zdt.plusHours(1).getHour()); // 輸出:3 // 所以說,如果涉及到時間的運算,要用ZonedDateTime }
6. 獲取某一機器時間所屬那天的零點的機器時間。
static long startOfDay(long millis) { return LocalDate.ofInstant(Instant.ofEpochMilli(millis), ZoneId.systemDefault()) .atStartOfDay(ZoneId.systemDefault()) .toInstant() .toEpochMilli(); }
7. 獲取某一機器時間所屬那個星期的星期一零點的機器時間。
static long startOfWeek(long millis) { return LocalDate.ofInstant(Instant.ofEpochMilli(millis), ZoneId.systemDefault()) .atStartOfDay(ZoneId.systemDefault()) .with(DayOfWeek.MONDAY) .toInstant() .toEpochMilli(); }
8. 獲取某一機器時間所屬那個月的一號零點的機器時間。
static long startOfMonth(long millis) { return LocalDate.ofInstant(Instant.ofEpochMilli(millis), ZoneId.systemDefault()) .atStartOfDay(ZoneId.systemDefault()) .withDayOfMonth(1) .toInstant() .toEpochMilli(); }
好,例子就這麼多吧,我覺得到這裡大家都差不多懂了。
有關Java新時間API更多介紹,請參考Java官方教程:
https://docs.oracle.com/javase/tutorial/datetime/TOC.html
希望對大家有所幫助。
完。