是的,你绝对应该尽可能地使用java.time框架。
避免旧的日期时间类
旧的日期时间类,包括java.util.Date
,java.util.Calendar
等,已被证明设计不佳,令人困惑和麻烦。尽可能避免使用它们。但是,当您必须与这些旧类型进行互操作时,您可以在新旧类型之间进行转换。java.text.SimpleDateFormat
请继续阅读基本介绍,有些过于简化,以指导您在旧日期时间类和新日期时间类之间来回移动。
java.time
java.time框架由JSR 310定义,灵感来自非常成功的Joda-Time库,并由ThreeTen-Extra项目扩展。在ThreeTen-Backport项目中,大部分功能被移植到Java 6和7,并在ThreeTenABP项目中进一步适应Android。
哪种 java.time 类型与 java.util.Date
匹配?好吧,对象基本上表示UTC时间轴上的一个时刻,即日期和时间的组合。我们可以将其转换为java.time中的几种类型中的任何一种。下面将逐一讨论。请注意,一些新方法已添加到旧的日期时间类中,以便于转换。java.util.Date
Instant
java.time中的构建块
是即时的,是UTC时间轴上的一个时刻,分辨率为纳秒。
通常,您应该在 UTC 中执行大部分业务逻辑。在这样的工作中,会经常使用。传递对象,应用时区仅用于向用户演示。当您确实需要应用偏移量或时区时,请使用下面进一步介绍的类型。Instant
Instant
从 到java.util.Date
Instant
鉴于两者都是 UTC 时间轴上的一个时刻,我们可以轻松地从 java.util.Date
移动到 .旧类获得了一个新方法,java.util.Date::toInstant
。Instant
java.util.Date
Instant
Instant instant = myUtilDate.toInstant();
您可以转到另一个方向,从 a 到 .但是您可能会丢失有关小数秒的信息。A 跟踪纳秒,在小数点后最多为九位,例如 .java.util.Date & .日历限制为毫秒,小数点后最多为三位,例如 .在此示例中,从 到 表示 截断 .Instant
java.util.Date
Instant
2016-01-23T12:34:56.123456789Z
2016-01-23T12:34:56.123Z
Instant
Date
456789
java.util.Date myUtilDate = java.util.Date.from(instant);
从 到java.util.Calendar
Instant
那么 java.util.Calendar
而不是 ?在对象内部,日期时间被跟踪为从 1970 年第一个时刻的 epoch 参考日期时间(UTC)开始的毫秒数()。因此,此值可以轻松转换为 .java.util.Date
Calendar
1970-01-01T00:00:00.0Z
Instant
Instant instant = myUtilCalendar.toInstant() ;
从 到java.util.GregorianCalendar
ZonedDateTime
更好的是,如果你的java.util.Calendar
对象实际上是一个java.util.GregorianCalendar,
你可以很容易地直接进入ZonedDateTime
。此方法具有保留嵌入的时区信息的优点。
从 的接口向下铸造到 的具体类 。然后调用 toZonedDateTime
和 from
方法来回切换。Calendar
GregorianCalendar
if (myUtilCalendar instanceof GregorianCalendar) {
GregorianCalendar gregCal = (GregorianCalendar) myUtilCalendar; // Downcasting from the interface to the concrete class.
ZonedDateTime zdt = gregCal.toZonedDateTime(); // Create `ZonedDateTime` with same time zone info found in the `GregorianCalendar`
}
向另一个方向走...
java.util.Calendar myUtilCalendar = java.util.GregorianCalendar.from(zdt); // Produces an instant of `GregorianCalendar` which implements `Calendar` interface.
如上所述,请注意,您可能会丢失有关几分之一秒的信息。java.time 类型 () 中的纳秒在 /中被截断为毫秒。ZonedDateTime
.Calendar
.GregorianCalendar
OffsetDateTime
从 一个,我们可以应用一个偏移量 UTC 来移动到某个位置的挂钟时间。偏移量是 UTC 之前(向东)或 UTC(向西)的小时数,可能为分钟和秒数。ZoneOffset
类表示此思想。结果是一个 OffsetDateTime
对象。Instant
ZoneOffset offset = ZoneOffset.of("-04:00");
OffsetDateTime odt = OffsetDateTime.ofInstant(instant, zoneOffset);
您可以转到另一个方向,从 a 到 .提取 一个,然后按照我们在上面的代码中看到的那样继续。如上所述,任何纳秒都会被截断为毫秒(数据丢失)。OffsetDateTime
java.util.Date
Instant
java.util.Date myUtilDate = java.util.Date.from(odt.toInstant());
ZonedDateTime
更好的是,应用完整的时区。时区是用于处理异常(如夏令时 (DST))的偏移量加规则。
应用 ZoneId
会获得一个 ZonedDateTime
对象。使用正确的时区名称(大洲/地区)。切勿使用常见的 3-4 个字母缩写,例如 或 因为它们既不标准化也不唯一。EST
IST
ZoneId zoneId = ZoneId.of("America/Montreal");
ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, zoneId);
您可以转到另一个方向,从 a 到 .提取 一个,然后按照我们在上面的代码中看到的那样继续。如上所述,任何纳秒都会被截断为毫秒(数据丢失)。ZonedDateTime
java.util.Date
Instant
java.util.Date myUtilDate = java.util.Date.from( zdt.toInstant() );
我们在上面进一步看到,a 可以转换为 .ZonedDateTime
GregorianCalendar
LocalDate
有时,您可能需要一个仅日期值,而不使用一天中的时间和时区。为此,请使用 java.time.LocalDate
对象。
有关更多讨论,请参阅此问题,将java.util.Date转换为java.time.LocalDate,特别是Joda-Time和java.time发明背后的主要人物撰写的答案。
关键是要通过一个(如上面的代码中生成的那样)。我们需要一个时区来确定日期。世界各地的日期各不相同,东部的新一天提前到来。例如,巴黎午夜过后是新的一天,而蒙特利尔仍然是“昨天”。因此,虽然 a 不包含时区,但需要时区来确定 .ZonedDateTime
LocalDate
LocalDate
LocalDate localDate = zdt.toLocalDate();
从另一个方向转换为日期时间意味着发明一天中的时间。您可以选择在业务方案中有意义的任何时间。对于大多数人来说,一天中的第一刻是有意义的。您可能会想在第一时间硬编码。在某些时区中,由于夏令时 (DST) 或其他异常,该时间可能作为第一个时刻无效。因此,让java.time通过调用atStartOfDay
来确定正确的时间。LocalDate
00:00:00.0
ZonedDateTime zdt = localDate.atStartOfDay(zoneId);
LocalTime
在极少数情况下,您可能只想要一个没有日期和时区的时间。此概念由 LocalTime
类表示。如上文所述,我们需要一个时区来确定一个,即使该对象不包含(不“记住”)该时区。因此,我们再次浏览从上面看到的对象。LocalDate
LocalTime
LocalTime
ZonedDateTime
Instant
LocalTime localTime = zdt.toLocalTime();
LocalDateTime
与其他两种类型一样,LocalDateTime
没有分配时区或偏移量。因此,您可能很少使用它。它为您提供了日期时间的粗略概念,但不是时间轴上的点。如果您指的是可能应用于某个时区的某个常规日期和某个时间,请使用此选项。Local…
例如,“今年圣诞节开始”将是 。请注意,在 的文本表示形式中缺少任何偏移量或时区。圣诞节在印度德里比在法国巴黎更早开始,后来在加拿大魁北克省蒙特利尔开始得更早。应用每个区域的时区将在时间轴上产生不同的时刻。2016-12-25T00:00:00.0
LocalDateTime
LocalDateTime ldt = zdt.toLocalDateTime();
关于 java.time
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧旧日期时间类,如java.util.Date
,Calendar
和SimpleDateFormat
。
要了解更多信息,请参阅 Oracle 教程。搜索 Stack Overflow 以获取许多示例和解释。规格是JSR 310。
Joda-Time 项目现在处于维护模式,建议迁移到 java.time 类。
您可以直接与数据库交换 java.time 对象。使用符合 JDBC 4.2 或更高版本的 JDBC 驱动程序。不需要字符串,不需要类。java.sql.*
从哪里获取 java.time 类?