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

希望對大家有所幫助。

完。