• Java8 JSR310规范-时间日期API使用总结


    参考资料

    1. 【小家java】java8新特性之—全新的日期、时间API(JSR 310规范),附SpringMVC、Mybatis中使用JSR310的正确姿势
    2. Java 8新特性(四):新的时间和日期API
    3. Java 8的时间类使用大全
    4. Java8中计算时间的四种方式及区别Period、Duration、ChronoUnit、Until & 时间区间Duration的简单使用
    5. Java8之新日期时间篇


    零. 前言

    Java 8之前,所有关于时间和日期的API都存在各种使用方面的缺陷,主要有:

    • ⏹Java的java.util.Date和java.util.Calendar类易用性差,不支持时区,而且他们都不是线程安全的;
      用于格式化日期的类DateFormat被放在java.text包中,它是一个抽象类,所以我们需要实例化一个SimpleDateFormat对象来处理日期格式化,并且DateFormat也是非线程安全,你得把它用ThreadLocal包起来才能在多线程中使用。
    • ⏹对日期的计算方式繁琐,而且容易出错,因为月份是从0开始的,从Calendar中获取的月份需要加一才能表示当前月份。

    由于以上这些问题,出现了一些三方的日期处理框架,例如Joda-Time,date4j等开源项目。但是,Java需要一套标准的用于处理时间和日期的框架,于是Java 8中引入了新的日期API。新的日期API是JSR-310规范的实现,Joda-Time框架的作者正是JSR-310的规范的倡导者,所以能从Java 8的日期API中看到很多Joda-Time的特性。


    一. 构建对象

    1.1 LocalDate

    ⏹只有年月日的时间

    // 构造2017年1月1日的时间对象
    LocalDate localDate1 = LocalDate.of(2017, 1, 1);
    // 获取当前时间
    LocalDate localDate2 = LocalDate.now();
    // 通过年月对象来构造
    LocalDate localDate3 = YearMonth.of(2022, 12).atDay(1);
    // 通过LocalDateTime获取LocalDate
    LocalDate localDate4 = LocalDateTime.now().toLocalDate();
    LocalDate localDate5 = LocalDate.from(LocalDateTime.now());
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    1.2 LocalTime

    ⏹只有时间,没有年月日

    // 构造时分秒对象
    LocalTime localTime1 = LocalTime.of(10, 15, 12);
    // 构造时分对象
    LocalTime localTime2 = LocalTime.of(10, 15);
    // 构造当前时间对象
    LocalTime localTime3 = LocalTime.now();
    // 通过LocalDateTime获取LocalTime 
    LocalTime localTime4 = LocalDateTime.now().toLocalTime();
    LocalTime localTime5 = LocalTime.from(LocalDateTime.now());
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    1.3 LocalDateTime

    ⏹有年月日和时间

    // 构造年月日时分秒对象
    LocalDateTime localDateTime1 = LocalDateTime.of(2023, 5, 15, 10, 15, 10);
    // 构造年月日时分对象
    LocalDateTime localDateTime2 = LocalDateTime.of(2023, 5, 15, 10, 15);
    // 构造当前时间对象
    LocalDateTime localDateTime3 = LocalDateTime.now();
    // 通过LocalDate + LocalTime来构造
    LocalDateTime localDateTime4 = LocalDate.of(2023, 5, 15).atTime(10, 15, 10);
    LocalDateTime localDateTime5 = LocalDate.of(2023, 5, 15).atTime(LocalTime.of(10, 15, 10));
    // 一天的开头和结尾LocalDateTime 
    LocalDateTime localDateTime6 = LocalDate.of(2023, 5, 15).atStartOfDay();
    LocalDateTime localDateTime7 = LocalDate.of(2023, 5, 15).atTime(LocalTime.MIN);
    LocalDateTime localDateTime8 = LocalDate.of(2023, 5, 15).atTime(LocalTime.MAX);
    // 通过Instant来构建(需要指定时区)
    LocalDateTime localDateTime9 = LocalDateTime.ofInstant(Instant.now(), ZoneId.systemDefault());
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    1.4 Instant

    ⏹Instant用于表示一个时间戳,它与我们常使用的System.currentTimeMillis()有些类似,不过

    • Instant可以精确到纳秒(Nano-Second)
    • System.currentTimeMillis()方法只精确到毫秒(Milli-Second)。
    // 获取当前时间的时间戳(UTC时间,非北京/东京时间)
    Instant instant1 = Instant.now();
    // 获取北京时间的时间戳
    Instant instant2 = Instant.now().plusMillis(TimeUnit.HOURS.toMillis(8));
    // 通过LocalDateTime构造Instant
    Instant instant3 = LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant();
    // 通过Date构造Instant
    Instant instant4 = new Date().toInstant();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    1.5 YearMonth

    ⏹年月时间对象

    YearMonth yearMonth1 = YearMonth.of(2022, 12);
    YearMonth yearMonth2 = YearMonth.now();
    // 通过LocalDate和LocalDateTime来构造
    YearMonth yearMonth3 = YearMonth.from(LocalDate.now());
    YearMonth yearMonth4 = YearMonth.from(LocalDateTime.now());
    
    • 1
    • 2
    • 3
    • 4
    • 5

    1.6 MonthDay

    ⏹月日时间对象,多用来表示周期性事件,例如生日和纪念日

    MonthDay monthDay1 = MonthDay.of(2022, 12);
    MonthDay monthDay2 = MonthDay.from(LocalDateTime.now());
    MonthDay monthDay3 = MonthDay.now();
    
    • 1
    • 2
    • 3

    1.7 Period

    ⏹Period是以年月日来衡量一个时间段的对象。
    ⏹可以通过.between()来创建一个段时间,由于以年月日来衡量,因此接收的参数只能是LocalDate类型的,不能是LocalDateTime类型的。

    // 2年3个月6天的时间段
    Period period1 = Period.of(2, 3, 6);
    // 2017-01-05 到 2017-02-05 这段时间
    Period period2 = Period.between(
            LocalDate.of(2017, 1, 5),
            LocalDate.of(2017, 2, 5)
    );
    // 当前日期和2023年11月11日之间的这段时间
    Period untilPeriod = LocalDate.now().until(LocalDate.of(2023, 11, 11));
    
    // 1整年,1个月,1个周,1整天的时间段
    Period periodYears = Period.ofYears(1);
    Period periodMonths = Period.ofMonths(1);
    Period periodWeeks = Period.ofWeeks(1);
    Period periodDays = Period.ofDays(1);
    // 3年3月3天的时间段
    Period year3Month3Day3 = Period.ofYears(3)
                    .plus(Period.ofMonths(3))
                    .plus(Period.ofDays(3));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    1.8 Duration

    ⏹Duration是以年月日时分秒来衡量一个时间段的对象。

    // ChronoUnit.YEARS ChronoUnit.MONTHS ChronoUnit.WEEKS 无法使用,会报错.
    
    // 5天
    Duration duration4 = Duration.of(5, ChronoUnit.DAYS);
    // 5个小时
    Duration duration5 = Duration.of(5, ChronoUnit.HOURS);
    // 5分钟
    Duration duration6 = Duration.of(5, ChronoUnit.MINUTES);
    // 5秒
    Duration duration7 = Duration.of(5, ChronoUnit.SECONDS);
    // 1000毫秒
    Duration duration8 = Duration.of(1000, ChronoUnit.MILLIS);
    
    // 2017-01-05 10:07:00 到 2017-02-05 10:07:00 这个时间段
    Duration duration9 = Duration.between(
        // 2017-01-05 10:07:00
        LocalDateTime.of(2017, Month.JANUARY, 5, 10, 7, 0),
        // 2017-02-05 10:07:00
        LocalDateTime.of(2017, Month.FEBRUARY, 5, 10, 7, 0)
    );
    
    // 3天3小时的时间段对象
    Duration duration10 = Duration.ofDays(3).plusHours(3);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    二. 获取

    2.1 时间戳

    ⏹获取时间戳的四种方式

    System.currentTimeMillis();
    Clock.systemDefaultZone().millis();
    Calendar.getInstance().getTimeInMillis();
    Instant.now().toEpochMilli()
    
    • 1
    • 2
    • 3
    • 4

    2.2 当前年

    int year = LocalDate.now().getYear();
    
    • 1

    2.3 月

    2.3.1 当前月

    int monthValue1 = LocalDate.now().getMonthValue();
    Month month = LocalDate.now().getMonth();
    int monthValue2 = month .getValue();
    
    • 1
    • 2
    • 3

    2.3.2 当前月底对象

    LocalDate localDate = YearMonth.of(2022, 12).atEndOfMonth();
    
    • 1

    2.3.3 月总天数

    int dayCount = LocalDate.of(2016, 2, 1).lengthOfMonth();
    System.out.println(dayCount);  // 29
    
    ValueRange range = LocalDate.of(2023, 9, 13).range(ChronoField.DAY_OF_MONTH);
    range.getMaximum();  // 30
    
    YearMonth yearMonth = YearMonth.of(2023, Month.JANUARY);
    System.out.println(yearMonth.lengthOfMonth());  // 31
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2.4 日

    2.4.1 当前日

    ⏹日期是月份的第几号

    int dayOfMonth = LocalDate.now().getDayOfMonth();
    
    • 1

    2.4.2 年份的第几天

    ⏹当前日期在本年度处于第几天

    int dayOfYear1 = LocalDate.of(2023, 9, 13).getDayOfYear();  // 256
    int dayOfYear2 = LocalDate.of(2023, 9, 13).get(ChronoField.DAY_OF_YEAR);  // 256
    
    • 1
    • 2

    2.5 周

    2.5.1 本周周几

    ⏹当前日期是本周的周几

    int dayOfWeek = LocalDate.now().getDayOfWeek().getValue();
    
    • 1

    2.5.2 月份第几周

    int num = LocalDate.of(2021, 8, 28).get(ChronoField.ALIGNED_WEEK_OF_MONTH);  // 5
    
    • 1

    2.5.3 年度第几周

    int num = LocalDate.of(2021, 8, 28).get(ChronoField.ALIGNED_WEEK_OF_YEAR);  // 35
    
    • 1

    2.5.4 本月对齐周

    ⏹对齐周的取值范围为1~7
    ⏹对齐周是从日历上看,当前日所在月份按周向上对齐。
    ⏹2023年8月28号所在的对齐周是7,因为31是7月所在的日期,不是8月的。

    int num1 = LocalDate.of(2023, 8, 15).get(ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH);  // 1
    int num2 = LocalDate.of(2023, 8, 28).get(ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH);  // 7
    
    • 1
    • 2

    在这里插入图片描述

    2.6 两个日期之间的所有日期

    ⏹方式1

    // 开始日
    LocalDate startLocalDate = LocalDate.of(2023, 5, 10);
    // 结束日
    LocalDate endLocalDate = LocalDate.of(2023, 6, 8);
    // 开始日和结束日之间的天数间隔
    long distance = ChronoUnit.DAYS.between(startLocalDate, endLocalDate);
    // 指定格式化
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
    
    List<String> localDateList = 
    		// 使用生成流生成日期
    		Stream.iterate(startLocalDate, d -> d.plusDays(1))
            .limit(distance + 1)
            // 将日期全部格式化
            .map(localDate_ -> localDate_.format(formatter))
            .collect(toList());
    System.out.println(localDateList);
    /*
    	2023-05-10
    	, 2023-05-11
    	, 2023-05-12
    	, 2023-05-13
    	, 2023-05-14
    	, 2023-05-15
    	, 2023-05-16
    	, ...... 
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    ⏹方式2:参考该文章
    Java 获取两个日期之间的所有日期


    三. 计算

    3.1 两个日期的间隔年

    long betweenYears = ChronoUnit.YEARS.between(LocalDate.of(2017, 1, 1), LocalDate.of(2022, 10, 16));
    System.out.println(betweenYears);  // 5
    
    long untilYears = LocalDate.of(2017, 1, 1).until(LocalDate.of(2022, 10, 16), ChronoUnit.YEARS);
    System.out.println(untilYears);  // 5
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3.2 两个日期的间隔月

    long betweenMonths = ChronoUnit.MONTHS.between(LocalDate.of(2017, 1, 1), LocalDate.of(2018, 5, 16));
    System.out.println(betweenMonths);  // 16
    
    long untilMonths = LocalDate.of(2017, 1, 1).until(LocalDate.of(2018, 5, 16), ChronoUnit.MONTHS);
    System.out.println(untilMonths);  // 16
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3.3 两个日期的间隔日

    long betweenDays = ChronoUnit.DAYS.between(LocalDate.of(2017, 2, 13), LocalDate.of(2017, 5, 18));
    System.out.println(betweenDays);  // 94
    
    long untilDays = LocalDate.of(2017, 2, 13).until(LocalDate.of(2017, 5, 18), ChronoUnit.DAYS);
    System.out.println(untilDays);  // 94
    
    LocalDateTime fromLocalDateTime = LocalDate.of(2017, 2, 13).atTime(8, 0, 0);
    LocalDateTime toLocalDateTime = LocalDate.of(2017, 5, 18).atTime(8, 30, 0);
    long days = Duration.between(fromLocalDateTime, toLocalDateTime).toDays();
    System.out.println(days);  // 94
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    3.4 两个日期的间隔时,分等

    ⏹间隔时

    long untilHours = LocalTime.of(10, 15).until(LocalTime.of(12, 45), ChronoUnit.HOURS);
    System.out.println(untilHours);  // 2
    
    • 1
    • 2

    ⏹间隔分

    long untilMinutes = LocalTime.of(10, 15).until(LocalTime.of(12, 45), ChronoUnit.MINUTES);
    System.out.println(untilMinutes);  // 150
    
    • 1
    • 2

    3.5 时间矫正器

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

    3.5.1 本月(第一天/最后一天)

    LocalDate of1 = LocalDate.of(2022, 10, 16);
    // 本月第一天
    LocalDate result1 = of1.with(TemporalAdjusters.firstDayOfMonth());  // 2022-10-01
    // 本月最后一天
    LocalDate result2 = of1.with(TemporalAdjusters.lastDayOfMonth());  // 2022-10-31
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3.5.2 本月第一个周?

    // 本月第一个周五
    LocalDate of1 = LocalDate.of(2022, 10, 16);
    LocalDate result3 = of1.with(TemporalAdjusters.firstInMonth(DayOfWeek.FRIDAY));  // 2022-10-07
    
    • 1
    • 2
    • 3

    3.5.3 (上/下)一个周?

    // 上一个周六
    LocalDate result4 = LocalDate.of(2023, 9, 16).with(TemporalAdjusters.previous(DayOfWeek.SATURDAY));
    System.out.println(result4);  // 2023-09-09
    
    // 下一个周五
    LocalDate result5 = LocalDate.of(2023, 9, 16).with(TemporalAdjusters.next(DayOfWeek.FRIDAY));
    System.out.println(result5);  // 2023-09-22
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    3.5.4 自定义时间矫正器_获取指定月份工资日

    LocalDate salaryDate = this.getSalaryDate(2023, 6);
    System.out.println(salaryDate);  // 2023-06-23
     
    // 下一个工资日,工资是每个月的25号发,如果25号是周六或者周日的话,就改为该周的周五发.
    private LocalDate getSalaryDate(Integer year, Integer month) {
    
        // 自定义一个时间矫正器,用来计算工资日
        TemporalAdjuster salaryTemporalAdjuster = temporal -> {
    
            LocalDate date = LocalDate.class.cast(temporal);
            // 获取当前月的25号的LocalDate对象
            LocalDate localDate25 = date.plusDays(24);
            // 获取指定月份25号的DayOfWeek对象
            DayOfWeek salaryWeek = localDate25.getDayOfWeek();
    
            // 如果指定月份的25号既不是周六也不是周日的话,直接返回当月的25号的LocalDate
            if (DayOfWeek.SATURDAY.compareTo(salaryWeek) != 0 && DayOfWeek.SUNDAY.compareTo(salaryWeek) != 0) {
                return localDate25;
            }
    
            // 如果指定月的25号是周六或者周日的话,那么将日期提前到上一个周五当做工资日
            return localDate25.with(TemporalAdjusters.previous(DayOfWeek.FRIDAY));
        };
    
        return LocalDate.of(year, month, 1).with(salaryTemporalAdjuster);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    四. 修改

    4.1 年

    LocalDate localDate1 = LocalDate.of(2023, 8, 14).withYear(1997);
    // 1997-08-14
    
    • 1
    • 2

    4.2 月

    LocalDate localDate2 = LocalDate.of(2023, 8, 14).withMonth(5);
    // 2023-05-14
    
    • 1
    • 2

    4.3 日

    4.3.1 指定月的第?天

    LocalDate localDate3 = LocalDate.of(2023, 8, 14).withDayOfMonth(29);
    // 2023-08-29
    
    • 1
    • 2

    4.3.2 指定年的第?天

    LocalDate localDate4 = LocalDate.of(2023, 8, 14).withDayOfYear(6);
    // 2023-01-06
    
    • 1
    • 2

    4.4 ?天前/后

    // 3天前
    LocalDate.now().minusDays(3);
    // 3天后
    LocalDate.now().plusDays(3);
    
    // 构造3天的时间段对象
    Period period3Day = Period.ofDays(3);
    // 3天前
    LocalDate.now().plus(period3Day);
    // 3天后
    LocalDate.now().minus(period3Day);
    
    // 3天前
    LocalDate.now().plus(3, ChronoUnit.DAYS);
    // 3天后
    LocalDate.now().minus(3, ChronoUnit.DAYS);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    4.5 ?周前/后

    // 1周前
    LocalDate.now().minusWeeks(1);
    // 1周后
    LocalDate.now().plusWeeks(1);
    
    • 1
    • 2
    • 3
    • 4

    4.6 ?月前/后

    // 1月前
    LocalDate.now().minusMonths(1);
    // 1月后
    LocalDate.now().plusMonths(1);
    
    // 1月前
    LocalDate.now().minus(1, ChronoUnit.MONTHS);
    // 1月后
    LocalDate.now().plus(1, ChronoUnit.MONTHS);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    4.7 ?年前/后

    // 1年前
    LocalDate.now().minusYears(1);
    // 1年后
    LocalDate.now().plusYears(1);
    
    • 1
    • 2
    • 3
    • 4

    五. 判断

    5.1 日期A早于日期B

    LocalDate.of(2023, 8, 14).isBefore(LocalDate.of(2023, 8, 15));  // true
    LocalDate.of(2023, 8, 14).compareTo(LocalDate.of(2023, 8, 15));  // -1
    
    • 1
    • 2

    5.2 日期A晚于日期B

    LocalDate.of(2023, 8, 14).isAfter(LocalDate.of(2023, 8, 15));  // false
    LocalDate.of(2023, 8, 14).compareTo(LocalDate.of(2023, 8, 15));  // -1
    
    • 1
    • 2

    5.3 日期相等

    ⏹普通日期判断相等

    // 使用.equals()判断
    LocalDate.of(2023, 9, 12).equals(LocalDate.now());
    // 使用.compareTo()判断
    LocalDate.of(2023, 8, 14).compareTo(LocalDate.of(2023, 8, 14));  // 0
    
    • 1
    • 2
    • 3
    • 4

    ⏹生日判断相等

    LocalDate birthdayLocalDate = LocalDate.of(1994, 12, 16);
    // 构造月日对象
    MonthDay birthMonthDay = MonthDay.of(
    	birthdayLocalDate.getMonth()
    	, birthdayLocalDate.getDayOfMonth()
    );
    MonthDay.now().equals(birthMonthDay);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    5.4 闰年

    LocalDate.now().isLeapYear();
    Year.isLeap(2020);
    
    • 1
    • 2

    六. 格式化

    6.1 字符串转日期

    • 非严格模式下的字符串转日期
    // 构造一个日期格式化对象
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日");
    // 字符串 --> 日期
    LocalDate parseLocalDate = LocalDate.parse("2016年10月25日", formatter);
    
    • 1
    • 2
    • 3
    • 4

    6.2 日期转字符串

    LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy年MM月"));
    
    DateTimeFormatter.ofPattern("yyyy年MM月").format(LocalDate.now());
    
    • 1
    • 2
    • 3

    七. 转换

    ⏹从包含的信息量而言,LocalDateTime > LocalDate > LocalTime,因此可以自上而下转换,不能自下而上转换。

    ⏹LocalDate和Date类、时间戳之间转换

    • Date对象表示特定的日期和时间,而LocalDate(Java8)对象只包含没有任何时间信息的日期。
    • 因此,如果我们只关心日期而不是时间信息,则可以在Date和LocalDate之间进行转换。
    • 转换的中间桥梁都是时间戳Instant对象,但是转换的时候如果没有考虑时区,就会报错的。

    7.1 LocalDateTime --> LocalDate

    LocalDate localDate = LocalDate.from(LocalDateTime.now());
    
    • 1

    7.2 LocalDateTime --> LocalTime

    LocalTime localTime = LocalTime.from(LocalDateTime.now());
    
    • 1

    7.3 LocalDateTime 互转 Instant

    // 构造一个LocalDateTime对象
    LocalDateTime localDateTime1 = LocalDate.of(2023, 5, 15).atTime(LocalTime.MAX);
    
    // LocalDateTime --> Instant
    Instant instant = localDateTime1.atZone(ZoneId.systemDefault()).toInstant();
    // Instant --> LocalDateTime
    LocalDateTime localDateTime2 = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    7.3 LocalDate --> YearMonth

    YearMonth yearMonth = YearMonth.from(LocalDate.now());
    
    • 1

    7.4 LocalDate --> MonthDay

    MonthDay monthDay = MonthDay.from(LocalDate.now());
    
    • 1

    7.5 Date 互转 LocalDateTime

    ⏹Date --> LocalDateTime

    Date date = new Date();
    // Date 转换 Instant 
    Instant instantOfDate = date.toInstant();
    // Instant 转换 LocalDateTime
    LocalDateTime localDateTime = LocalDateTime.ofInstant(instantOfDate, ZoneId.systemDefault());
    
    • 1
    • 2
    • 3
    • 4
    • 5

    ⏹LocalDateTime --> Date

    Instant instantLocalDateTime = LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant();
    Date dateLocalDateTime = Date.from(instantLocalDateTime);
    
    • 1
    • 2

    7.6 Date 互转 LocalDate

    ⏹Date --> LocalDate

    public LocalDate date2LocalDate(Date date) {
        ZonedDateTime zdt = date.toInstant().atZone(ZoneId.systemDefault());
        return zdt.toLocalDate();
    }
    
    • 1
    • 2
    • 3
    • 4

    ⏹LocalDate --> Date

    public Date localDate2Date(LocalDate localDate){
        ZonedDateTime zdt = localDate.atStartOfDay(ZoneId.systemDefault());
        return Date.from(zdt.toInstant());
    }
    
    • 1
    • 2
    • 3
    • 4

    八. 小案例

    8.1 统计程序运行所消耗的时间

    // 开始时间
    Instant startInstant = Instant.now();
    
    // 模拟程序运行耗时
    try {
        Thread.sleep(2000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    
    // 终了时间
    Instant endInstant = Instant.now();
    
    // 获取开始和终了时间的时间段对象
    Duration taskTime = Duration.between(startInstant, endInstant);
    long second = taskTime.toSeconds();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    8.2 高并发下Data格式化正确使用方式

    // 高并发环境下Data的正确使用方式,要和ThreadLocal进行绑定
    private static ThreadLocal<DateFormat> threadLocal = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
    
    // 和线程绑定 保证安全
    public static String format(Date date) {
        return threadLocal.get().format(date);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
  • 相关阅读:
    Redis参数规范详解
    微软8月系统更新引发问题:虚拟内存分页文件出现错误
    【深度学习】卷积层填充和步幅以及其大小关系
    ROS学习十二、图像传输Image_transport使用
    大数据之Kafka
    1.1.OpenCV技能树--第一单元--OpenCV简介
    来自雪域高原的馈赠——大凉山高原生态糖心苹果
    STM32CubeIDE基础学习-EXTI外部中断实验
    流程图在线制作:5款专业流程图制作网站,无需下载,高效立现!
    面试经典-Spring篇
  • 原文地址:https://blog.csdn.net/feyehong/article/details/132845562