乐趣区

关于java:Java8为什么需要引入新的日期和时间库

Java8 为什么须要引入新的日期和工夫库

  1. Date 日期输入可读性较差

    Date date = new Date();
    System.out.println(date);

    打印输出的后果:

    Sat Nov 14 11:03:41 CST 2020
  2. Date 日期的解析、格式化通过 JDK 自带的 api 实现较为麻烦,通常会应用第三方的日期工夫库,比方:joda-time, commons-lang

Java8 中提供了哪些日期和工夫类

在 java.time 包中提供了很多新的类,通常次要应用到的是LocalDate, LocalTime, LocalDateTime, ZoneId, ZoneDateTime; 关系图如下:

  • LocaDate 这个类自身不蕴含工夫和时区信息,只蕴含了日期信息;提供了很多办法来获取罕用的值:星期几,几月 …

    罕用的动态结构 LocaDate 办法

    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罕用实例办法

    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 合并

    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 中都能够找到

  • ZoneId 用来代替老版本 TimeZone, 每个ZoneId 都有一个特定的地区标识;

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

    查看所有的地区标识能够进入到 ZoneId 源码

  • 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.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.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

最初一句

自己菜鸟,如果有任何写的不对的中央,欢送在评论区指出

退出移动版