# 旧版日期 - 时间码

> 原文： [https://docs.oracle.com/javase/tutorial/datetime/iso/legacy.html](https://docs.oracle.com/javase/tutorial/datetime/iso/legacy.html)

在 Java SE 8 发布之前，Java 日期和时间机制由 [`java.util.Date`](https://docs.oracle.com/javase/8/docs/api/java/util/Date.html) ， [`java.util.Calendar`](https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html) 和 [`java.util.TimeZone`](https://docs.oracle.com/javase/8/docs/api/java/util/TimeZone.html) 类提供，以及它们的子类，例如 [`java.util.GregorianCalendar`](https://docs.oracle.com/javase/8/docs/api/java/util/GregorianCalendar.html)。这些类有几个缺点，包括：

*   `日历`类不是类型安全的。
*   因为类是可变的，所以它们不能用于多线程应用程序。
*   应用程序代码中的错误很常见，因为数月的数量异常且缺乏类型安全性。

## 与旧版代码的互操作性

也许您有遗留代码使用 `java.util` 日期和时间类，并且您希望利用 `java.time` 功能，只需对代码进行最少的更改。

添加到 JDK 8 版本的是几种允许在 `java.util` 和 `java.time` 对象之间进行转换的方法：

*   [`Calendar.toInstant（）`](https://docs.oracle.com/javase/8/docs/api/java/util/Calendar.html#toInstant--) 将 `Calendar` 对象转换为 `Instant` 。
*   [`GregorianCalendar.toZonedDateTime（）`](https://docs.oracle.com/javase/8/docs/api/java/util/GregorianCalendar.html#toZonedDateTime--) 将 `GregorianCalendar` 实例转换为 `ZonedDateTime` 。
*   [`GregorianCalendar.from（ZonedDateTime）`](https://docs.oracle.com/javase/8/docs/api/java/util/GregorianCalendar.html#from-java.time.ZonedDateTime-) 使用来自 `ZonedDateTime` 实例的默认语言环境创建 `GregorianCalendar` 对象。
*   [`Date.from（即时）`](https://docs.oracle.com/javase/8/docs/api/java/util/Date.html#from-java.time.Instant-) 从 `Instant` 创建 `Date` 对象。
*   [`Date.toInstant（）`](https://docs.oracle.com/javase/8/docs/api/java/util/Date.html#toInstant--) 将 `Date` 对象转换为 `Instant` 。
*   [`TimeZone.toZoneId（）`](https://docs.oracle.com/javase/8/docs/api/java/util/TimeZone.html#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();

```

## 将 java.util 日期和时间功能映射到 java.time

由于日期和时间的 Java 实现已在 Java SE 8 发行版中完全重新设计，因此您无法将一种方法替换为另一种方法。如果您想使用 `java.time` 软件包提供的丰富功能，最简单的解决方案是使用上一节中列出的 `toInstant` 或 `toZonedDateTime` 方法。但是，如果您不想使用该方法或者它不足以满足您的需求，那么您必须重写日期时间代码。

在[概述](overview.html)页面上介绍的表是开始评估哪些 `java.time` 类满足您需求的好地方。

两个 API 之间没有一对一的映射关系，但是下表让您大致了解 `java.util` 日期和时间类中哪些功能映射到 `java。时间` API。

| java.util 功能 | java.time 功能 | 评论 |
| --- | --- | --- |
| `java.util.Date` | `java.time.Instant` | `Instant` 和 `Date` 类相似。每个类：
- 表示时间轴上的瞬时时间点（UTC）
- 保持与时区无关的时间
- 表示为纪元秒（自 1970-01-01T00：00 起） ：00Z）加纳秒
`Date.from（Instant）`和 `Date.toInstant（）`方法允许在这些类之间进行转换。 |
| `java.util.GregorianCalendar` | `java.time.ZonedDateTime` | `ZonedDateTime` 类是 `GregorianCalendar` 的替代品。它提供以下类似功能。
人体时间表示如下：
`LocalDate` ：年，月，日
`LocalTime` ：小时，分钟，秒，纳秒
`ZoneId` ：时区
`ZoneOffset` ：当前偏离 GMT
`GregorianCalendar.from（ZonedDateTime）`和 `GregorianCalendar.to（ZonedDateTime）`方法促进这些类之间的转换。 |
| `java.util.TimeZone` | `java.time.ZoneId` 或 `java.time.ZoneOffset` | `ZoneId` 类指定时区标识符，并且可以访问每个时区使用的规则。 `ZoneOffset` 类仅指定格林威治/ UTC 的偏移量。有关更多信息，请参阅[时区和偏移类](timezones.html)。 |
| `GregorianCalendar` ，日期设为 `1970-01-01` | `java.time.LocalTime` | 在 `GregorianCalendar` 实例中将日期设置为 1970-01-01 以便使用时间组件的代码可以替换为 `LocalTime` 的实例。 |
| `GregorianCalendar` ，时间设置为 `00:00。` | `java.time.LocalDate` | 为了使用日期组件，在 `GregorianCalendar` 实例中将时间设置为 00:00 的代码可以用 `LocalDate` 的实例替换。 （这 `GregorianCalendar` 的方法存在缺陷，因为由于过渡到夏令时，一些国家每年都不会出现午夜。） |

## 日期和时间格式

虽然 `java.time.format.DateTimeFormatter` 提供了一种强大的日期和时间值格式化机制，但您也可以直接使用 `java.time` 基于时间的类与 `java .util.Formatter` 和 `String.format` ，使用与 `java.util` 日期和时间类相同的基于模式的格式。