一. 为什么要使用JDK8的新版日期API
1. 日期差值问题
1). 使用老版本的Date来计算两个日期之间相差的天数:
将两个日期转换成毫秒数(Date的getTime()方法返回的是对应日期距离1970.01.01的毫秒值),相减之后,将差值再转换成“天”的单位。
2). 使用新版本的日期API来计算两个日期之间相差的天数:
ChronoUnit.DAYS.between方法。
发现使用老版本的API存在计算误差。
2.线程安全问题
SimpleDateFormater是线程不安全的,因为它有一个成员变量Calendar calendar.
二. Date-Time API中的基本类使用
1. 常用类
(1)Instant:
Instant类对事件轴上的单一瞬时点建模,可以用于记录应用程序中的事件时间戳,在日期类型转换中,可以使用该类作为中间类来完成类型转换。
(2)Duration:
Duration类表示秒或者纳秒时间间隔,适合处理时间间隔短,但需要较高精确度的时间间隔计算。
(3)Period:
Period类表示一段时间的年、月、日。
(4)LocalDate:
LocalDate类是一个不可变的日期时间对象,表示日期,通常被视为年月日。
(5)LocalTime:
LocalTime是一个不可变的日期时间对象,表示时间,通常被看作是时分秒,精确到纳秒。
(6)LocalDateTime:
LocalDateTime是一个不可变的日期时间对象,表示日期时间,通常视为年月日时分秒。
(7)ZonedDateTime:
ZonedDateTime是一个不可变的、具有时区的日期时间对象,此类存储所有日期和时间字段,精确到纳秒,时区为区域偏移量,用于处理模糊的本地日期时间。
2. now方法
Date-Time API中所有的类均声称不可变实例,它们是线程安全的,并且这些类不提供公共构造方法,需要采用工厂方法进行实例化。
Instant封装的是格林威治时间,也就是标准时间;LocalXXX封装的默认是本地的时间;ZonedDateTime是带时区的时间,默认也是本地所在时区的时区时间。
Year, YearMonth, MonthDay三个类,及其now方法。
3. of方法
LocalDateTime可以使用of方法传入LocalDate和LocalTime作为参数。
4. LocalDateTime添加时区信息
(1)通过ZoneId的getAvailablefZoneIds方法可以获取封装了600个时区的set集合。
(2)获取当前系统的默认时区:ZoneId.systemDefault()
(3)给LocalDateTime添加时区信息:ZonedDateTime time = localDateTime.atZone(ZoneId.of("Asia/Shanghai"))
(4)查看当前时区的时间在另外一个时区对应的事件:
zonedDateTime.withZoneSameInstant(ZoneId.of("Asia/Tokyo"))
5. 根据现有实例创建日期和时间
(1)plus方法
1)minus方法其实就是plus方法的入参改成负数;
2)两个特殊的方法:
plus(long amountToAdd, TemporalUnit unit)
plus(TemporalAmount amountToAdd)
a)距离当前日期2年零3月零4天的日期是哪天?
TemporalAmount的实现类Period,now.plus(Period.of(2, 3, 4))
b)ChronoUnit中封装了很多枚举,如半天,10年...
now.plus(1, ChronoUnit.HALF_DAYS)
(2)with方法
1)withXXX: 用于将某个具体的时间单位定位到指定的数值
2)with(TemporalField field, long newValue)
TemporalField的实现类ChronoField定义了很多枚举值供使用,例如ChronoField.DAY_OF_MONTH
3)with(TemporalAdjuster adjuster)
使用时间调节器TemporalAdjuster,例如now.with(TemporalAdjusters.firstDayOfMonth())
4)自定义TemporalAdjuster
假如员工的发薪日是每个月的15号,但是如果发薪日是周末,则调整为上一个周五。
public class PayDayAdjuster implements TemporalAdjuster {
@Override
public Temporal adjustInto(Temporal temporal) {
LocalDate payDate = LocalDate.from(temporal);
LocalDate newPayDate = payDate.withDayOfMonth(15);
if(newPayDate.getDayOfWeek() == DayOfWeek.SUNDAY || newPayDate.getDayOfWeek() == DayOfWeek.SATORDAY){
newPayDate = newPayDate.with(TemporalAdjusters.previous(DayOfWeek.FRIDAY));
}
return newPayDate;
}
}
5)TemporalQuery应用
6. Date和LocalDate的转换
(1)Instant作为中介
(2)Date转成sql Date,再转成LocalDate
(3)Calendar转成LocalDate
7. 时间的格式化
(1)DateTimeFormatter