Java8爲何須要引入新的日期和時間庫

image.png


Java8爲何須要引入新的日期和時間庫

  1. Date日期輸出可讀性較差
    Date date = new Date();
    System.out.println(date);

    打印輸出的結果:java

    Sat Nov 14 11:03:41 CST 2020
  2. Date日期的解析、格式化經過JDK自帶的api實現較爲麻煩,一般會使用第三方的日期時間庫,好比:joda-time, commons-lang

Java8中提供了哪些日期和時間類

在java.time包中提供了不少新的類,一般主要使用到的是LocalDate, LocalTime, LocalDateTime, ZoneId, ZoneDateTime; 關係圖以下:
image.pngapi

  • LocaDate這個類自己不包含時間和時區信息,只包含了日期信息;提供了不少方法來獲取經常使用的值:星期幾,幾月 ...ide

    經常使用的靜態構造LocaDate方法lua

    LocalDate.of(2020, 11, 14); //指定年月日
    LocalDate.of(2020, Month.NOVEMBER, 14); //指定年月日 使用Month枚舉類
    LocalDate.ofYearDay(2020, 10); //2020年第10天 => 2020-01-10
    LocalDate.now(); //當前時間
    System.out.println(LocalDate.now()); // 比較好的可讀性輸出 => 2020-11-14

    LocaDate經常使用實例方法code

    LocalDate now = LocalDate.of(2020, 11, 14);
    System.out.println(now.getMonth()); //月份的枚舉 => NOVEMBER
    System.out.println(now.getMonthValue()); //月份的數字 => 11
    System.out.println(now.getDayOfMonth()); //幾號 => 14
    System.out.println(now.getDayOfYear()); // 一年中的第幾天 => 319
    System.out.println(now.getDayOfWeek()); // 周幾枚舉 => SATURDAY
    System.out.println(now.lengthOfMonth()); //本月多少天 => 30
    System.out.println(now.lengthOfYear()); //本年多少天 => 366
  • LocalTime只包含時間信息
    LocalTime.of(12, 9, 10); //時、分、秒
    LocalTime.now();
    LocalTime time = LocalTime.of(12, 9, 10);
    System.out.println(time.getHour());
    System.out.println(time.getMinute());
    System.out.println(time.getSecond());
  • LocalDateTime 從這個類的名字能夠看出是合併了LocalDate, LocalTime,只包含日期和時間,不包含時區信息
    構造的方式,能夠直接使用靜態方法建立,也能夠經過LocalDateLocalTime合併orm

    LocalDateTime.of(LocalDate.now(), LocalTime.now());
    LocalDateTime.of(2020, 11, 14, 13, 10, 50);
    LocalDate.now().atTime(LocalTime.now());
    LocalTime.now().atDate(LocalDate.now());
    LocalDateTime.now();

    因爲LocalDateTimeLocalDate, LocalTime的合併,因此LocalDate, LocalTime有的實例方法,基本在LocalDateTime中均可以找到blog

  • ZoneId 用來替代老版本TimeZone, 每一個ZoneId都有一個特定的地區標識;字符串

    ZoneId.of("Asia/Shanghai");
      ZoneId.systemDefault()

    查看全部的地區標識能夠進入到ZoneId源碼get

  • ZoneDateTime帶有日期、時間、時區信息,是LocalDateTimeZoneId的組合
    ZonedDateTime zonedDateTime = ZonedDateTime.of(LocalDateTime.now(), ZoneId.systemDefault());
    ZonedDateTime.of(LocalDate.now(),LocalTime.now(),ZoneId.of("Asia/Shanghai"));

常常咱們會遇到須要求兩個時間之間相差的時間, 如何實現呢?
Java8也提供給了相應的API支持, DurationPeriod源碼

Duration between = Duration.between(LocalTime.of(13, 0), LocalTime.of(14, 0)); 
between.getSeconds(); //返回兩個時間相差的秒數 => 3600

Duration是經過秒和毫秒來記錄時間的長短,因此只能處理兩個LocalTime, DateLocalTime, ZonedDateTime; 若是傳入的是LocalDate,將會拋出異常

java.time.temporal.UnsupportedTemporalTypeException: Unsupported unit: Seconds

    at java.time.LocalDate.until(LocalDate.java:1614)
    at java.time.Duration.between(Duration.java:475)
    at com.haixue.crm.stock.service.LocalTest.testDate(LocalTest.java:121)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4Cla***unner.runChild(BlockJUnit4Cla***unner.java:78)
    at org.junit.runners.BlockJUnit4Cla***unner.runChild(BlockJUnit4Cla***unner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)

在這種狀況下就可使用Period

Period between1 = Period.between(LocalDate.of(2020, 11, 13), LocalDate.of(2020, 11, 13));
between1.getDays();  //返回相差的天數 => 1

時間日期的更高級的操做

  • 覺得對時間日期的修改增長減小都是經過第三方依賴包操做,如今原生API已經支持
LocalDate now2 = LocalDate.of(2020, 11, 13);
System.out.println(now2.plusDays(2));       //加2天   => 2020-11-15
System.out.println(now2.plusMonths(1));     //加1月   => 2020-12-13
System.out.println(now2.plusWeeks(1));      //加一週   => 2020-11-20
System.out.println(now2.minusDays(1));      //減一天   => 2020-11-12
System.out.println(now2.minusMonths(1));    //減一月   => 2020-10-13
System.out.println(now2.minusYears(1));     //減一年   => 2019-11-13
System.out.println(now2.withYear(2021));    //修改年   => 2021-11-13
  • 有時候咱們會遇到須要取本月的最後一天、本月的第一天、調整日期到下一個週日... ;這些需求也可以經過使用TemporalAdjuster很好的實現,TemporalAdjuster 可以實現不少定製化的日期操做,Java8在TemporalAdjusters已經給提供了默認的不少實現。

    LocalDate now3 = LocalDate.of(2020, 11, 13);
    System.out.println(now3.with(TemporalAdjusters.firstDayOfYear())); // 本年的第一天 => 2020-01-01
    System.out.println(now3.with(TemporalAdjusters.next(DayOfWeek.MONDAY))); //下一個週一 => 2020-11-16
    System.out.println(now3.with(TemporalAdjusters.lastDayOfMonth())); // 本月的最後一天 => 2020-11-30
    System.out.println(now3.with(TemporalAdjusters.lastDayOfYear())); // 本年的最後一天 => 2020-12-31
  • 自定義TemporalAdjuster實現獲取當天的開始時間和當天的最後時間
LocalDateTime localDateTime = LocalDateTime.of(2020, 11, 13, 10, 10, 10);
System.out.println(localDateTime);
System.out.println(localDateTime.with((temporal) -> 
    temporal.with(ChronoField.SECOND_OF_DAY, 0))); // 當天的凌晨 => 2020-11-13T00:00
System.out.println(localDateTime.with((temporal) ->
    temporal.with(ChronoField.SECOND_OF_DAY, temporal.range(ChronoField.SECOND_OF_DAY).getMaximum()))); // 當天的最後一刻時間 => 2020-11-13T23:59:59

解析、格式化

對日期的字符串解析和格式化的操做是經常使用的,首先看下不用第三方包如何簡單的實現日期解析

System.out.println(LocalDateTime.parse("2020-11-14T20:50:00")); // 輸出:2020-11-14T20:50
System.out.println(LocalDateTime.parse("2020/11/14 20:50:00",
        DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"))); // 輸出:2020-11-14T20:50

實現格式化一樣也簡單

LocalDate now4 = LocalDate.of(2020, 11, 13);
System.out.println(now4.format(DateTimeFormatter.ofPattern("yyyy/MM/dd"))); //輸出:2020/11/13

LocalDateTime localDateTime2 = LocalDateTime.of(2020, 11, 13, 10, 10, 10);
System.out.println(localDateTime2.format(DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"))); //輸出:2020/11/13 10:10:10

最後一句

本人菜鳥,若是有任何寫的不對的地方,歡迎在評論區指出

原創不易 轉載請註明出處:https://silently9527.cn/archives/30

相關文章
相關標籤/搜索