Java新的時間API究竟怎麼用

在閱讀本文之前,請先看上一篇文章 有關機器時間、UTC時間、本地時間的總結

Java新時間API中有三個特別重要的類,分別是Instant、LocalDateTime、ZonedDateTime,它們分別對應到上一篇文章中講到的時間概念爲:機器時間、無時區的本地時間、有時區的本地時間。

機器時間其實可以理解爲UTC時間的另一種表現形式,其可以唯一確定時間線上的某一時刻。

無時區的本地時間因爲沒有時區信息,所以其無法唯一確定時間線上的某一時刻。

有時區的本地時間其實是在UTC時間的基礎上加一些時間偏移,所以也是可以唯一確定時間線上的某一時刻。

Java的新時間API其實都是圍繞這三個類來實現的,所以,徹底理解這三個類的目的及使用場景對於靈活使用Java新時間API來說非常重要。

下面我們用示例來講解下Java的新時間API究竟怎麼用。

  • 獲取當前時間的年月日等信息。
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的唯一區別就是攜帶了時區信息
  // 但如果只是爲了獲取年月日等信息,時區是沒用的
}
  • 獲取某一機器時間的年月日等信息。
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使用
}
  • 人類時間轉機器時間。
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類間接完成
}
  • 解析時間字符串。
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);
}
  • 時間的運算。
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
}
  • 獲取某一機器時間所屬那天的零點的機器時間。
static long startOfDay(long millis) {
  return LocalDate.ofInstant(Instant.ofEpochMilli(millis), ZoneId.systemDefault())
      .atStartOfDay(ZoneId.systemDefault())
      .toInstant()
      .toEpochMilli();
}
  • 獲取某一機器時間所屬那個星期的星期一零點的機器時間。
static long startOfWeek(long millis) {
  return LocalDate.ofInstant(Instant.ofEpochMilli(millis), ZoneId.systemDefault())
      .atStartOfDay(ZoneId.systemDefault())
      .with(DayOfWeek.MONDAY)
      .toInstant()
      .toEpochMilli();
}
  • 獲取某一機器時間所屬那個月的一號零點的機器時間。
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/javas...

希望對大家有所幫助。

完。

更多原創文章,請關注我微信公衆號:

底層技術研究

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章