Date 类在 Java 面世之初就存在于标准库中,但从 Java 1.1 开始,Date 类的所有方法都被弃用
使用示例
// 获取当前时间,toString: Wed Jan 01 00:00:00 CST 2020
Date date = new Date();
// 对应的时间戳,long 类型
long stamp = d.getTime();
Java 1.1 推荐使用 Calendar 类处理时间
使用示例
// 获取 Calendar 实例,默认当前时间
Calendar calendar = Calendar.getInstance();
// 通过 setTime() 设置 Calendar 对象的时间
calendar.setTime(new Date());
// 通过 getTime() 获取对应的 Date 对象
Date date = calendar.getTime();
// 通过年/月/日/时/分/秒设置时间,month 由 0 开始
calendar.set(2020, 1, 1);
calendar.set(2020, 1, 1, 8, 30, 30);
// 通过 set(int field, int value) 设置时间字段
calendar.set(Calendar.MONTH, 0);
// 通过 get(int field) 获取对应时间字段
int month = calendar.get(Calendar.MONTH) + 1;
// 通过 after 和 before 方法比较 Calendar 对象的先后,返回布尔值
Calendar oldCalendar = Calendar.getInstance();
oldCalendar.set(2019, 1, 1, 8, 30, 30);
boolean after = calendar.after(oldCalendar);
时间计算困难
毫秒值与日期直接转换比较繁琐,通过毫秒值来计算时间差步骤较多
线程安全问题
SimpleDateFormat 类是线程不安全的,在多线程的情况下,全局共享一个SimpleDateFormat类中的Calendar对象可能会出现异常
因为 SimpleDateFormat 类 format 方法执行时使用一个 Calendar 类型成员变量报错时间,该变量被多个线程共享时就会出问题
Instant 类
Instant类对时间轴上的单一瞬时点建模,可以用于记录应用程序中的事件时间戳,之后学习的类型转换中,均可以使用Instant类作为中间类完成转换
Duration 类
Duration类表示秒或纳秒时间间隔,适合处理较短的时间,需要更高的精确性
Period类
Period类表示一段时间的年、月、日
LocalDate 类
LocalDate是一个不可变的日期时间对象,表示日期,通常被视为年-月-日
LocalTime 类
LocalTime是一个不可变的日期时间对象,代表一个时间,通常被看作是小时-秒,时间表示为纳秒精度
LocalDateTime 类
LocalDateTime类是一个不可变的日期时间对象,代表日期时间,通常被视为年-月-日-时-分-秒
ZonedDateTime 类
ZonedDateTime是具有时区的日期时间的不可变表示,此类存储所有日期和时间字段,精度为纳秒,时区为区域偏移量,用于处理模糊的本地日期时间
now 方法根据当前日期或时间创建实例
使用示例
// 使用 now 方法创建 Instant 的实例对象
Instant instantNow = Instant.now();
// 使用 now 方法创建 LocalDate 的实例对象
LocalDate localDateNow = LocalDate.now();
// 使用 now 方法创建 LocalTime 的实例对象
LocalTime localTimeNow = LocalTime.now();
// 使用 now 方法创建 LocalDateTime 的实例对象
LocalDateTime localDateTimeNow = LocalDateTime.now();
// 使用now方法创建 ZonedDateTime 的实例对象
ZonedDateTime zonedDateTimeNow = ZonedDateTime.now();
// 祖鲁时间(格林尼治时间 GMT /国际标准时间 UTC)
System.out.println("Instant:" + instantNow);
// 年-月-日 yy-MM-dd
System.out.println("LocalDate:" + localDateNow);
// 时:分:秒 HH:mm:ss
System.out.println("LocalTime:" + localTimeNow);
// 年-月-日T时:分:秒
System.out.println("LocalDateTime:" + localDateTimeNow);
// 年-月-日T时:分:秒+08:00[Asia/Shanghai] 表示时区
System.out.println("ZonedDateTime:" + zonedDateTimeNow);
/*
Instant:2020-11-26T08:12:23.426Z
LocalDate:2020-11-26
LocalTime:16:12:23.473
LocalDateTime:2020-11-26T16:12:23.473
ZonedDateTime:2020-11-26T16:12:23.473+08:00[Asia/Shanghai]
*/
time 包其他类也可以使用 now 方法更精准的获取某些信息
Year类(表示年)
YearMonth类(表示年月)
MonthDay类(表示月日)
of 方法根据给定的参数生成对应的日期/时间对象
使用示例
// 2018 年 8 月 8 日
LocalDate localDate = LocalDate.of(2018, 8, 8);
// 8 点 8 分 8 秒,秒为 0 或省略则 toString 不显示
LocalTime localTime = LocalTime.of(8, 8, 8);
// 2018 年 8 月 8 日 8 点 8 分 8 秒
LocalDateTime localDateTime = LocalDateTime.of(2018, 8, 8, 8, 8, 8);
System.out.println("localTime: " + localTime);
System.out.println("localDate: " + localDate);
System.out.println("localDateTime:" + localDateTime);
/*
localDate: 2018-08-08
localTime: 08:08:08
localDateTime:2018-08-08T08:08:08
*/
ZoneId 用于表示时区
ZoneId.getAvailableZoneIds 返回一个 set
ZoneId.of 传入表示时区的字符串返回时区对象
ZonedDateTime 设置时区
// 获取 LocalDateTime
LocalDateTime localDate = LocalDateTime.now();
// LocalDateTime atZone 返回 ZonedDateTime 对象
// 设置该 LocalDateTime 对象时区为上海
ZonedDateTime zonedDateTime = localDate.atZone(ZoneId.of("Asia/Shanghai"));
System.out.println(zonedDateTime);
// 获取时区为东京的对应时间
ZonedDateTime tokyoDateTime = zonedDateTime.withZoneSameInstant(ZoneId.of("Asia/Tokyo"));
System.out.println(tokyoDateTime);
/*
2020-11-26T16:54:31.692+08:00[Asia/Shanghai]
2020-11-26T17:54:31.692+09:00[Asia/Tokyo]
*/
Month 月份枚举
// 使用 Month 枚举获得月份
LocalDateTime localDate = LocalDateTime.of(2018, Month.AUGUST, 8, 8, 8);
注意老版本 Calendar 月份是从 0 开始,LocalDate/LocalDateTime 月份都是是从 1 开始
Month.of 方法
Month month = Month.of(12);
System.out.println(month);
// DECEMBER
LocalDate 的 plus 方法
LocalTime 的 plus 方法
plus(TemporalAmount amoutToadd)
TemporalAmount 是一个接口,Period 是其实现类,代表一段时间
LocalDateTime localDateTime = LocalDateTime.now();
// 1 年 2 个月 3 天
Period p = Period.of(1, 2, 3);
// 在 localDateTime 基础上加上 p 表示的一段时间
LocalDateTime dateTimeAfterPlus = localDateTime.plus(p);
plus(long amountToadd, TemporalUnit unit)
TemporalUnit是一个接口,ChronoUnit 是其实现类,封装了许多时间段
LocalDateTime localDateTime = LocalDateTime.now();
// 加 1 天
LocalDateTime localDateTime1 = localDateTime.plus(1, ChronoUnit.DAYS);
// 加 2 小时
LocalDateTime localDateTime2 = localDateTime.plus(2, ChronoUnit.HOURS);
with 方法可以直接对时间的某一项进行修改
with(TemporalField field, long newValue)
temporalField是一个接口,ChronoField 是其实现类,提供了许多日期字段的枚举
LocalDateTime localDateTime = LocalDateTime.of(2018, 8, 8, 8, 8, 8);
// 修改到 10 月
LocalDateTime localDateTimeModified = localDateTime.withMonth(10);
// 修改到 10 月
LocalDateTime localDateTimeModified = localDateTime.with(ChronoField.MONTH_OF_YEAR, 10);
with(TemporalAdjuster adjuster)
TemporalAdjuster 是一个函数式接口,可以自定义 TemporalAdjuster 实现类完成想要的修改
TemporalAdjusters 封装了许多方法,返回 TemporalAdjuster 的实现
TemporalAdjusters 的 next、previous 方法配合 DayOfWeek 枚举类,可以方便的获取下周或上周的某天
LocalDateTime localDateTime = LocalDateTime.of(2018, 8, 8, 8, 8, 8);
// 改为当月第一天
LocalDateTime localDateTime1 = localDateTime.with(TemporalAdjusters.firstDayOfMonth());
// 改为下个月第一天
LocalDateTime localDateTime2 = localDateTime.with(TemporalAdjusters.firstDayOfNextMonth());
// 自定义 TemporalAdjuster,改为当月倒数第二天
LocalDateTime localDateTime3 = localDateTime.with(new TemporalAdjuster() {
@Override
public Temporal adjustInto(Temporal temporal) {
return temporal.with(ChronoField.DAY_OF_MONTH, temporal.range(ChronoField.DAY_OF_MONTH).getMaximum() -1 );
}
});
// next、previous 方法配合 DayOfWeek 枚举类,如:下一个周五
LocalDateTime localDateTime4 = localDateTime.with(TemporalAdjusters.next(DayOfWeek.FRIDAY));
LocalDate、LocalTime 有一个 query 方法,用来进行对日期的查询
R query(TemporalQuery query) 是一个泛型方法,返回的数据是传入的泛型类的类型
TemporalQuery 是一个泛型接口,通过重写其 queryFrom(TemporalAccessor temporal) 方法,传入时间返回数据
LocalDate localDate = LocalDate.of(2018, 8, 8);
// 返回是否过了当年的劳动节
boolean isAfterLabour = localDate.query(new TemporalQuery<Boolean>() {
@Override
public Boolean queryFrom(TemporalAccessor temporal) {
LocalDate today = LocalDate.from(temporal);
LocalDate labour = LocalDate.of(today.getYear(), 5 ,1);
return today.isAfter(labour);
}
});
parse 方法是 LocalDate、LocalDateTime 的静态方法,将字符串转为时间或日期对象
format 是 LocalDate、LocalDateTime 的实例方法,用于格式化字符串
DateTimeFormatter 类封装了常用的格式作为静态变量,也可使用 ofPattern 方法自定义格式
// LocalDate.parse,默认解析 yyyy-MM-dd
LocalDate parsedDate1 = LocalDate.parse("2018-08-08");
// LocalDate.parse 指定格式
LocalDate parsedDate2 = LocalDate.parse("2018/11/1", DateTimeFormatter.ofPattern("yyyy/M/d"));
LocalDateTime localDateTime = LocalDateTime.of(2018,8,8,8,8,8);
// localDateTime 对象可以直接调用 format 方法进行格式化
// 2018-08-08
String s1 = localDateTime.format(DateTimeFormatter.ISO_DATE);
// 2018-08-08T08:08:08
String s2 = localDateTime.format(DateTimeFormatter.ISO_DATE_TIME);
// DateTimeFormatter.ofPattern 自定义格式 -> 2018.08.08
String s3 = localDateTime.format(DateTimeFormatter.ofPattern("yyyy.MM.dd"));