将 java.util.Date 转换为什么“java.time”类型?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/36639154/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Convert java.util.Date to what “java.time” type?
提问by Basil Bourque
I have a java.util.Date
object, or a java.util.Calendar
object. How do I convert that to the right type in java.timeframework?
我有一个java.util.Date
对象,或者一个java.util.Calendar
对象。如何在java.time框架中将其转换为正确的类型?
I have heard that we should now be doing the bulk of our business logic with java.time types. When working with old code not yet updated for java.time I need to be able to convert back and forth. What types map to java.util.Date
or java.util.Calendar
?
我听说我们现在应该使用 java.time 类型来处理我们的大部分业务逻辑。当使用尚未针对 java.time 更新的旧代码时,我需要能够来回转换。什么类型映射到java.util.Date
或java.util.Calendar
?
回答by Basil Bourque
Yes, you definitely should be using the java.timeframework whenever possible.
是的,您绝对应该尽可能使用java.time框架。
Avoid old date-time classes
避免旧的日期时间课程
The old date-time classes including java.util.Date
, java.util.Calendar
, and java.text.SimpleTextFormat
and such have proven to be poorly designed, confusing, and troublesome. Avoid them where you can. But when you must interoperate with these old types, you can convert between old and new.
旧的日期,时间类,包括java.util.Date
,java.util.Calendar
以及java.text.SimpleTextFormat
和这种已被证明是设计不当,令人费解,麻烦。尽可能避免它们。但是当您必须与这些旧类型进行互操作时,您可以在新旧之间进行转换。
Read on for a basic introduction, somewhat over-simplified, to orient you in moving back-and-forth between the old and new date-time classes.
继续阅读基本介绍,有些过于简化,以引导您在新旧日期时间类之间来回移动。
java.time
时间
The java.timeframework is defined by JSR 310, inspired by the highly-successful Joda-Timelibrary, and extended by the ThreeTen-Extraproject. The bulk of the functionality was back-ported to Java 6 & 7 in the ThreeTen-Backportproject, with a further adaptation for Android in the ThreeTenABPproject.
该java.time框架由定义JSR 310,由大获成功的启发乔达时库,并通过扩展ThreeTen-EXTRA项目。的功能的大部分被后移植到Java 6和7在ThreeTen-反向移植项目,在为Android进一步适配ThreeTenABP项目。
What java.time type matches java.util.Date
? Well, a java.util.Date
object basically represents a moment on the timeline in UTC, a combination of a date and a time-of-day. We can translate that to any of several types in java.time. Each is discussed below. Note that some new methods have been added to the old date-time classes to facilitate conversions.
什么 java.time 类型匹配java.util.Date
?嗯,一个java.util.Date
对象基本上代表UTC时间线上的一个时刻,日期和时间的组合。我们可以将其转换为 java.time 中的几种类型中的任何一种。下面分别讨论。请注意,旧的日期时间类中添加了一些新方法以方便转换。
Instant
Instant
The building block in java.time is an Instant
, a moment on the timeline in UTCwith a resolution of nanoseconds.
java.time 中的构建块是UTCInstant
时间线上的一个时刻,分辨率为纳秒。
Generally you should do much of your business logic in UTC. In such work, Instant
will be used frequently. Pass around Instant
objects, applying a time zone only for presentation to a user. When you doneed to apply an offset or time zone, use the types covered further below.
通常,您应该在 UTC 中完成大部分业务逻辑。在这样的工作中,Instant
会经常用到。传递Instant
对象,应用时区仅用于向用户展示。当您确实需要应用偏移量或时区时,请使用下面进一步介绍的类型。
From java.util.Date
to Instant
从java.util.Date
到Instant
Given that both Instant
and java.util.Date
are a moment on the timeline in UTC, we can easily move from a java.util.Date
to an Instant
. The old class has gained a new method, java.util.Date::toInstant
.
鉴于Instant
和java.util.Date
都是 UTC 时间线上的一个时刻,我们可以轻松地从 a 移动java.util.Date
到Instant
。旧类获得了一个新方法,java.util.Date::toInstant
.
Instant instant = myUtilDate.toInstant();
You can go the other direction, from an Instant
to a java.util.Date
. But you may lose information about the fractional second. An Instant
tracks nanoseconds, for up to nine digits after the decimal place such as 2016-01-23T12:34:56.123456789Z
. Both java.util.Date & .Calendar are limited to milliseconds, for up to three digits after the decimal place such as 2016-01-23T12:34:56.123Z
. In this example going from Instant
to Date
means truncation of the 456789
.
你可以往另一个方向,从 anInstant
到 a java.util.Date
。但是您可能会丢失有关小数秒的信息。AnInstant
跟踪纳秒,小数点后最多九位数字,例如2016-01-23T12:34:56.123456789Z
. java.util.Date 和 .Calendar 都限制为毫秒,小数点后最多三位,例如2016-01-23T12:34:56.123Z
. 在这个例子中,从Instant
toDate
意味着截断456789
.
java.util.Date myUtilDate = java.util.Date.from(instant);
From java.util.Calendar
to Instant
从java.util.Calendar
到Instant
What about a java.util.Calendar
instead of a java.util.Date
? Internal to the Calendar
object the date-time is tracked as a count of millisecondsfrom the epoch reference date-timeof the first moment of 1970 in UTC (1970-01-01T00:00:00.0Z
). So this value can be converted easily to an Instant
.
ajava.util.Calendar
而不是 ajava.util.Date
呢?在Calendar
对象内部,日期时间被跟踪为从UTC ( )中 1970 年第一个时刻的纪元参考日期时间开始的毫秒计数。所以这个值可以很容易地转换为.1970-01-01T00:00:00.0Z
Instant
Instant instant = myUtilCalendar.toInstant() ;
From java.util.GregorianCalendar
to ZonedDateTime
从java.util.GregorianCalendar
到ZonedDateTime
Even better, if your java.util.Calendar
object is actually a java.util.GregorianCalendar
you can easily go directly to a ZonedDateTime
. This approach has the benefit of retaining the embedded time zone information.
更好的是,如果您的java.util.Calendar
对象实际上是 ajava.util.GregorianCalendar
您可以轻松地直接转到 a ZonedDateTime
。这种方法的好处是可以保留嵌入的时区信息。
Downcastfrom the interfaceof Calendar
to the concrete classof GregorianCalendar
. Then call the toZonedDateTime
and from
methods to go back and forth.
垂头丧气从接口的Calendar
到具体类的GregorianCalendar
。然后调用toZonedDateTime
和from
方法来回。
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`
}
Going the other direction…
走向另一个方向……
java.util.Calendar myUtilCalendar = java.util.GregorianCalendar.from(zdt); // Produces an instant of `GregorianCalendar` which implements `Calendar` interface.
As discussed above, beware that you may be losing information about the fraction of a second. The nanosecondsin the java.time type (ZonedDateTime
) gets truncated to millisecondsin the .Calendar
/.GregorianCalendar
.
如上所述,请注意您可能会丢失有关几分之一秒的信息。在纳秒在java.time类型(ZonedDateTime
)被截断,以毫秒为单位的.Calendar
/ .GregorianCalendar
。
OffsetDateTime
OffsetDateTime
From an Instant
we can apply an offset-from-UTCto move into a wall-clock timefor some locality. An offset is a number of hours, and possibly minutes and seconds, ahead of UTC(eastward) or behind UTC (westward). The ZoneOffset
class represents this idea. The result is an OffsetDateTime
object.
从Instant
我们可以应用的偏移从-UTC搬进挂钟时间对于一些局部性。偏移量是UTC(向东)之前或 UTC(向西)之前的小时数,可能还有几分钟和几秒。这个ZoneOffset
类代表了这个想法。结果是一个OffsetDateTime
对象。
ZoneOffset offset = ZoneOffset.of("-04:00");
OffsetDateTime odt = OffsetDateTime.ofInstant(instant, zoneOffset);
You can go the other direction, from an OffsetDateTime
to a java.util.Date
. Extract an Instant
and then proceed as we saw in code above. As discussed above, any nanosecondsget truncated to milliseconds(data loss).
你可以往另一个方向,从 anOffsetDateTime
到 a java.util.Date
。提取一个Instant
,然后按照我们在上面的代码中看到的那样继续。如上所述,任何纳秒都会被截断为毫秒(数据丢失)。
java.util.Date myUtilDate = java.util.Date.from(odt.toInstant());
ZonedDateTime
ZonedDateTime
Better yet, apply a full time zone. A time zone is an offset plusrules for handling anomalies such as Daylight Saving Time (DST).
更好的是,应用一个完整的时区。时区是偏移量加上用于处理夏令时 (DST)等异常的规则。
Applying a ZoneId
gets you a ZonedDateTime
object. Use a proper time zone name(continent/region). Never use the 3-4 letter abbreviations commonly seen such as EST
or IST
as they are neither standardized nor unique.
应用 aZoneId
会让你得到一个ZonedDateTime
对象。使用正确的时区名称(大陆/地区)。切勿使用常见的 3-4 个字母缩写,例如EST
或 ,IST
因为它们既不标准化也不独特。
ZoneId zoneId = ZoneId.of("America/Montreal");
ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, zoneId);
You can go the other direction, from an ZonedDateTime
to a java.util.Date
. Extract an Instant
and then proceed as we saw in code above. As discussed above, any nanosecondsget truncated to milliseconds(data loss).
你可以往另一个方向,从 anZonedDateTime
到 a java.util.Date
。提取一个Instant
,然后按照我们在上面的代码中看到的那样继续。如上所述,任何纳秒都会被截断为毫秒(数据丢失)。
java.util.Date myUtilDate = java.util.Date.from( zdt.toInstant() );
And we saw further above that a ZonedDateTime
may be converted to a GregorianCalendar
.
我们在上面进一步看到 aZonedDateTime
可以转换为 a GregorianCalendar
。
LocalDate
LocalDate
Sometimes you may want a date-only value, without time-of-day and without time zone. For that, use a java.time.LocalDate
object.
有时您可能需要一个只有日期的值,没有时间和时区。为此,请使用java.time.LocalDate
对象。
See this Question for more discussion, Convert java.util.Date to java.time.LocalDate, especially this Answerwritten by the main man behind the invention of both Joda-Time and java.time.
请参阅此问题以获取更多讨论,将 java.util.Date 转换为 java.time.LocalDate,尤其是由 Joda-Time 和 java.time 的发明背后的主要人员编写的这个答案。
The key is to go through a ZonedDateTime
(as generated in code above). We need a time zone to determine a date. The date varies around the world, with a new day dawning earlier in the east. For example, after midnight in Paris is a new day while still “yesterday” in Montréal. So while a LocalDate
does not containa time zone, a time zone is required to determinea LocalDate
.
关键是要经过一个ZonedDateTime
(如上面代码中生成的)。我们需要一个时区来确定日期。世界各地的日期各不相同,东部将迎来新的一天。例如,在巴黎午夜过后是新的一天,而在蒙特利尔仍然是“昨天”。因此,虽然 aLocalDate
不包含时区,但需要时区来确定a LocalDate
。
LocalDate localDate = zdt.toLocalDate();
Converting in the other direction from LocalDate
to a date-time means inventing a time-of-day. You can choose any time-of-day that makes sense in your business scenario. For most people, the first moment of the day makes sense. You may be tempted to hard code that first moment as the time 00:00:00.0
. In some time zones, that time may not be valid as the first moment because of Daylight Saving Time (DST)or other anomalies. So let java.time determine the correct time with a call to atStartOfDay
.
从另一个方向转换LocalDate
为日期时间意味着发明一天中的时间。您可以选择在您的业务场景中有意义的任何一天中的时间。对于大多数人来说,一天中的第一刻是有意义的。您可能会想将第一时刻硬编码为时间00:00:00.0
。在某些时区,由于夏令时 (DST)或其他异常情况,该时间可能无法作为第一时刻有效。因此,让 java.time 通过调用来确定正确的时间atStartOfDay
。
ZonedDateTime zdt = localDate.atStartOfDay(zoneId);
LocalTime
LocalTime
On rare occasion you may want only a time-of-day without a date and without a time zone. This concept is represented by the LocalTime
class. As discussed above with LocalDate
, we need a time zone to determine a LocalTime
even though the LocalTime
object does not contain (does not ‘remember') that time zone. So, again, we go through a ZonedDateTime
object obtained from an Instant
as seen above.
在极少数情况下,您可能只需要一个没有日期和时区的时间。这个概念由LocalTime
类表示。如上所述LocalDate
,我们需要一个时区来确定 ,LocalTime
即使LocalTime
对象不包含(不“记住”)该时区。因此,我们再次浏览ZonedDateTime
从Instant
上面看到的从 an 获得的对象。
LocalTime localTime = zdt.toLocalTime();
LocalDateTime
LocalDateTime
As with the other two Local…
types, a LocalDateTime
has no time zone nor offset assigned. As such you may rarely usethis. It gives you a rough idea of a date-time but is nota point on the timeline. Use this if you mean some general date and some time that might be applied to a time zone.
与其他两种Local…
类型一样, aLocalDateTime
没有分配时区和偏移量。因此,您可能很少使用它。它让您大致了解日期时间,但不是时间线上的一个点。如果您的意思是某个可能适用于某个时区的一般日期和时间,请使用此选项。
For example, “Christmas starts this year” would be 2016-12-25T00:00:00.0
. Note the lack of any offset or time zone in that textual representation of a LocalDateTime
. Christmas starts sooner in Delhi India than it does in Paris France, and later still in Montréal Québec Canada. Applying each of those areas' time zone would yield a different moment on the timeline.
例如,“今年圣诞节开始”将是2016-12-25T00:00:00.0
. 请注意,在 a 的文本表示中缺少任何偏移量或时区LocalDateTime
。圣诞节在印度德里比在法国巴黎更早开始,而在加拿大魁北克蒙特利尔则更晚。应用每个区域的时区会在时间线上产生不同的时刻。
LocalDateTime ldt = zdt.toLocalDateTime();
About java.time
关于java.time
The java.timeframework is built into Java 8 and later. These classes supplant the troublesome old legacydate-time classes such as java.util.Date
, Calendar
, & SimpleDateFormat
.
该java.time框架是建立在Java 8和更高版本。这些类取代了麻烦的旧的遗留日期时间类,例如java.util.Date
, Calendar
, & SimpleDateFormat
。
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
要了解更多信息,请参阅Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。规范是JSR 310。
The Joda-Timeproject, now in maintenance mode, advises migration to the java.timeclasses.
现在处于维护模式的Joda-Time项目建议迁移到java.time类。
You may exchange java.timeobjects directly with your database. Use a JDBC drivercompliant with JDBC 4.2or later. No need for strings, no need for java.sql.*
classes.
您可以直接与数据库交换java.time对象。使用符合JDBC 4.2或更高版本的JDBC 驱动程序。不需要字符串,不需要类。java.sql.*
Where to obtain the java.time classes?
从哪里获得 java.time 类?
- Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
- Java 9 adds some minor features and fixes.
- Java SE 6and Java SE 7
- Most of the java.timefunctionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
- Android
- Later versions of Android bundle implementations of the java.timeclasses.
- For earlier Android (<26), the ThreeTenABPproject adapts ThreeTen-Backport(mentioned above). See How to use ThreeTenABP….
- Java SE 8、Java SE 9、Java SE 10、Java SE 11及更高版本 - 标准 Java API 的一部分,具有捆绑实现。
- Java 9 添加了一些小功能和修复。
- Java SE 6和Java SE 7
- 大多数java.time功能在ThreeTen-Backport 中被反向移植到 Java 6 & 7 。
- 安卓
- 更高版本的 Android 捆绑实现java.time类。
- 对于早期的 Android(<26),ThreeTenABP项目采用了ThreeTen-Backport(上面提到过)。请参阅如何使用ThreeTenABP ...。