• 浅析Java8新特性-新的日期和时间API:起初时间存在的问题(非线程安全、设计乱、时区处理麻烦)、日期时间(LocalDate/LocalTime/LocalDateTime)、时间戳(Instant)、时间差(Duration/Period)、TemporalAdjuster时间矫正器、LocalDateTime 与 Date 互转、时间先后判断/MonthDay类的使用(生日检查)


    一、Java8 之前时间存在的问题

      Java 8 (又称为 jdk1.8) 是 Java 语言开发的一个主要版本,它支持函数式编程,新的日期 API,新的Stream API 等。Java 8通过发布新的 Date-Time API (JSR 310) 来进一步加强对日期与时间的处理。在旧版的 Java 中,我们使用的是 SimpleDateFormat 对日期进行格式化,日期时间 API(Date,calendar) 存在诸多问题,其中有:

    1、非线程安全 − java.util.Date 是非线程安全的,所有的日期类都是可变的,这是Java日期类最大的问题之一。

    2、设计很差 − Java的日期/时间类的定义并不一致,在 java.util 和 java.sql 的包中都有日期类,此外用于格式化和解析的类在 java.text 包中定义。java.util.Date 同时包含日期和时间,而 java.sql.Date 仅包含日期,将其纳入 java.sql 包并不合理。另外这两个类都有相同的名字,这本身就是一个非常糟糕的设计。

    3、时区处理麻烦 − 日期类并不提供国际化,没有时区支持,因此 Java 引入了 java.util.Calendar 和 java.util.TimeZone 类,但他们同样存在上述所有的问题。

      Java 8 在 java.time 包下提供了很多新的 API。以下为两个比较重要的 API:

    (1)Local(本地) − 简化了日期时间的处理,没有时区的问题。

    (2)Zoned(时区) − 通过制定的时区处理日期时间。

    二、Java8 新特性之新的时间和日期的使用

      传统的时间 API 存在线程安全的问题,在多线程开发中必须要上锁,所以 java8 现在为我们提供了一套全新的时间日期 API。

      Java 8 的日期和时间类包含:日期( LocalDate)、时间(LocalTime)、时刻(Instant)、过程(Duration) 以及时钟(clock),这些类都包含在 java.time 包中,Java 8 新的时间 API 的使用方式,包括创建、格式化、解析、计算、修改。

    Instant:时间戳
    Duration:持续时间,时间差
    LocalDate:只包含日期,比如:2021-09-02
    LocalTime:只包含时间,比如:23:12:10
    LocalDateTime:包含日期和时间,比如:2019-02-02 23:14:21
    Period:时间段
    ZoneOffset:时区偏移量,比如:+8:00
    ZonedDateTime:带时区的时间
    Clock:时钟,比如获取目前美国纽约的时间

    1、LocalDate、LocalTime、LocalDateTime

      LocalDate、LocalTime、LocalDateTime 类的实例是不可变的对象,分别表示使用 ISO-8601 (ISO-8601 日历系统是国际化组织制定的现代化公民的日期和时间的表达法)日历系统的日期、时间、日期和时间。

      从名称也可以看出来,第一种表示日期 年月日,第二种表示时间 时分秒,第三种表示年月日时分秒。

      由于的实例是不可变的对象,所以我们如果对时间对象进行更改,包括修改时间,加减时间都需要重新返回一个新的实例。

    // 获取当前时间
    LocalDate localDate = LocalDate.now();
    // 获取指定日期时间
    LocalDateTime localDateTime = LocalDateTime.of(2020,06,02,12,22,23);
    // 当前日期+1天
    LocalDate localDate =LocalDate.now();
    LocalDate tomorrow =  localDate.plusDays(1);
    
    // 对日期时间进行加减
    /**
    * 对日期时间进行加操作,使用 localDateTime.plus***(num)
    * 对日期时间进行减操作,使用 localDateTime.minus***(num)
    * 修改不限于,年、月、日、时、分、秒、纳秒
    */
    LocalDateTime localDateTime2 = localDateTime.plusMonths(2);
    System.out.println("指定时间添加2月:"+localDateTime2);
    
    LocalDateTime localDateTime3 = localDateTime.minusDays(2);
    System.out.println("指定时间减少2天:"+localDateTime3);

      对日期时间进行加操作,使用 localDateTime.plusXXX(num)

      对日期时间进行减操作,使用 localDateTime.minusXXX(num)

      修改不限于,年、月、日、时、分、秒、纳秒

    2、Instant: 时间戳(以Unix 元年 : 1970-01-01 00:00:00 到某个时间之间的毫秒数)

    //获取当前时间戳   时间戳已UTC 时间展示,与中国时间差距8小时
    Instant instant = Instant.now();
    //如果想要获取中国时间 可以通过设置偏移量来获取 OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8));

      使用Instant获取当前时间戳默认为UTC格式时间,我们如果想要获取中国时间的话,必须给instant设置偏移量,instant.atOffset(ZoneOffset.ofHours(8));可以设置偏移量为加8小时,即为中国时间。也可设置负值,则为减8小时。

    //toEpochMilli 获取毫秒数
    long l = instant.toEpochMilli();

      获取毫秒数(时间戳):以前来获取当前时间戳是用:new Date().getTime() 以及 System.currentTimeMillis获取。现在可用使用instant.toEpochMilli()来获取,他们三个获取的时间戳是一样的。

    3、Duration、Period:计算两个日期时间的时间差

    (1)Duration获取2个时间之间的间隔(LocalDateTime、Instant)

      使用Duration.between(instant, instant1)获取两个时间时间差返回一个 Duration对象,可以通过对象内部的实例方法获取时间间隔。

    Duration between = Duration.between(instant, instant1);
    System.out.println("毫秒:"+between.toMillis());
    System.out.println("秒:"+between.getSeconds());

      Duration不仅可以获取Instant时间的间隔,获取LocalDateTime 的时间间隔也是可以的。

    LocalDateTime localDateTime = LocalDateTime.now();
    LocalDateTime localDateTime1 = LocalDateTime.of(2020,09,18,15,02,03);
    
    Duration between1 = Duration.between(localDateTime, localDateTime1);
    System.out.println("LocalDateTime间隔小时:"+between1.toHours());

    (2)Period获取两个时间之间的间隔 (LocalDate)

    Period between2 = Period.between(LocalDate.now(), LocalDate.of(2020, 07, 06));
    System.out.println("日期间隔天数:"+between2.getDays());

    4、TemporalAdjuster:时间矫正器。

      有时我们可能需要获取一个周末,或者下一个工作日等时间,这里 java8 就为我们提供了一个时间校正器,让我们对时间进行校准。

      TemporalAdjusters:该类通过静态方法提供了大量的常用的TemporalAdjuster的实现供我们使用。

      在localDateTime中,有一个with方法,其中可以让我们去写一TemporalAdjuster接口,而TemporalAdjusters类中,有许多常用的方法

    //时间校正器
        @Test
        public void testTemporalAdjuster(){
            LocalDateTime localDateTime = LocalDateTime.now();
            System.out.println("当前时间:"+localDateTime);
            LocalDateTime localDateTime1 = localDateTime.withDayOfMonth(10);
            System.out.println("手动指定日期时间:"+localDateTime1);
    
            //获取当月第一天
            LocalDateTime with = localDateTime.with(TemporalAdjusters.firstDayOfMonth());
            System.out.println("使用TemporalAdjuster获取当月第一天:"+with);
    
            System.out.println(localDateTime.with(TemporalAdjusters.firstDayOfMonth()));
             //获取下一年的第一天
            System.out.println(localDateTime.with(TemporalAdjusters.firstDayOfNextYear()));
             //获取年中第一天
            System.out.println(localDateTime.with(TemporalAdjusters.lastDayOfYear()));
             //获取月中最后一天
            System.out.println(localDateTime.with(TemporalAdjusters.lastDayOfMonth()));
             //获取下个星期一
            System.out.println(localDateTime.with(TemporalAdjusters.next(DayOfWeek.MONDAY)));
        }

      TemporalAdjusters 包含许多静态方法,可以直接调用,以下列举一些:

    方法名描述
    dayOfWeekInMonth 返回同一个月中每周的第几天
    firstDayOfMonth 返回当月的第一天
    firstDayOfNextMonth 返回下月的第一天
    firstDayOfNextYear 返回下一年的第一天
    firstDayOfYear 返回本年的第一天
    firstInMonth 返回同一个月中第一个星期几
    lastDayOfMonth 返回当月的最后一天
    lastDayOfNextMonth 返回下月的最后一天
    lastDayOfNextYear 返回下一年的最后一天
    lastDayOfYear 返回本年的最后一天
    lastInMonth 返回同一个月中最后一个星期几
    next / previous 返回后一个/前一个给定的星期几
    nextOrSame / previousOrSame 返回后一个/前一个给定的星期几,如果这个值满足条件,直接返回

    5、时间格式化工具:DateTimeFormatter

      DateTimeFormatter是专门为LocalDateTime进行格式化的工具类,内置了很多基本格式,也可自定义时间格式化公式。写法也比较特别,可以是formatter.format(dateTime),也可以是dateTime.format(formatter)

    //本身内置了很多格式化格式
    DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
    // 也可自定义格式
    DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy年MMdd hh:mm:ss");

    6、LocalDateTime 与 Date 互转

      LocalDateTime 与 Date 互转主要是利用两者共有的属性 Instant 进行相互转换。

    (1)LocalDateTime 转 Date:

      LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());

      或者 date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();

    (2)Date 转 LocalDateTime :

      Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());

    @Test
    public void LocalDateToDate(){
        Date date = new Date();
        LocalDateTime localDateTime1 = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
        LocalDateTime localDateTime2 = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
    
        LocalDateTime localDateTime = LocalDateTime.now();
        Date from = Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
        System.out.println("LocalDateTime转换成date:"+from);
        SimpleDateFormat ss = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println(ss.format(from));
    }

    7、其他一些常用的方法

    (1)比较两个时间的先后

    LocalDate date15 = LocalDate.of(2021,9,31);
    date.isAfter(date15); // false
    date.isBefore(date15); // true

    (2)MonthDay类的使用

      MonthDay只包含月日信息,可以用于存放类似于生日,结婚纪念日等信息。

      比如:生日检查或账单检查,我们在购物时注册会员时都会有生日祝福,例如,用户的生日为1996-09-10,如果今天是2021-09-10,那么今天就是用户的生日(按公历/身份证日期来算),那么通过java8新的日期库,我们该如何来进行实现呢?

    LocalDate birthday = LocalDate.of(1996, 09, 10);
    MonthDay birthdayMd = MonthDay.of(birthday.getMonth(), birthday.getDayOfMonth());
    MonthDay today = MonthDay.from(LocalDate.of(2021, 09, 10));
    System.out.println(today.equals(birthdayMd));
    // 输出结果为 :true

      这里用到了:

      Java中MonthDay类的 from() 方法从时间对象获取MonthDay的实例,

      Java中MonthDay类的of(Month month,int dayOfMonth)方法用于获取MonthDay的实例

    MonthDay monthday = MonthDay.of(9, 18);  // 09-18
    MonthDay date = MonthDay.from(ZonedDateTime.now()); // 09-18
  • 相关阅读:
    重构二叉树
    LeetCode-Construct Binary Tree from Preorder and Inorder Traversal
    二叉平衡树
    二叉树的三种递归与非递归遍历算法
    Jump Game
    Ubuntu中安装最新 Node.js 和 npm
    ORACLE查看并修改最大连接数
    设计模式之工厂模式
    设计模式之单例模式
    设计模式之模板方法模式
  • 原文地址:https://www.cnblogs.com/goloving/p/15309272.html
Copyright © 2020-2023  润新知