文章目录
1、为什么会引入新的API
在旧版的 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类,但他们同样存在上述所有的问题。
JDK 1.8 中的新日期和时间API解决了旧API中的许多问题,并且借鉴了 Joda Time API 。新的java.time 包涵盖了所有处理日期,时间,日期/时间,时区,时刻(instants),过程(during)与时钟(clock)的操作。
2、java.time 包
JDK 1.8 引入了五个新的日期和时间API包,如下:
2.1、java.time
这是新的Java日期/时间API的基础包,它是基于ISO-8601标准的API,所有的主要基础类都是这个包的一部分,如:LocalDate, LocalTime, LocalDateTime, Instant, Period, Duration等等。所有这些类都是不可变的和线程安全的,在绝大多数情况下,这些类能够有效地处理一些公共的需求。
2.2、java.time.chrono
java.time.chrono 包含日历API。 这适用于需要使用本地化日历的应用程序。 为Hijrah,Japanese,Minguo和ThaiBuddhist日历提供支持。我们可以扩展AbstractChronology类来创建自己的日历系统。
2.3、java.time.format
java.time.format 包含能够格式化和解析日期时间对象的API,可以通过各种方式创建格式化程序,包括常量,模式,本地化样式和构建器。 格式化程序是不可变的和线程安全的。
2.4、java.time.temporal
java.time.temporal包含用于访问日期时间字段和单位的API。单位是可衡量的,例如年,月和小时。例如,表达“2小时后”使用小时单位。例如,年的月份(month-of-year),星期几(day-of-week)和小时(hour-of-day )都是字段。如果需要,可以通过应用程序扩展受支持的单元和字段集。
2.5、java.time.zone
java.time.zone包含处理时区的API。 提供有关每个时区规则的详细信息。
3、用于表示本地日期和时区的新类
3.1、java.time.LocalDate
LocalDate 类表示日期。 没有时间或时区的表示。是一个不可变的类,它表示默认格式(yyyy-MM-dd)的日期,我们可以使用now()方法得到当前时间,也可以提供输入年份、月份和日期的输入参数来创建一个LocalDate实例。该类为now()方法提供了重载方法,我们可以传入ZoneId来获得指定时区的日期,该类提供与java.sql.Date相同的功能.
3.1.1、创建当前日期和特定日期
LocalDate类提供以下API以创建当前日期和特定日期。
- static LocalDate now() - 在默认时区中从系统时钟获取当前日期。
- static LocalDate now(Clock clock) - 从指定的时钟获取当前日期。
- static LocalDate now(ZoneId zone) - 从指定时区的系统时钟获取当前日期。
- static LocalDate of(int year, int month, int dayOfMonth) - 从年,月和日获得LocalDate的实例。
- static LocalDate of(int year, Month month, int dayOfMonth) - 从年,月和日获得LocalDate的实例。
/**
* 创建当前日期和特定日期
*/
public static void createLocalDate() {
// 在默认时区中从系统时钟获取当前日期。
LocalDate localDate = LocalDate.now();
System.out.println("LocalDate.now():" + localDate);
// 从指定的时钟获取当前日期。
LocalDate localDate1 = LocalDate.now(Clock.systemDefaultZone());
System.out.println("LocalDate.now(Clock.systemDefaultZone()):" + localDate1);
// 从指定时区的系统时钟获取当前日期。
LocalDate localDate3 = LocalDate.now(Clock.system(ZoneId.of("Indian/Cocos")));
System.out.println("LocalDate.now(Clock.system(ZoneId.of(\"Indian/Cocos\"))):" + localDate3);
// 从年,月和日获得LocalDate的实例。
LocalDate localDate2 = LocalDate.of(1991, Month.MARCH, 24);
System.out.println("LocalDate.of(1991, Month.MARCH, 24):" + localDate2);
// 从年,月和日获得LocalDate的实例。
LocalDate localDate5 = LocalDate.of(1991, 12, 24);
System.out.println("LocalDate.of(1991, 12, 24):" + localDate5);
}
输出:
LocalDate.now():2019-07-28
LocalDate.now(Clock.systemDefaultZone()):2019-07-28
LocalDate.now(Clock.system(ZoneId.of("Indian/Cocos"))):2019-07-28
LocalDate.of(1991, Month.MARCH, 24):1991-03-24
LocalDate.of(1991, 12, 24):1991-12-24
3.1.2、从LocalDate获取年,月,日
LocalDate类提供以下API以分别获得年,月和日。
- Month getMonth() - 使用Month枚举获取月份字段。
- int getMonthValue() - 获取1到12之间的月份字段。
- int getYear() - 获取年份字段。
- int getDayOfMonth() - 获取日期字段。
- DayOfWeek getDayOfWeek() - 获取星期几字段,即枚举DayOfWeek。
- int getDayOfYear() - 获取日期字段。
/**
* 从LocalDate获取年,月,日
*/
public static void getYearMonthDay() {
LocalDate localDate = LocalDate.now();
System.out.println("Year : " + localDate.getYear());
System.out.println("Month : " + localDate.getMonth().getValue());
System.out.println("Day of Month : " + localDate.getDayOfMonth());
System.out.println("Day of Week : " + localDate.getDayOfWeek());
System.out.println("Day of Year : " + localDate.getDayOfYear());
}
输出:
Year : 2019
Month : 7
Day of Month : 28
Day of Week : SUNDAY
Day of Year : 209
3.1.3、向LocalDate添加或减去天,月,周和年
LocalDate类提供以下API以向LocalDate添加或减去Days,Months,Weeks和Years。
- LocalDate plusDays(long daysToAdd) - 返回此LocalDate的副本,并添加指定的天数。
- LocalDate plusMonths(long monthsToAdd) - 返回此LocalDate的副本,并添加指定的月数。
- LocalDate plusWeeks(long weeksToAdd) - 返回此LocalDate的副本,并添加指定的周数。
- LocalDate plusYears(long yearsToAdd) - 返回此LocalDate的副本,并添加指定的年数。
/**
* 向LocalDate添加或减去天,月,周和年
*/
public static void addOrSubstractUsingLocalDate() {
LocalDate localDate = LocalDate.now();
// LocalDate 添加指定年月日的方法
System.out.println("添加 days : " + localDate.plusDays(5));
System.out.println("添加 months : " + localDate.plusMonths(15));
System.out.println("添加 weeks : " + localDate.plusWeeks(45));
System.out.println("添加 years : " + localDate.plusYears(5));
// LocalDate 减去指定年月日的方法
System.out.println("减去 days : " + localDate.minusDays(5));
System.out.println("减去 months : " + localDate.minusMonths(15));
System.out.println("减去 weeks : " + localDate.minusWeeks(45));
System.out.println("减去 years : " + localDate.minusYears(5));
}
输出:
添加 days : 2019-08-02
添加 months : 2020-10-28
添加 weeks : 2020-06-07
添加 years : 2024-07-28
减去 days : 2019-07-23
减去 months : 2018-04-28
减去 weeks : 2018-09-16
减去 years : 2014-07-28
3.1.4、比较LocalDate对象
LocalDate类提供以下API来比较Java中的LocalDate对象。
- boolean isAfter(ChronoLocalDate other) - 检查此日期是否在指定日期之后。
- boolean isBefore(ChronoLocalDate other) - 检查此日期是否在指定日期之前。
- boolean isEqual(ChronoLocalDate other) - 检查此日期是否等于指定日期。
/**
* 比较LocalDate对象
*/
public static void compareLocalDate() {
LocalDate localDate1 = LocalDate.now();
LocalDate localDate2 = LocalDate.of(2017, Month.MAY, 14);
LocalDate localDate3 = LocalDate.of(2016, Month.MAY, 15);
// isEqual()
if (localDate1.isEqual(localDate2)) {
System.out.println("localDate1 等于 localDate2");
} else {
System.out.println("localDate1 不等于 localDate2");
}
// ifAfter()
if (localDate2.isAfter(localDate3)) {
System.out.println("localDate2 大于 localDate3");
}
// isBefore()
if (localDate3.isBefore(localDate1)) {
System.out.println("localDate3 小于 localDate1");
}
}
输出:
localDate1 不等于 localDate2
localDate2 大于 localDate3
localDate3 小于 localDate1
3.1.5、从LocalDate获取月或年的天数
LocalDate类提供以下API,以从LocalDate获取Month或Year的天数。
- int lengthOfMonth() - 返回此日期表示的月份长度。
- int lengthOfYear() - 返回此日期表示的年份长度。
/**
* 从LocalDate获取月或年的天数
*/
public static void getDaysFromMonthAndYear() {
LocalDate localDate1 = LocalDate.of(2017, Month.JANUARY, 1);
LocalDat