• 20191227 Java8 日期时间API


    背景

    Java 8通过发布新的Date-Time API (JSR 310)来进一步加强对日期与时间的处理。

    在旧版的 Java 中,日期时间 API 存在诸多问题,其中有:

    • 非线程安全 − java.util.Date 是非线程安全的,所有的日期类都是可变的,这是Java日期类最大的问题之一。
    • 设计很差 − Java的日期/时间类的定义并不一致,在java.util和java.sql的包中都有日期类,此外用于格式化和解析的类在java.text包中定义。java.util.Date同时包含日期和时间,而java.sql.Date仅包含日期,将其纳入java.sql包并不合理。另外这两个类都有相同的名字,这本身就是一个非常糟糕的设计。
    • 时区处理麻烦 − 日期类并不提供国际化,没有时区支持,因此Java引入了java.util.Calendar和java.util.TimeZone类,但他们同样存在上述所有的问题。

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

    • Local(本地) − 简化了日期时间的处理,没有时区的问题。
    • Zoned(时区) − 通过制定的时区处理日期时间。

    新的java.time包涵盖了所有处理日期,时间,日期/时间,时区,时刻(instants),过程(during)与时钟(clock)的操作。

    LocalDateTime, LocalDate, LocalTime

    这三者是本地化日期时间API

    • LocalDateTime 包含日期和时间,比如:2018-09-24 10:32:10
    • LocalDate 只包含日期,比如:2018-09-24
    • LocalTime 只包含时间,比如:10:32:10
    private void testLocalDateTime() {
    
        System.out.println("=================== testLocalDateTime ============================");
    
        // 获取当前的日期时间
        LocalDateTime localDateTime = LocalDateTime.now();
        System.out.println("当前日期时间: " + localDateTime);
        System.out.println("当前日期: " + localDateTime.toLocalDate());
        System.out.println("当前时间: " + localDateTime.toLocalTime());
    
        System.out.println(",================== get =============================");
        // get
        // 获取日期时间的单项值
        int year = localDateTime.get(ChronoField.YEAR);
        Month month = localDateTime.getMonth();
        int monthValue = localDateTime.getMonthValue();
        int dayOfYear = localDateTime.getDayOfYear();
        int dayOfMonth = localDateTime.getDayOfMonth();
        DayOfWeek dayOfWeek = localDateTime.getDayOfWeek();
        int hour = localDateTime.getHour();
        int minute = localDateTime.getMinute();
        int seconds = localDateTime.getSecond();
        int nano = localDateTime.getNano();
    
        System.out.println("year:" + year);
        System.out.println("month:" + month);
        System.out.println("monthValue:" + monthValue);
        System.out.println("dayOfYear:" + dayOfYear);
        System.out.println("dayOfMonth:" + dayOfMonth);
        System.out.println("dayOfWeek:" + dayOfWeek);
        System.out.println("hour:" + hour);
        System.out.println("minute:" + minute);
        System.out.println("seconds:" + seconds);
        System.out.println("nano:" + nano);
    
        System.out.println(",================== with, plus, minus =============================");
    
        LocalDateTime withDateTime = localDateTime.with(ChronoField.YEAR, 2000).withMonth(10);
        System.out.println("withDateTime: " + withDateTime);
    
        LocalDateTime plusLocalDateTime = localDateTime.plus(1, ChronoUnit.MONTHS);
        System.out.println("plusLocalDateTime: " + plusLocalDateTime);
    
        LocalDateTime minusLocalDateTime = localDateTime.minusDays(1);
        System.out.println("minusLocalDateTime: " + minusLocalDateTime);
    
        System.out.println(",================== of =============================");
        // of
        // 通过指定值获取指定日期
        LocalDateTime ofLocalDateTime = LocalDateTime.of(2019, 12, 27, 15, 8, 7);
        System.out.println("ofLocalDateTime:" + ofLocalDateTime);
    
        LocalDate ofLocalDate = LocalDate.of(2014, Month.DECEMBER, 12);
        System.out.println("ofLocalDate: " + ofLocalDate);
    
        LocalTime ofLocalTime = LocalTime.of(22, 15);
        System.out.println("ofLocalTime: " + ofLocalTime);
    
    
        System.out.println(",================== parse =============================");
        // parse
        // 将字符串解析为日期、时间
        LocalDateTime parseDateTime = LocalDateTime.parse("2019-11-01T20:15:30.001");
        System.out.println("parseDateTime: " + parseDateTime);
    
        LocalDate parseDate = LocalDate.parse("2019-11-01");
        System.out.println("parseDate: " + parseDate);
    
        LocalTime parseTime = LocalTime.parse("20:15:30");
        System.out.println("parseTime: " + parseTime);
    
        System.out.println(",================== isAfter, isBefore =============================");
        boolean isAfter = localDateTime.isAfter(localDateTime.minusDays(1));
        System.out.println("isAfter: " + isAfter);
    
        boolean isBefore = localDateTime.isBefore(localDateTime.minusDays(1));
        System.out.println("isBefore: " + isBefore);
    
        System.out.println("================== LocalDate =============================");
    
        LocalDate localDate = LocalDate.now();
        System.out.println("localDate:" + localDate);
    
        int lengthOfMonth = localDate.lengthOfMonth();
        System.out.println("该月天数:" + lengthOfMonth);
    
        boolean isLeapYear = localDate.isLeapYear(); // false
        System.out.println("是否闰年:" + isLeapYear);
    
        LocalDateTime dateTime = localDate.atTime(5, 6);
        System.out.println("转为LocalDateTime:" + dateTime);
    
        System.out.println("================== LocalTime =============================");
    
        LocalTime localTime = LocalTime.now();
        System.out.println("localTime:" + localTime);
    
        LocalDateTime localDateTime1 = localTime.atDate(localDate);
        System.out.println("转为LocalDateTime:" + localDateTime1);
    
    
    }
    

    ZonedDateTime

    带时区的日期时间

    private void testZonedDateTime() {
    
        System.out.println("=================== testZonedDateTime ============================");
    
        // 获取当前时间日期
        ZonedDateTime date1 = ZonedDateTime.parse("2015-12-03T10:15:30+05:30[Asia/Shanghai]");
        System.out.println("date1: " + date1);
    
        ZoneId id = ZoneId.of("Europe/Paris");
        System.out.println("ZoneId: " + id);
    
        ZoneId currentZone = ZoneId.systemDefault();
        System.out.println("当期时区: " + currentZone);
    }
    

    MonthDay

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

    private void testMonthDay() {
        System.out.println("=================== testMonthDay ============================");
    
        LocalDate birthday = LocalDate.of(1999, 12, 27);
        MonthDay monthDay = MonthDay.of(birthday.getMonth(), birthday.getDayOfMonth());
    
        System.out.println("monthDay:" + monthDay);
    
        MonthDay fromMonthDay = MonthDay.from(LocalDate.now());
        System.out.println("MonthDay.from(LocalDate.now()):" + fromMonthDay);
    
    
        if (fromMonthDay.equals(monthDay)) {
            System.out.println("happy birthday!");
        } else {
            System.out.println("not birthday!");
        }
    }
    

    Period

    Period用于计算两个LocalDate之间的时长。

    private void testPeriod() {
        System.out.println("=================== testPeriod ============================");
    
    
        LocalDate date1 = LocalDate.of(2018, 9, 30);
        LocalDate date2 = LocalDate.of(2018, 10, 31);
    
        Period period = Period.between(date1, date2);
        System.out.println("period:" + period);
    
        List<TemporalUnit> units = period.getUnits();
        System.out.println("units:" + units);
    
        int months = period.getMonths();
        int days = period.getDays();
    
        System.out.println("months:" + months);
        System.out.println("days:" + days);
    
    }
    

    Duration

    Duration用于计算两个LocalTime或者LocalDateTime的时间差。

    private void testDuration() {
        System.out.println("=================== testDuration ============================");
    
        LocalDateTime dateTime1 = LocalDateTime.now();
        LocalDateTime dateTime2 = LocalDateTime.now().plusSeconds(60 * 60 * 2 + 1).minusNanos(1000000);
    
        Duration duration = Duration.between(dateTime1, dateTime2);
        System.out.println("duration:" + duration);
    
        List<TemporalUnit> units = duration.getUnits();
        System.out.println("duration.getUnits():" + units);
    
        long seconds = duration.getSeconds();
        System.out.println("duration.getSeconds():" + seconds);
    
        long nano = duration.getNano();
        System.out.println("duration.getNano():" + nano);
    
        boolean isZero = duration.isZero();
        System.out.println("duration.isZero():" + isZero);
    
        long hours = duration.toHours();
        System.out.println("duration.toHours():" + hours);
    
        Duration abs = duration.abs();
        System.out.println("duration.abs():" + abs);
    
        boolean isNegative = duration.isNegative();
        System.out.println("duration.isNegative():" + isNegative);
    
        Duration withDuration = duration.withSeconds(5);
        System.out.println("duration.withSeconds(5):" + withDuration);
    
        Duration plusNanos = duration.plusNanos(1000000);
        System.out.println("duration.plusNanos(1000000):" + plusNanos);
    
    }
    

    Instant

    时间戳。

    private void testInstant() {
        System.out.println("=================== testInstant ============================");
    
        Instant instant = Instant.now();
        System.out.println("instant:" + instant);
    
        // 获取毫秒数
        long toEpochMilli = instant.toEpochMilli();
        System.out.println("toEpochMilli:" + toEpochMilli);
    
    }
    

    Clock

    Clock 通过指定一个时区,然后就可以获取到当前的时刻,日期与时间。可以替代 System.currentTimeMillis() 与 TimeZone.getDefault() 。

    private void testClock() {
        System.out.println("=================== testClock ============================");
    
        Clock clock = Clock.systemDefaultZone();
        System.out.println("Clock.systemDefaultZone():" + clock);
    
        Instant instant = clock.instant();
        System.out.println("clock.instant():" + instant);
    
    }
    

    ZoneId, ZoneOffset, ZoneRegion

    对时区的操作。

    ZoneId是抽象类,是ZoneOffset和ZoneRegion的父类。

    private void testZone() {
        System.out.println("=================== testZone ============================");
    
        System.out.println(",=================== ZoneId ============================");
    
        Set<String> set = ZoneId.getAvailableZoneIds();
        System.out.println("ZoneId.getAvailableZoneIds():" + Arrays.toString(set.toArray()));
    
        System.out.println(",,=================== ZoneOffset ============================");
    
        ZoneId systemDefaultZoneId = ZoneId.systemDefault();
        System.out.println("ZoneId.systemDefault():" + systemDefaultZoneId);
    
        ZoneId ofZoneId = ZoneId.of("Asia/Aden");
        System.out.println("ofZoneId.getClass():" + ofZoneId.getClass());
        System.out.println("ZoneId.of("Asia/Aden"):" + ofZoneId);
    
    
        System.out.println(",,=================== ZoneRegion ============================");
    
        ZoneId ofZoneRegion = ZoneId.of("+8");
        System.out.println("ofZoneRegion.getClass():" + ofZoneRegion.getClass());
        System.out.println("ZoneId.of("+8"):" + ofZoneRegion);
    
    
    }
    

    TemporalAdjuster, TemporalAdjusters

    用于调整日期时间。

    TemporalAdjuster 是函数式接口,TemporalAdjusters 是工具类。

    private void testTemporalAdjusters() {
        System.out.println("=================== testTemporalAdjusters ============================");
    
        LocalDateTime localDateTime = LocalDateTime.now();
        System.out.println("当前时间:" + localDateTime);
    
        TemporalAdjuster temporalAdjuster = null;
    
        System.out.println("=================== first, last ============================");
    
        temporalAdjuster = TemporalAdjusters.firstInMonth(DayOfWeek.FRIDAY);
        this.adjustDateTime("当月的第一个星期五", temporalAdjuster);
    
        temporalAdjuster = TemporalAdjusters.firstDayOfMonth();
        this.adjustDateTime("当月的第一天", temporalAdjuster);
    
        temporalAdjuster = TemporalAdjusters.firstDayOfNextMonth();
        this.adjustDateTime("下个月的第一天", temporalAdjuster);
    
        temporalAdjuster = TemporalAdjusters.lastInMonth(DayOfWeek.FRIDAY);
        this.adjustDateTime("当月的最后一个星期五", temporalAdjuster);
    
        temporalAdjuster = TemporalAdjusters.lastDayOfMonth();
        this.adjustDateTime("当月的最后一天", temporalAdjuster);
    
        temporalAdjuster = TemporalAdjusters.lastDayOfYear();
        this.adjustDateTime("当年的最后一天", temporalAdjuster);
    
        System.out.println("=================== next, previous ============================");
    
        // next:如果当天是周五,返回下一个周五
        // nextOrSame:如果当天是周五,返回当天
        temporalAdjuster = TemporalAdjusters.next(DayOfWeek.FRIDAY);
        this.adjustDateTime("下一个周五", temporalAdjuster);
    
        temporalAdjuster = TemporalAdjusters.nextOrSame(DayOfWeek.FRIDAY);
        this.adjustDateTime("下一个周五", temporalAdjuster);
    
        // previous:如果当天是周五,返回上一个周五
        // previousOrSame:如果当天是周五,返回当天
        temporalAdjuster = TemporalAdjusters.previous(DayOfWeek.FRIDAY);
        this.adjustDateTime("上一个周五", temporalAdjuster);
    
        temporalAdjuster = TemporalAdjusters.previousOrSame(DayOfWeek.FRIDAY);
        this.adjustDateTime("上一个周五", temporalAdjuster);
    
        System.out.println("=================== dayOfWeekInMonth ============================");
    
        temporalAdjuster = TemporalAdjusters.dayOfWeekInMonth(3, DayOfWeek.SUNDAY);
        this.adjustDateTime("当月的第三个星期日", temporalAdjuster);
    
        System.out.println("=================== ofDateAdjuster ============================");
    
        temporalAdjuster = TemporalAdjusters.ofDateAdjuster(localDate -> localDate.minusDays(1));
        this.adjustDateTime("昨天", temporalAdjuster);
    }
    
    private void adjustDateTime(String desc, TemporalAdjuster temporalAdjuster) {
        LocalDateTime localDateTime = LocalDateTime.now();
        LocalDateTime with = localDateTime.with(temporalAdjuster);
        System.out.println(desc + ":" + with);
    }
    

    DateTimeFormatter

    用于格式化日期时间

    private void testDateTimeFormatter() {
        System.out.println("=================== testDateTimeFormatter ============================");
    
        DateTimeFormatter dateTimeFormatter = null;
    
        System.out.println(",=================== ofLocalizedDateTime ============================");
    
        // FormatStyle.FULL 带时区信息,不能用于 LocalDateTime
        dateTimeFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL);
        this.formatDateTime("ofLocalizedDateTime(FormatStyle.FULL):", dateTimeFormatter);
    
        dateTimeFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG);
        this.formatDateTime("ofLocalizedDateTime(FormatStyle.LONG):", dateTimeFormatter);
    
        dateTimeFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM);
        this.formatDateTime("ofLocalizedDateTime(FormatStyle.MEDIUM):", dateTimeFormatter);
    
        dateTimeFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT);
        this.formatDateTime("ofLocalizedDateTime(FormatStyle.SHORT):", dateTimeFormatter);
    
    
        System.out.println(",=================== ofPattern ============================");
    
        dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy MM dd");
        this.formatDateTime("ofPattern("yyyy MM dd"):", dateTimeFormatter);
    
        System.out.println(",=================== 静态常量 DateTimeFormatter ============================");
    
        dateTimeFormatter = DateTimeFormatter.BASIC_ISO_DATE;
        this.formatDateTime("BASIC_ISO_DATE:", dateTimeFormatter);
    
        dateTimeFormatter = DateTimeFormatter.ISO_DATE_TIME;
        this.formatDateTime("ISO_DATE_TIME:", dateTimeFormatter);
    
    
    }
    
    private void formatDateTime(String desc, DateTimeFormatter dateTimeFormatter) {
        ZonedDateTime zonedDateTime = ZonedDateTime.now();
        String format = zonedDateTime.format(dateTimeFormatter);
        System.out.println(desc + ":" + format);
    }
    

    与 java.util.Date 的相互转换

    private void testConvert() {
        System.out.println("=================== testConvert ============================");
    
        System.out.println(",=================== LocalDateTime 转 java.util.Date ============================");
    
        LocalDateTime localDateTime = LocalDateTime.now();
        System.out.println("localDateTime:" + localDateTime);
        Instant instant = localDateTime.atZone(ZoneId.systemDefault()).toInstant();
        Date fromDate = Date.from(instant);
        System.out.println("fromDate:" + fromDate);
    
        System.out.println(",=================== java.util.Date 转 LocalDateTime ============================");
        Date date = new Date();
        System.out.println("date:" + date);
        Instant toInstant = date.toInstant();
        LocalDateTime ofLocalDateTime = LocalDateTime.ofInstant(toInstant, ZoneId.systemDefault());
        System.out.println("ofLocalDateTime:" + ofLocalDateTime);
    }
    

    参考资料

  • 相关阅读:
    rabbitmqctl常用命令-3
    Count and Say
    Spiral Matrix II
    Minimum Path Sum
    Plus One
    Rotate Image
    Permutations
    Search a 2D Matrix
    Binary Tree Level Order Traversal II
    Binary Tree Level Order Traversal
  • 原文地址:https://www.cnblogs.com/huangwenjie/p/12109833.html
走看看 - 开发者的网上家园