旧版日期时间代码

在 Java SE 8 发行版之前,Java 日期和时间机制由java.util.Datejava.util.Calendarjava.util.TimeZone类及其子类(如java.util.GregorianCalendar)提供。这些类有几个缺点,包括:

  • Calendar类的 Importing 类型不安全。

  • 由于这些类是可变的,因此无法在多线程应用程序中使用它们。

  • 由于异常的月份数和缺乏类型安全性,应用程序代码中的错误很常见。

与旧版代码的互操作性

也许您有使用java\.util日期和时间类的旧代码,并且您想利用java\.time功能,而对代码的更改最少。

JDK 8 版本中添加了几种方法,允许在java\.utiljava\.time对象之间进行转换:

下面的示例将Calendar实例转换为ZonedDateTime实例。请注意,必须提供一个timezone才能从Instant转换为ZonedDateTime

Calendar now = Calendar.getInstance();
ZonedDateTime zdt = ZonedDateTime.ofInstant(now.toInstant(), ZoneId.systemDefault()));

以下示例显示了DateInstant之间的转换:

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

将 java.util 日期和时间功能 Map 到 java.time

由于日期和时间的 Java 实现已在 Java SE 8 发行版中进行了完全重新设计,因此您不能将一种方法交换为另一种方法。如果要使用java\.time软件包提供的丰富功能,最简单的解决方案是使用上一部分中列出的toInstanttoZonedDateTime方法。但是,如果您不想使用该方法或不足以满足您的需求,则必须重写日期时间代码。

Overview页上介绍的表格是开始评估哪些java\.time类满足您的需求的好地方。

这两个 API 之间没有一对一的 Map 对应关系,但是下表让您大致了解java\.util日期和时间类中的哪些功能 Map 到java\.time API。

java.util Functionalityjava.time Functionality注解
java\.util\.Datejava\.time\.InstantInstantDate类相似。每节课:

-表示时间轴(UTC)上的瞬时时间点
-保持与timezone无关的时间
-表示为纪元(自 1970-01-01T00:00:00Z)加上纳秒
Date\.from\(Instant\)Date\.toInstant\(\)方法允许在这些类之间进行转换。
java\.util\.GregorianCalendarjava\.time\.ZonedDateTimeZonedDateTime类是GregorianCalendar的替代。它提供以下类似功能。
人类时间表示如下:
LocalDate:年,月,日
LocalTime:小时,分钟,秒,纳秒
ZoneId:timezone
ZoneOffset:当前距格林尼治标准时间的offset量
GregorianCalendar\.from\(ZonedDateTime\)GregorianCalendar\.to\(ZonedDateTime\)方法有助于这些类之间的转换。
java\.util\.TimeZonejava\.time\.ZoneIdjava\.time\.ZoneOffsetZoneId类指定timezone标识符,并可以访问每个timezone使用的规则。 ZoneOffset类仅指定与 Greenwich/ UTC 的offset量。有关更多信息,请参见timezone和offset类
GregorianCalendar,日期设置为1970\-01\-01java\.time\.LocalTimeGregorianCalendar实例中的日期设置为 1970-01-01 以使用时间分量的代码可以替换为LocalTime的实例。
GregorianCalendar,时间设置为00:00\.java\.time\.LocalDateGregorianCalendar实例中将时间设置为 00:00 以使用日期组件的代码可以由LocalDate实例替换。 (这种GregorianCalendar方法存在缺陷,因为由于向夏时制的过渡,在某些国家/地区每年一次都不会发生午夜.)

日期和时间格式

尽管java\.time\.format\.DateTimeFormatter提供了用于格式化日期和时间值的强大机制,但是您也可以将java\.time基于时间的类直接用于java\.util\.FormatterString\.format,并使用与java\.util日期和时间类相同的基于 Pattern 的格式。