旧版日期时间代码
在 Java SE 8 发行版之前,Java 日期和时间机制由java.util.Date,java.util.Calendar和java.util.TimeZone类及其子类(如java.util.GregorianCalendar)提供。这些类有几个缺点,包括:
-
Calendar
类的 Importing 类型不安全。 -
由于这些类是可变的,因此无法在多线程应用程序中使用它们。
-
由于异常的月份数和缺乏类型安全性,应用程序代码中的错误很常见。
与旧版代码的互操作性
也许您有使用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
实例。请注意,必须提供一个timezone才能从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 日期和时间功能 Map 到 java.time
由于日期和时间的 Java 实现已在 Java SE 8 发行版中进行了完全重新设计,因此您不能将一种方法交换为另一种方法。如果要使用java\.time
软件包提供的丰富功能,最简单的解决方案是使用上一部分中列出的toInstant
或toZonedDateTime
方法。但是,如果您不想使用该方法或不足以满足您的需求,则必须重写日期时间代码。
Overview页上介绍的表格是开始评估哪些java\.time
类满足您的需求的好地方。
这两个 API 之间没有一对一的 Map 对应关系,但是下表让您大致了解java\.util
日期和时间类中的哪些功能 Map 到java\.time
API。
java.util Functionality | java.time Functionality | 注解 |
---|---|---|
java\.util\.Date | java\.time\.Instant | Instant 和Date 类相似。每节课: |
-表示时间轴(UTC)上的瞬时时间点 -保持与timezone无关的时间 -表示为纪元(自 1970-01-01T00:00:00Z)加上纳秒 Date\.from\(Instant\) 和Date\.toInstant\(\) 方法允许在这些类之间进行转换。 | ||
java\.util\.GregorianCalendar | java\.time\.ZonedDateTime | ZonedDateTime 类是GregorianCalendar 的替代。它提供以下类似功能。人类时间表示如下: LocalDate :年,月,日LocalTime :小时,分钟,秒,纳秒ZoneId :timezoneZoneOffset :当前距格林尼治标准时间的offset量GregorianCalendar\.from\(ZonedDateTime\) 和GregorianCalendar\.to\(ZonedDateTime\) 方法有助于这些类之间的转换。 |
java\.util\.TimeZone | java\.time\.ZoneId 或java\.time\.ZoneOffset | ZoneId 类指定timezone标识符,并可以访问每个timezone使用的规则。 ZoneOffset 类仅指定与 Greenwich/ UTC 的offset量。有关更多信息,请参见timezone和offset类。 |
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
日期和时间类相同的基于 Pattern 的格式。