java8新特性之新的时间和日期

本文深入探讨Java8中引入的新时间日期API,包括LocalDate、LocalTime、LocalDateTime、Instant、Duration、Period等类的使用方法,以及时间格式化、时间校正器和与Date类型转换的技巧。

我们一直以来在写代码使用的时间无外乎两种,Date和Calender。
但是传统的时间 API 存在线程安全的问题,在多线程开发中必须要上锁,所以 java8 现在为我们提供了一套全新的时间日期 API ,今天进来学习一下java8 的时间日期 API。

一、LocalDate、LocalTime、LocalDateTime

LocalDate、LocalTime、LocalDateTime类的实例是不可变的对象,分别表示使用 ISO-8601 (ISO-8601 日历系统是国际化组织制定的现代化公民的日期和时间的表达法)日历系统的日期、时间、日期和时间。从名称也可以看出来,第一种表示日期 年月日,第二种表示时间 时分秒,第三种表示年月日时分秒
由于的实例是不可变的对象,所以我们如果对时间对象进行更改,包括修改时间,加减时间都需要重新返回一个新的实例。

 /**
     * 测试 LocalDate,LocalTime,LocalDateTime
     */
    @Test
    public void testLocalDate(){
        //获取当前日期
        LocalDate localDate = LocalDate.now();
        //获取当前日期
        LocalTime localTime = LocalTime.now();
        //获取当前日期时间
        LocalDateTime localDateTime = LocalDateTime.now();

        System.out.println("localDate:"+localDate+"  localTime:"+localTime+" localDateTime:"+localDateTime);

    }
localDate:2020-07-01  localTime:21:24:19.925 localDateTime:2020-07-01T21:24:19.925

一般来说我们用的最多的就是LocalDateTime:

1.获取指定日期

使用LocalDateTime.of()可以获取指定时间:
在这里插入图片描述
我们可以看到LocalDateTime内置了很多静态方法,可以用于获取指定时间。

//获取指定时间
    @Test
    public void testLocalDateTime(){
        LocalDateTime localDateTime = LocalDateTime.of(2020,06,02,12,22,23);
        System.out.println("指定时间:"+localDateTime);
    }
指定时间:2020-06-02T12:22:23
2.对日期时间进行加减
//获取指定时间
    @Test
    public void testLocalDateTime(){
        LocalDateTime localDateTime = LocalDateTime.of(2020,06,02,12,22,23);
        System.out.println("指定时间:"+localDateTime);
        //对时间进行加减
        LocalDateTime localDateTime1 = localDateTime.plusYears(2);
        System.out.println("指定时间添加2年:"+localDateTime1);

        /**
         * 对日期时间进行加操作,使用 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);

    }
指定时间:2020-06-02T12:22:23
指定时间添加2年:2022-06-02T12:22:23
指定时间添加2月:2020-08-02T12:22:23
指定时间减少2天:2020-05-31T12:22:23

对日期时间进行加操作,使用 localDateTime.plusXXX(num)
对日期时间进行减操作,使用 localDateTime.minusXXX(num)
修改不限于,年、月、日、时、分、秒、纳秒

在这里插入图片描述
通过LocalDateTime对象,可分别获取相应的年、月、日、时、分、秒、纳秒等。

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

1.获取当前时间
/**
     * 获取时间戳(UTC)时间
     */
    @Test
    public void testInstant(){
        //获取当前时间戳   时间戳已UTC 时间展示,与中国时间差距8小时
        Instant instant = Instant.now();
        System.out.println("UTC instant:"+instant);
        //如果想要获取中国时间  可以通过设置偏移量来获取
        OffsetDateTime offsetDateTime = instant.atOffset(ZoneOffset.ofHours(8));
        System.out.println("中国时间 offsetDateTime:"+offsetDateTime);
    }
UTC instant:2020-07-01T13:52:58.106Z
中国时间 offsetDateTime:2020-07-01T05:52:58.106+08:00

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

2.获取毫秒数(时间戳)

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

//toEpochMilli 获取毫秒数
long l = instant.toEpochMilli();
System.out.println("使用instant获取当前时间戳:"+l);
System.out.println("使用new Date()获取当前时间戳"+new Date().getTime());
System.out.println("使用System.currentTimeMillis获取当前时间戳:"+System.currentTimeMillis());
使用instant获取当前时间戳:1593612101298
使用new Date()获取当前时间戳1593612101373
使用System.currentTimeMillis获取当前时间戳:1593612101373

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

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

使用Duration.between(instant, instant1)获取两个时间时间差返回一个 Duration对象,可以通过对象内部的实例方法获取时间间隔。
要注意的是:这里获取秒与纳秒的方式有点特别:
在这里插入图片描述
在这里插入图片描述
可以看到获取毫秒间隔包括天数、小时、分钟与获取秒的方法前缀是不一样的。一个是toXXX()
一个是getXXX();

//使用Duration 获取两个时间时间差
    @Test
    public void testDuration() throws InterruptedException {
        Instant instant = Instant.now();

        Thread.sleep(4899);

        Instant instant1 = Instant.now();

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

    }
毫秒:4899:4

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

LocalDateTime localDateTime = LocalDateTime.now();

LocalDateTime localDateTime1 = LocalDateTime.of(2020,07,01,01,02,03);

 Duration between1 = Duration.between(localDateTime, localDateTime1);

 System.out.println("LocalDateTime间隔小时:"+between1.toHours());
LocalDateTime间隔小时:-21
2.Period获取两个时间之间的间隔 (LocalDate)
 Period between2 = Period.between(LocalDate.now(), LocalDate.of(2020, 07, 06));
 System.out.println("日期间隔天数:"+between2.getDays());
日期间隔天数:5

四、时间校正器

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)));
    }

我们可以使用withXXX()来获取指定的nian、月、日、时、分、秒等。
在这里插入图片描述
但是如果上述方法已经不能够满足我们的需求,我们需要获取下一年,下一月等日期时可以使用TemporalAdjusters时间校正器来针对获取,里面提供了大量实例。

//自定时时间:下一个工作日,因为这里需要一个接口,所以完全可以自定义方法
        LocalDateTime with1 = localDateTime.with((e) -> {
            LocalDateTime now = (LocalDateTime) e;
            DayOfWeek dow = now.getDayOfWeek();
            if (dow.equals(DayOfWeek.FRIDAY)) {
                return now.plusDays(3);
            } else if (dow.equals(DayOfWeek.SATURDAY)) {
                return now.plusDays(2);
            }
            return now.plusDays(1);
        });
        System.out.println("下一个工作日是:"+with1);

也可以自定义日期的实现方法逻辑,获取自己想要的日期,比如上面的下一个工作日。

五、时间格式化工具 DateTimeFormatter

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

@Test
    public void formatDateTest(){
        //本身内置了很多格式化格式
        DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
        // 也可自定义格式
        DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy年MMdd hh:mm:ss");
        //当前时间
        LocalDateTime dateTime = LocalDateTime.now();

        /**
         * 两种写法效果一样
         */
        System.out.println("格式化日期一:"+formatter.format(dateTime));
        System.out.println("格式化日期二:"+dateTime.format(formatter));

        System.out.println("自定义格式化日期一:"+formatter1.format(dateTime));
        System.out.println("自定义格式化日期二:"+dateTime.format(formatter1));

        //字符串转换时间
        String format = dateTime.format(formatter1);
        LocalDateTime parse = LocalDateTime.parse(format, formatter1);
        System.out.println("自定义格式化日期三:"+parse);
    }
格式化日期一:2020-07-04T11:48:26.297
格式化日期二:2020-07-04T11:48:26.297
自定义格式化日期一:2020070411:48:26
自定义格式化日期二:2020070411:48:26
自定义格式化日期三:2020-07-04T11:48:26

这里需要注意一点,在吧时间转换成字符串时,必须使用与时间格式相同的formatter,否则会报错。
自定义时间格式化类型的 时:HH必须是大写,否则转换成时间也会报错。
DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern(“yyyy年MM月dd日 HH:mm:ss”);

六、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();
        System.out.println("date转换成LocalDateTime一:"+localDateTime1);
        LocalDateTime localDateTime2 = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
        System.out.println("date转换成LocalDateTime二:"+localDateTime2);

        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));
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值