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

参考资料

原文地址:https://www.cnblogs.com/huangwenjie/p/12109833.html

时间: 2024-10-07 10:17:47

20191227 Java8 日期时间API的相关文章

Java8 日期时间API

使用Java8,新的日期时间API引入覆盖旧的日期时间API的以下缺点. 非线程安全 - java.util.Date不是线程安全的,因此开发者必须在使用日期处理并发性问题.新的日期时间API是不可变的,并且没有setter方法. 设计不佳 - 默认的开始日期从1900年,开始每月从1天从0开始,所以没有统一.不直接使用方法操作日期.新的API提供了这样操作实用方法. 困难的时区处理 - 开发人员必须编写大量的代码来处理时区的问题.新的API设计开发保持特定领域设计. JAVA8引入了java.

Java日期时间API系列11-----Jdk8中java.time包中的新的日期时间API类,使用java8日期时间API重写农历LunarDate

通过Java日期时间API系列7-----Jdk8中java.time包中的新的日期时间API类的优点,java8具有很多优点,现在网上查到的农历转换工具类都是基于jdk7及以前的类写的,下面使用java新的日期时间API重写农历LunarDate. package com.xkzhangsan.time; import java.time.Instant; import java.time.LocalDate; import java.time.LocalDateTime; import ja

[转] Java8 日期/时间(Date Time)API指南

[From] http://www.importnew.com/14140.html Java 8日期/时间( Date/Time)API是开发人员最受追捧的变化之一,Java从一开始就没有对日期时间处理的一致性方法,因此日期/时间API也是除Java核心API以外另一项倍受欢迎的内容. 为什么我们需要新的Java日期/时间API? 在开始研究Java 8日期/时间API之前,让我们先来看一下为什么我们需要这样一个新的API.在Java中,现有的与日期和时间相关的类存在诸多问题,其中有: Jav

Java 8 新特性:Java 类库的新特性之日期时间API (Date/Time API ) ——诺诺&quot;涂鸦&quot;记忆

----------   诺诺学习技术交流博客.期待与您交流!    ---------- 详情请查看:http://blog.csdn.net/sun_promise  日期时间API (Date/Time API ) 1.Java8之前java.util.Date和Calendar类的弊端 1)最开始的时候,Date既要承载日期信息,又要做日期之间的转换,还要做不同日期格式的显示,职责较繁杂(不遵守单一职责). 后来从JDK 1.1 开始,这三项职责分开了: 使用Calendar类实现日期和

全面解析Java日期时间API

时区 GMT(Greenwich Mean Time):格林尼治时间,格林尼治标准时间的正午是指当太阳横穿格林尼治子午线时(也就是在格林尼治上空最高点时)的时间. UTC(Universal Time Coordinated):统一协调时间,其以原子时秒长为基础,在时刻上尽量接近于格林尼治标准时间,标准 UTC 时间格式 yyyy-MM-dd'T'HH:mm:ss.SSSXXX. 格林尼治时间已经不再被作为标准时间使用,UTC 是最主要的世界时间标准. Java提供了获取当前时间的方法 Syst

Java日期时间API系列7-----Jdk8中java.time包中的新的日期时间API类的特点

1.不变性 新的日期/时间API中,所有的类都是不可变的,这对多线程环境有好处. 比如:LocalDateTime 2.关注点分离 新的API将人可读的日期时间和机器时间(unix timestamp)明确分离,它为日期(Date).时间(Time).日期时间(DateTime).时间戳(unix timestamp)以及时区定义了不同的类. 不同时间分解成了各个类,比如:LocalDate, LocalTime, LocalDateTime, Instant,Year,Month,YearMo

Java日期时间API系列8-----Jdk8中java.time包中的新的日期时间API类的LocalDate源码分析

目录 0.前言 1.TemporalAccessor源码 2.Temporal源码 3.TemporalAdjuster源码 4.ChronoLocalDate源码 5.LocalDate源码 6.总结 0.前言 通过前面Java日期时间API系列6-----Jdk8中java.time包中的新的日期时间API类中主要的类关系简图如下: 可以看出主要的LocalDate, LocalTime, LocalDateTime, Instant都是实现相同的接口,这里以LocalDate为例分析jav

Java日期时间API系列17-----Jdk8中java.time包中的新的日期时间API类,java日期计算4,2个日期对比,获取相差年月日部分属性和相差总的天时分秒毫秒纳秒等

通过Java日期时间API系列9-----Jdk8中java.time包中的新的日期时间API类的Period和Duration的区别 ,可以看出java8设计非常好,新增了Period和Duration类,专用于对比2个时间场景: Period,可以获取2个时间相差的年月日的属性. Duration,可以获取2个时间相差总的天时分秒毫秒纳秒. 下面应用: /** * 获取2个日期的相差年月天的年数部分 * @param startInclusive * @param endExclusive

Java 8 日期时间 API

Java 8 日期时间 API Java 8通过发布新的Date-Time API (JSR 310)来进一步加强对日期与时间的处理. 在旧版的 Java 中,日期时间 API 存在诸多问题,其中有: 非线程安全 ? java.util.Date 是非线程安全的,所有的日期类都是可变的,这是Java日期类最大的问题之一. 设计很差 ? Java的日期/时间类的定义并不一致,在java.util和java.sql的包中都有日期类,此外用于格式化和解析的类在java.text包中定义.java.ut