旧版日期时间代码
在 Java SE 8 版本之前,Java 日期和时间机制由 java.util.Date、java.util.Calendar 和 java.util.TimeZone 类及其子类(如 java.util.GregorianCalendar)提供。这些类存在一些缺点,包括
Calendar类不是类型安全的。- 由于这些类是可变的,因此不能在多线程应用程序中使用它们。
- 由于月份编号不寻常以及缺乏类型安全性,应用程序代码中的错误很常见。
与旧版代码的互操作性
也许您有使用 java.util 日期和时间类的旧版代码,并且您希望利用 java.time 功能,同时对代码进行最少的更改。
JDK 8 版本中添加了一些方法,允许在 java.util 和 java.time 对象之间进行转换
Calendar.toInstant()将Calendar对象转换为Instant。GregorianCalendar.toZonedDateTime()将GregorianCalendar实例转换为ZonedDateTime。GregorianCalendar.from(ZonedDateTime)使用默认区域设置从ZonedDateTime实例创建一个GregorianCalendar对象。Date.from(Instant)从Instant创建一个Date对象。Date.toInstant()将Date对象转换为Instant。TimeZone.toZoneId()将TimeZone对象转换为ZoneId。
以下示例将 Calendar 实例转换为 ZonedDateTime 实例。请注意,必须提供时区才能从 Instant 转换为 ZonedDateTime
Calendar now = Calendar.getInstance();
ZonedDateTime zdt = ZonedDateTime.ofInstant(now.toInstant(), ZoneId.systemDefault()));
以下示例显示了 Date 和 Instant 之间的转换
Instant inst = date.toInstant();
Date newDate = Date.from(inst);
以下示例从 GregorianCalendar 转换为 ZonedDateTime,然后从 ZonedDateTime 转换为 GregorianCalendar。其他基于时间的类是使用 ZonedDateTime 实例创建的
GregorianCalendar cal = ...;
TimeZone tz = cal.getTimeZone();
int tzoffset = cal.get(Calendar.ZONE_OFFSET);
ZonedDateTime zdt = cal.toZonedDateTime();
GregorianCalendar newCal = GregorianCalendar.from(zdt);
LocalDateTime ldt = zdt.toLocalDateTime();
LocalDate date = zdt.toLocalDate();
LocalTime time = zdt.toLocalTime();
将旧版日期和时间功能映射到日期时间 API
由于 Java 中的日期和时间实现已在 Java SE 8 版本中完全重新设计,因此您无法将一种方法替换为另一种方法。如果您想使用 java.time 包提供的丰富功能,最简单的解决方案是使用上一节中列出的 toInstant() 或 toZonedDateTime() 方法。但是,如果您不想使用这种方法,或者它不足以满足您的需求,那么您必须重写日期时间代码。
在 概述 页面上介绍的 表格 是一个很好的起点,可以评估哪些 java.time 类满足您的需求。
这两个 API 之间没有一对一的映射对应关系,但下表让您大致了解 java.util 日期和时间类中的哪些功能映射到 java.time API。
旧版 Date 和 Instant 之间的对应关系
- 表示时间轴上的一个瞬时时间点(UTC)
- 保存与时区无关的时间
- 表示为纪元秒(自 1970-01-01T00:00:00Z 以来)加上纳秒
Date.from(Instant) 和 Date.toInstant() 方法允许在这些类之间进行转换。
GregorianCalendar 和 ZonedDateTime 之间的对应关系
ZonedDateTime 类是 GregorianCalendar 的替代品。它提供了以下类似的功能。人类时间表示如下
LocalDate:年、月、日LocalTime:时、分、秒、纳秒ZoneId:时区ZoneOffset:当前与 GMT 的偏移量
GregorianCalendar.from(ZonedDateTime) 和 GregorianCalendar.toZonedDateTime() 方法便于在这些类之间进行转换。
旧版 TimeZone 和 ZoneId 或 ZoneOffset 之间的对应关系
ZoneId 类指定一个时区标识符,并可以访问每个时区使用的规则。 ZoneOffset 类仅指定与格林威治/UTC 的偏移量。有关更多信息,请参见 时区和偏移量类。
日期设置为 1970-01-01 的 GregorianCalendar 与 LocalTime 之间的对应关系
将日期设置为 1970-01-01 的 GregorianCalendar 实例以使用时间组件的代码可以替换为 LocalTime 的实例。
时间设置为 00:00 的 GregorianCalendar 与 LocalDate 之间的对应关系
将时间设置为 00:00 的 GregorianCalendar 实例以使用日期组件的代码可以替换为 LocalDate 的实例。(这种 GregorianCalendar 方法存在缺陷,因为由于夏令时的转换,一些国家/地区每年都会出现午夜。)
日期和时间格式化
尽管java.time.format.DateTimeFormatter 提供了强大的日期和时间值格式化机制,但您也可以直接使用java.time 基于时间类的java.util.Formatter 和String.format(),使用与java.util 日期和时间类相同的基于模式的格式化。
上次更新: 2022 年 1 月 27 日