Java 8 日期和时间

Java 8 日期和时间

为什么Java8提供了新的日期与时间的API?

官方是这么解释的:

Why do we need a new date and time library?

A long-standing bugbear of Java developers has been the inadequate support for the date and time use cases of ordinary developers.

For example, the existing classes (such as java.util.Date and SimpleDateFormatter) aren’t thread-safe, leading to potential concurrency issues for users—not something the average developer would expect to deal with when writing date-handling code.

Some of the date and time classes also exhibit quite poor API design. For example, years in java.util.Date start at 1900, months start at 1, and days start at 0—not very intuitive.

These issues, and several others, have led to the popularity of third-party date and time libraries, such as Joda-Time.

In order to address these problems and provide better support in the JDK core, a new date and time API, which is free of these problems, has been designed for Java SE 8.

The project has been led jointly by the author of Joda-Time (Stephen Colebourne) and Oracle, under JSR 310, and will appear in the new Java SE 8 package java.time.

参考链接:官方文档

总的来说就是以前写的Date API不好用,而且存在一些线程安全问题,给开发人员造成很多的烦恼,以至于开发人员需要使用其他优秀第三方的日期API,比如Joda-Time。Oracle可能实在忍不了,所以根据Joda-Time API中的一些优秀设计,设计了Java8的Date和Time,放在了新的包下java.time

在这里插入图片描述

简单概述

  • java.time包中,Instant类表示时间线上的一个点,通常用于对时间进行操作。 LocalDate类为没有时间和时区部分的日期,例如:2021-02-24
    如果你需要日期和时间,就选择LocalDateTime,例如:2021-02-24T13:49:10.758276300
    如果你需要一段时间但不关心日期,那么可以使用LocalTime,例如:13:50:26.058539700
    如果时区很重要,日期和时间API提供ZonedDateTime类。 顾名思义,这个类表示带有时区日期时间。

  • 然后有两个类来测量时间总计,即Duration类和Period类。 这两个类是相似的,除了Duration是基于时间,但而Period是基于日期的。 Duration提供了纳秒精度的时间量。 例如,可以模拟飞行时间,因为它通常以小时数和分钟数表示。 另一方面,如果只关心天数,月数或年数,例如计算一个人的年龄,则Period更为适用。

  • java.time包也带有两个枚举DayOfWeekMonthDayOfWeek表示从一周的一天,从周一开始到周日。 Month枚举代表这一年的十二个月,从1月到12月。

  • 处理日期和时间通常涉及解析和格式。 日期和时间API通过在所有主要类中提供parseformat方法来解决这两个问题。 另外,java.time.format包含一个用于格式化日期和时间的DateTimeFormatter类。

参考:Java 8 Date-Time API 详解

Instant类

Instant 没有时区信息(也可以认为是0时区,即GMT时区),Instant实例表示时间线上的一个点。 参考点是标准的Java纪元(epoch),即1970-01-01T00:00:00Z1970年1月1日00:00 GMT)。

Instant的静态now方法返回一个表示当前时间的Instant对象。
getEpochSecond方法返回自纪元以来经过的秒数。 getNano方法返回自上一秒开始以来的纳秒数。

Instant类的一个常用用途是用来操作时间。

    @Test
    void testTime1() throws InterruptedException {
        Instant start = Instant.now();
        // do something here
        TimeUnit.MILLISECONDS.sleep(100);
        Instant end = Instant.now();
        System.out.println(Duration.between(start, end).toMillis());
    }

如上面代码所示,Duration类用于返回两个Instant之间时间数量的差异。

Instant与Date的转换

Instant相当于Date

     @Test
    void testTime2() {
        //instant 相当于 date
        Instant instant = Instant.now();
        System.out.println(instant); //2021-02-24T06:53:58.933542200Z

        Date date = new Date();
        System.out.println(date); //Wed Feb 24 14:53:58 CST 2021

        //instant转date 类方法(java.util.date)
        Date from = Date.from(instant);
        System.out.println(from); // Wed Feb 24 14:53:58 CST 2021

        //date 转instant 对象方法(java.util.date)
        Instant instant1 = date.toInstant();
        System.out.println(instant1); //2021-02-24T06:53:58.944Z

        //instant 根据毫秒值或者date转换为instant 类方法 (java.time)
        Instant instant2 = Instant.ofEpochMilli(date.getTime());
        System.out.println(instant2); //2021-02-24T06:53:58.944Z
    }
将字符串类型的Instant转换为Instantd对象

注意:必须传入的是符合 UTC格式的字符串

    @Test
    void testTime3() {
        Instant parse = Instant.parse("2021-02-24T08:59:10.142029600Z");
        System.out.println(parse);//2021-02-24T08:59:10.142029600Z
    }
Instant的加減操作
    @Test
    void testTime4() {
        //instant 在现有的instant的时间上追加些时间,下面例子追加了5小时10分钟,这里plus会产生新的instant对象
        Instant instant = Instant.now();
        Instant plus = instant.plus(Duration.ofHours(5).plusMinutes(10));
        System.out.println("instant:" + instant + ", plus:" + plus);//instant:2021-02-26T05:30:55.385967500Z, plus:2021-02-26T10:40:55.385967500Z
        System.out.println(instant == plus);//plus会产生新的instant对象 所以结果位false

        //instant 获取其5天前的instant(此刻)
        Instant minus = instant.minus(5, ChronoUnit.HOURS);
        System.out.println("instant:" + instant + ", minus:" + minus);//instant:2021-02-26T05:30:55.385967500Z, minus:2021-02-26T00:30:55.385967500Z
        //也可以直接调用相关减法方法,效果跟上面的方法一样
        Instant minus1 = instant.minusSeconds(60 * 60 * 5);
        System.out.println("instant:" + instant + ", minus1:" + minus1);//instant:2021-02-26T05:30:55.385967500Z, minus1:2021-02-26T00:30:55.385967500Z
        //减法方法,效果跟上面的方法一样
        Instant minus2 = instant.minus(Duration.ofHours(5));
        System.out.println("instant:" + instant + ", minus2:" + minus2);//instant:2021-02-26T05:30:55.385967500Z, minus2:2021-02-26T00:30:55.385967500Z
    }
Instant时间差计算
    @Test
    void testTime5() throws InterruptedException {
        //计算两个Instant之间的秒数, ChronoUnit用的什么,得到的结果就是什么单位
        Instant instant = Instant.now();
        TimeUnit.SECONDS.sleep(2);
        Instant instant2 = Instant.now();
        long between = ChronoUnit.SECONDS.between(instant, instant2);
        
        long between2 = Duration.between(instant, instant2).toSeconds();
        System.out.println(between);//2
        System.out.println(between2);//2
    }
Instant时间大小比较
    @Test
    void testTime6() throws InterruptedException {
        Instant instant = Instant.now();
        TimeUnit.SECONDS.sleep(2);
        Instant instant2 = Instant.now();
        //比较两个instant 相等 0, 前者时间纳秒值大于后者 1,小于后者 -1或小于0
        int i = instant.compareTo(instant2);
        System.out.println(i);//-1
        //判断instant时间前后,前者在后者之后返回true,反之false
        boolean after = instant.isAfter(instant2);
        System.out.println(after);//false
        //判断instant时间前后,前者在后者之前返回true,反之false,正好与上面相反
        boolean before = instant.isBefore(instant2);
        System.out.println(before);//true
    }
Instant详解

通过Instant.now()获得的时间戳与北京时间相差八个小时,这是因为Instant.now()使用的是UTC时间,如果要转化为北京时间需要加上八个小时

/**
     * Obtains the current instant from the system clock.
     * <p>
     * This will query the {@link Clock#systemUTC() system UTC clock} to
     * obtain the current instant.
     * <p>
     * Using this method will prevent the ability to use an alternate time-source for
     * testing because the clock is effectively hard-coded.
     *
     * @return the current instant using the system clock, not null
     */
    public static Instant now() {
        return Clock.systemUTC().instant();
    }

而。LocalDateLocalDateTimenow()方法使用的是系统默认时区 不存在Instant.now()的时间问题。

Instant.now()转化为北京时间
    @Test
    void testTime7() {
        Instant now = Instant.now().plusMillis(TimeUnit.HOURS.toMillis(8));
        System.out.println("now:"+now);//now:2021-02-26T13:51:40.324904700Z
    }

LocalDate类

方法描述
now静态方法,返回今天的日期
of从指定年份,月份和日期创建LocalDate的静态方法
getDayOfMonth, getMonthValue, getYear以int形式返回此LocalDate的日,月或年
getMonth以Month枚举常量返回此LocalDate的月份
plusDays, minusDays给LocalDate添加或减去指定的天数
plusWeeks, minusWeeks给LocalDate添加或减去指定的星期数
plusMonths, minusMonths给LocalDate添加或减去指定的月份数
plusYears, minusYears给LocalDate添加或减去指定的年数
isLeapYear检查LocalDate指定的年份是否为闰年
isAfter, isBefore检查此LocalDate是在给定日期之后还是之前
lengthOfMonth返回此LocalDate中月份的天数
withDayOfMonth返回此LocalDate的拷贝,将月份中的某天设置为给定值
withMonth返回此LocalDate的拷贝,其月份设置为给定值
withYear返回此LocalDate的拷贝,并将年份设置为给定值
创建LocalDate的方式

LocalDate提供了许多创建日期的方法。

    @Test
    void testLocalDate1() {
        LocalDate localDate = LocalDate.now();
        System.out.println(localDate);//2021-02-26

        LocalDate date = LocalDate.of(2018, 3, 7);
        System.out.println(date);//2018-03-07

        LocalDate date2 = LocalDate.of(2018, Month.MARCH, 7);
        System.out.println(date2);//2018-03-07
    }
LocalDate获取日,月,年
    @Test
    void testLocalDate2() {
        //LocalDate的日,月或年的方法,例如getDayOfMonth,getMonth,getMonthValue和getYear。他们都没有任何参数,并返回一个int或Month的枚举常量。
        LocalDate localDate = LocalDate.now();
        System.out.println(localDate.getDayOfYear());//61
        System.out.println(localDate.getDayOfMonth());//2
        Month month = localDate.getMonth(); //Month的枚举常量。
        System.out.println(month);//MARCH
        System.out.println(localDate.getYear());//2021
        System.out.println(localDate.getMonthValue());//2

        //get方法,接受一个TemporalField并返回这个LocalDate的一部分。 例如,传递ChronoField.YEAR以获取LocalDate的年份部分。
        //ChronoField是一个实现TemporalField接口的枚举
        int year = localDate.get(ChronoField.YEAR);
        System.out.println(year);//2021
    }
LocalDate的加减操作
    @Test
    void testLocalDate3() {
        LocalDate now = LocalDate.now();
        System.out.println(now);//2021-03-02
        LocalDate plusDays = now.plusDays(1);
        System.out.println(plusDays); //2021-03-03
        LocalDate minusDays = now.minusDays(1);
        System.out.println(minusDays);//2021-03-01
        LocalDate pastDate = now.minus(2, ChronoUnit.DECADES);
        System.out.println(pastDate);//2001-03-02
        LocalDate plus = now.plus(2, ChronoUnit.DAYS);
        System.out.println(plus);//2021-03-04
        //注意:LocalDate是不可变的,因此无法更改。 任何返回LocalDate的方法都返回LocalDate的新实例。
    }
LocalDate 与 Date的转换
    @Test
    void testLocalDate4() {
        Date date = new Date();
        Instant instant = date.toInstant();
        ZoneId zoneId = ZoneId.systemDefault();
        System.out.println(zoneId);//Asia/Shanghai
        
        LocalDate localDate = LocalDate.ofInstant(instant, zoneId);
        System.out.println(localDate); //2021-03-03
        
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zoneId);
        LocalDate localDate2 = localDateTime.toLocalDate();
        System.out.println(localDate2);//2021-03-03
    }
    @Test
    void testLocalDate5() {
        // LocalDate 转 Date
        LocalDate localDate = LocalDate.now();
        ZoneId zone = ZoneId.systemDefault();
        Instant instant = localDate.atStartOfDay().atZone(zone).toInstant();
        Date date = Date.from(instant);
        System.out.println(date);//Wed Mar 03 00:00:00 CST 2021
    }
LocalDate 与 Instant的转换
    @Test
    void testLocalDate6() {
        //Instant 转 LocalDate
        ZoneId zoneId = ZoneId.systemDefault();
        System.out.println(zoneId);//Asia/Shanghai
        Instant now = Instant.now();
        System.out.println(now);//2021-03-03T12:31:29.568519200Z
        LocalDate localDate = LocalDate.ofInstant(now, zoneId);
        System.out.println(localDate);//2021-03-03
    }
   @Test
    void testLocalDate7() {
        //LocalDate 转 Instant
        ZoneId zone = ZoneId.systemDefault();
        LocalDate now = LocalDate.now();
        System.out.println(now);//2021-03-03
        Instant instant = LocalDate.now().atStartOfDay().atZone(zone).toInstant();
        System.out.println(instant);//2021-03-02T16:00:00Z
    }
LocalDate 详解

当我们调用LocalDate.now()的时候我们会返回系统当前时区的一个日期, 从源码中就可以看出来

//-----------------------------------------------------------------------
    /**
     * Obtains the current date from the system clock in the default time-zone.
     * <p>
     * This will query the {@link Clock#systemDefaultZone() system clock} in the default
     * time-zone to obtain the current date.
     * <p>
     * Using this method will prevent the ability to use an alternate clock for testing
     * because the clock is hard-coded.
     *
     * @return the current date using the system clock and default time-zone, not null
     */
    public static LocalDate now() {
        return now(Clock.systemDefaultZone());
    }

LocalTime类

创建LocalTime的方式
     @Test
    void testLocalTime1() {
        LocalTime localTime = LocalTime.now();
        System.out.println(localTime);

        LocalTime time = LocalTime.of(1, 30, 20);
        System.out.println(time);//01:30:20
    }
LocalTime 获取时,分,秒
    @Test
    void testLocalTime2() {
        LocalTime localTime = LocalTime.now();
        System.out.println(localTime);//21:18:19.843617500
        int hour = localTime.getHour();
        int minute = localTime.getMinute();
        int second = localTime.getSecond();
        System.out.println(hour);//21
        System.out.println(minute);//18
        System.out.println(second);//19

    }
LocalTime的加减操作
    @Test
    void testLocalTime3() {
        LocalTime localTime = LocalTime.now();
        System.out.println(localTime);//21:26:15.524736600
        System.out.println(localTime.plus(1, ChronoUnit.HOURS));//22:26:15.524736600
        System.out.println(localTime.plusHours(1));//22:26:15.524736600
        System.out.println(localTime.plusMinutes(2));//21:28:15.524736600
        System.out.println(localTime.minus(1,ChronoUnit.HOURS));//20:26:15.524736600
        System.out.println(localTime.minusSeconds(1));//21:26:14.524736600
    }
LocalTime 与 Date的转换
    @Test
    void testLocalTime4(){
        //Date 转 LocalTime
        Date date = new Date();
        System.out.println(date);//Thu Mar 04 19:53:57 CST 2021
        Instant instant = date.toInstant();
        ZoneId zone = ZoneId.systemDefault();
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
        LocalTime localTime = localDateTime.toLocalTime();
        System.out.println(localTime);//19:53:57.089
    }
    @Test
    void testLocalTime5() {
        //LocalTime 转 Date
        LocalTime localTime = LocalTime.now();
        LocalDate localDate = LocalDate.now();
        LocalDateTime localDateTime = LocalDateTime.of(localDate, localTime);
        System.out.println(localTime);//19:55:14.254197800
        ZoneId zone = ZoneId.systemDefault();
        Instant instant = localDateTime.atZone(zone).toInstant();
        java.util.Date date = Date.from(instant);
        System.out.println(date);//Thu Mar 04 19:55:14 CST 2021
    }
LocalTime 与 Instant的转换
    @Test
    void testLocalTime6() {
        //Instant 转 LocalTime
        Instant instant = Instant.now();
        System.out.println(instant);//2021-03-04T12:30:28.125689400Z
        ZoneId zone = ZoneId.systemDefault();
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
        LocalTime localTime = localDateTime.toLocalTime();
        System.out.println(localTime);//20:30:28.125689400
    }

    @Test
    void testLocalTime7() {
        //LocalTime 转 Instant
        LocalTime localTime = LocalTime.now();
        LocalDate localDate = LocalDate.now();
        LocalDateTime localDateTime = LocalDateTime.of(localDate, localTime);
        System.out.println(localTime);//19:55:14.254197800
        ZoneId zone = ZoneId.systemDefault();
        Instant instant = localDateTime.atZone(zone).toInstant();
        System.out.println(instant);//2021-03-04T12:30:48.286638100Z
    }
LocalTime 详解

当我们调用LocalTime.now()的时候我们会返回系统当前时区的一个时间, 从源码中就可以看出来

  //-----------------------------------------------------------------------
    /**
     * Obtains the current time from the system clock in the default time-zone.
     * <p>
     * This will query the {@link Clock#systemDefaultZone() system clock} in the default
     * time-zone to obtain the current time.
     * <p>
     * Using this method will prevent the ability to use an alternate clock for testing
     * because the clock is hard-coded.
     *
     * @return the current time using the system clock and default time-zone, not null
     */
    public static LocalTime now() {
        return now(Clock.systemDefaultZone());
    }

LocalDateTime类

LocalDateTime类是一个没有时区的日期时间的构建。 下表显示了LocalDateTime中一些重要的方法。 这些方法类似于LocalDate的方法,以及用于修改时间部分的一些其他方法,例如在LocalDate中不可用的plusHoursplusMinutesplusSeconds

方法描述
now返回当前日期和时间的静态方法。
of从指定年份,月份,日期,小时,分钟,秒和毫秒创建LocalDateTime的静态方法。
getYear, getMonthValue, getDayOfMonth, getHour, getMinute, getSecond以int形式返回此LocalDateTime的年,月,日,小时,分钟或秒部分。
plusDays, minusDays给当前LocalDateTime添加或减去指定的天数。
plusWeeks, minusWeeks给当前LocalDateTime添加或减去指定的周数。
plusMonths, minusMonths给当前LocalDateTime添加或减去指定的月数。
plusYears, minusYears给当前LocalDateTime添加或减去指定的年数。
plusHours, minusHours给当前LocalDateTime添加或减去指定的小时数
plusMinutes, minusMinutes给当前LocalDateTime添加或减去指定的分钟数
plusSeconds, minusSeconds给当前LocalDateTime添加或减去指定的秒数
IsAfter, isBefore检查此LocalDateTime是否在指定的日期时间之后或之前
withDayOfMonth返回此LocalDateTime的拷贝,并将月份中的某天设置为指定值
withMonth, withYear返回此LocalDateTime的拷贝,其月或年设置为指定值

withHour, withMinute, withSecond 返回此LocalDateTime的拷贝,其小时/分钟/秒设置为指定值

LocalDateTime的创建方式
    @Test
    void testLocalDateTime1() {
        
        LocalDateTime localDateTime = LocalDateTime.now();
        System.out.println(localDateTime);//2021-03-04T21:10:08.697760700

        LocalDateTime dateTime = LocalDateTime.of(2021, 3, 14, 5, 20);
        System.out.println(dateTime);//2021-03-14T05:20
    }
LocalDateTime获取年,月,日,小时,分钟或秒
    @Test
    void testLocalDateTime2() {
        LocalDateTime dateTime = LocalDateTime.of(2021, 3, 14, 5, 20);
        System.out.println(dateTime);//2021-03-14T05:20

        System.out.println(dateTime.getYear());//2021
        System.out.println(dateTime.getMonthValue());//3
        System.out.println(dateTime.getHour());//5
        System.out.println(dateTime.getMinute());//20
        System.out.println(dateTime.getSecond());//0
    }
LocalDateTime的加减操作
    @Test
    void testLocalDateTime3() {
        LocalDateTime dateTime = LocalDateTime.of(2021, 3, 14, 5, 20);
        System.out.println(dateTime);//2021-03-14T05:20
        System.out.println(dateTime.plusDays(1).plusMinutes(1).plusMonths(1).plus(1,ChronoUnit.SECONDS));//2021-04-15T05:21:01
        System.out.println(dateTime.minus(1, ChronoUnit.DAYS).minusSeconds(1).minusHours(1).minusMonths(1));//2021-02-13T04:19:59
    }
LocalDateTime 与 Date的转换
    @Test
    void testLocalDateTime4() {
        // LocalDateTime 转 Date
        LocalDateTime localDateTime = LocalDateTime.now();
        System.out.println(localDateTime); //2021-03-04T23:35:28.661442800
        ZoneId zone = ZoneId.systemDefault();
        Instant instant = localDateTime.atZone(zone).toInstant();
        java.util.Date date = Date.from(instant);
        System.out.println(date);//Thu Mar 04 23:35:28 CST 2021
    }
    @Test
    void testLocalDateTime5() {
        // Date 转 LocalDateTime
        java.util.Date date = new java.util.Date();
        System.out.println(date); //Thu Mar 04 23:36:23 CST 2021
        Instant instant = date.toInstant();
        ZoneId zone = ZoneId.systemDefault();
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
        System.out.println(localDateTime);//2021-03-04T23:36:23.589
    }
LocalDateTime 与 Instant的转换
    @Test
    void testLocalDateTime6() {
        // LocalDateTime 转 Instant
        LocalDateTime localDateTime = LocalDateTime.now();
        System.out.println(localDateTime); //2021-03-07T16:23:30.639903200
        ZoneId zone = ZoneId.systemDefault();
        Instant instant = localDateTime.atZone(zone).toInstant();
        System.out.println(instant);//2021-03-07T08:23:30.639903200Z
    }
    @Test
    void testLocalDateTime7() {
        // Instant 转 LocalDateTime
        Instant instant = Instant.now();
        System.out.println(instant); //2021-03-07T08:23:43.286203600Z
        ZoneId zone = ZoneId.systemDefault();
        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, zone);
        System.out.println(localDateTime);//2021-03-07T16:23:43.286203600
    }

Period类

方法描述
between在两个LocalDates之间创建一个Period示例
ofDays, ofWeeks, ofMonths, ofYears创建代表给定天数/周/月/年的Period实例
of根据给定的年数,月数和天数创建一个Period实例
getDays, getMonths, getYears以int形式返回此Period的天数/月/年
isNegative如果此Period的三个部分中的任何一个为负数,则返回true。 否则返回false
isZero如果此Period的所有三个部分均为零,则返回true。 否则,返回false
plusDays, minusDays在此Period上添加或减去给定的天数
plusMonths, minusMonths在此Period上增加或减去给定的月数
plusYears, minusYears在此Period增加或减去给定的年数
withDays以指定的天数返回此Period的拷贝
withMonths以指定的月数返回此Period的拷贝
withYears以指定的年数返回此Period的拷贝
创建Period的方式

创建一个Period很简单,between,of,ofDays / ofWeeks / ofMonths / ofYears等静态工厂方法可以很简单帮我们创建Period

    @Test
    void testPeriodTest1() {
        //创建代表两周的Period实例
        Period twoWeeks = Period.ofWeeks(2);
        System.out.println(twoWeeks);//P14D

        //创建代表一年两个月三天的Period实例
        Period p = Period.of(1, 2, 3);
        System.out.println(p);//P1Y2M3D
    }
Period获取某个期间的年/月/日组件
    @Test
    void testPeriodTest2() {
        //创建代表两周的Period实例
        Period twoWeeks = Period.ofWeeks(2);
        System.out.println(twoWeeks);//P14D
        System.out.println(twoWeeks.getDays());//14


        Period twoYears = Period.ofYears(2);
        System.out.println(twoYears);//P2Y
        System.out.println(twoYears.getYears());//2

        Period twoMonths = Period.ofMonths(2);
        System.out.println(twoMonths);//P2M
        System.out.println(twoMonths.getMonths());//2

    }
Period的加减操作
    @Test
    void testPeriodTest3() {
        //创建代表两周的Period实例
        Period twoWeeks = Period.ofWeeks(2);
        System.out.println(twoWeeks);//P14D
        System.out.println(twoWeeks.getDays());//14

        Period plusDays = twoWeeks.plusDays(1);
        System.out.println(plusDays.getDays());//15


        Period minusDays = plusDays.minusDays(2);
        System.out.println(minusDays.getDays());//13

    }
年龄计算器
    @Test
    void testPeriodTest4() {
        LocalDate dateA = LocalDate.of(1978, 8, 26);
        LocalDate dateB = LocalDate.of(1988, 9, 28);
        Period period = Period.between(dateA, dateB);
        System.out.printf("Between %s and %s"
                        + " there are %d years, %d months"
                        + " and %d days%n", dateA, dateB,
                period.getYears(),
                period.getMonths(),
                period.getDays());//Between 1978-08-26 and 1988-09-28 there are 10 years, 1 months and 2 days
    }

ZonedDateTime类

ZonedDateTime类以一个时区为日期时间的构建。

ZonedDateTime始终是不可变的,时间分量的存储精度为纳秒。

ZonedDateTIme中一些重要方法的使用与LocalDateTime类似,只是多了一个时区的概念。

ZonedDateTime 创建方式
    @Test
    void testZonedDateTime1() {
        //无参now方法会使用计算机的默认时区创建ZonedDateTime
        ZonedDateTime zonedDateTime = ZonedDateTime.now();
        System.out.println(zonedDateTime);//2021-03-07T20:56:15.409935300+08:00[Asia/Shanghai]

        //允许传递区域标识符
        ZonedDateTime parisTime = ZonedDateTime.now(ZoneId.of("Europe/Paris"));
        System.out.println(parisTime);//2021-03-07T13:56:15.411934400+01:00[Europe/Paris]

        ZonedDateTime time = ZonedDateTime.of(2021, 3, 4, 2, 2, 2, 2, ZoneId.systemDefault());
        System.out.println(time);//2021-03-04T02:02:02.000000002+08:00[Asia/Shanghai]

        ZonedDateTime dateTime = ZonedDateTime.of(LocalDateTime.now(), ZoneId.of("Europe/Paris"));
        System.out.println(dateTime);//2021-03-07T20:56:15.414933100+01:00[Europe/Paris]

        ZonedDateTime zonedDateTime1 = ZonedDateTime.of(LocalDate.now(), LocalTime.now(), ZoneId.of("Europe/Paris"));
        System.out.println(zonedDateTime1);//2021-03-07T20:56:15.414933100+01:00[Europe/Paris]

    }

查看所有的时区:

    @Test
    void testZonedDateTimeTest2() {
        Set<String> availableZoneIds = ZoneId.getAvailableZoneIds();
        for (String availableZoneId : availableZoneIds) {
            System.out.println(availableZoneId);
        }
    }
ZonedDateTime 的加减操作
    @Test
    void testZonedDateTime3() {
        ZonedDateTime zonedDateTime = ZonedDateTime.now();
        System.out.println(zonedDateTime);//2021-03-07T21:00:39.707036800+08:00[Asia/Shanghai]
        System.out.println(zonedDateTime.plusDays(1));//2021-03-08T21:00:39.707036800+08:00[Asia/Shanghai]
        System.out.println(zonedDateTime.minus(1, ChronoUnit.DAYS));//2021-03-06T21:00:39.707036800+08:00[Asia/Shanghai]
    }

Duration 类

Duration类是基于时间的持续时间的构建。 它与Period类似,不同之处在于Duration的时间分量为纳秒精度,并考虑了ZonedDateTime实例之间的时区.

方法描述
between在两个时差的对象之间创建一个Duration实例,例如在两个LocalDateTime或两个ZonedDateTime之间。
ofYears, ofMonths, ofWeeks, ofDays, ofHours, ofMinutes, ofSeconds, ofNano创建给定年数/月/周/天/小时/分钟/秒/纳秒的Duration实例
of根据指定数量的时间单位创建Duration实例
toDays, toHours, toMinutes以int形式返回此Duration的天数/小时/分钟数
isNegative如果此Duration为负,则返回true。 否则返回false。
isZero如果此Duration长度为零,则返回true。 否则,返回false
plusDays, minusDays在此Duration内添加或减去指定的天数。
plusMonths, minusMonths在此Duration内添加或减去指定的月数。
plusYears, minusYears在Duration内添加或减去指定的年数
withSeconds以指定的秒数返回此Duration的拷贝。
Duration 的创建方式

可以通过调用静态方法between或of来创建Duration

    @Test
    void testDuration1() {
        LocalDateTime dateTimeA = LocalDateTime
                .of(2015, 1, 26, 8, 10, 0, 0);
        LocalDateTime dateTimeB = LocalDateTime
                .of(2015, 1, 26, 11, 40, 0, 0);
        Duration duration = Duration.between(
                dateTimeA, dateTimeB);

        System.out.printf("There are %d hours and %d minutes.%n",
                duration.toHours(),
                duration.toMinutes() % 60);//There are 3 hours and 30 minutes.
    }

两个ZoneDateTime之间创建一个Duration,具有相同的日期和时间,但时区不同。

    @Test
    void testDuration2() {
        //相同时间 不同时区
        ZonedDateTime zdt1 = ZonedDateTime.of(
                LocalDateTime.of(2015, Month.JANUARY, 1,
                        8, 0),
                ZoneId.of("America/Denver"));
        ZonedDateTime zdt2 = ZonedDateTime.of(
                LocalDateTime.of(2015, Month.JANUARY, 1,
                        8, 0),
                ZoneId.of("America/Toronto"));

        Duration duration = Duration.between(zdt1, zdt2);
        System.out.printf("There are %d hours and %d minutes.%n",
                duration.toHours(),
                duration.toMinutes() % 60);//There are -2 hours and 0 minutes.
    }

DateTimeFormatter 类

    @Test
    void testDateTimeFormatter() {
        LocalDate localDate = LocalDate.of(2019, 9, 10);
        String format = localDate.format(DateTimeFormatter.BASIC_ISO_DATE);
        System.out.println(format);//20190910

        DateTimeFormatter dateTimeFormatter =   DateTimeFormatter.ofPattern("dd/MM/yyyy");
        String format2 = localDate.format(dateTimeFormatter);
        System.out.println(format2);//10/09/2019


        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.CHINA);
        LocalDateTime parse = LocalDateTime.parse("2017-04-01 22:39:40", timeFormatter);
        System.out.println(parse);//2017-04-01T22:39:40
    }

参考

java 8新特性 instant 和 LocalDateTime

使用Java 8 的日期和时间Api

LocalDateTime,String,Instant相互转换

Java8学习笔记:LocalDateTime、Instant 和 OffsetDateTime 相互转换

java中的时间与时区:LocalDateTime和Date

Java 8 Date-Time API 详解

Java面试问题总结——为什么处理时间问题建议使用LocalDate类而逐渐抛弃Date类?

源代码

https://gitee.com/cckevincyh/java8_time_date

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值