将 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 01:42:31  来源:igfitidea点击:

Convert java.util.Date to what “java.time” type?

javadatedatetimejava-time

提问by Basil Bourque

I have a java.util.Dateobject, or a java.util.Calendarobject. 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.Dateor java.util.Calendar?

我听说我们现在应该使用 java.time 类型来处理我们的大部分业务逻辑。当使用尚未针对 java.time 更新的旧代码时,我需要能够来回转换。什么类型映射到java.util.Datejava.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.SimpleTextFormatand 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.Datejava.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.Dateobject 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 中的几种类型中的任何一种。下面分别讨论。请注意,旧的日期时间类中添加了一些新方法以方便转换。

diagram of converting from java.util.Date/.Calendar through ZonedDateTime (or OffsetDateTime) to the three <code>Local…</code>types

从 java.util.Date/.Calendar 到 ZonedDateTime(或 OffsetDateTime)到三种 <code>Local…</code>类型的转换图

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, Instantwill be used frequently. Pass around Instantobjects, 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.Dateto Instant

java.util.DateInstant

Given that both Instantand java.util.Dateare a moment on the timeline in UTC, we can easily move from a java.util.Dateto an Instant. The old class has gained a new method, java.util.Date::toInstant.

鉴于Instantjava.util.Date都是 UTC 时间线上的一个时刻,我们可以轻松地从 a 移动java.util.DateInstant。旧类获得了一个新方法,java.util.Date::toInstant.

Instant instant = myUtilDate.toInstant();

You can go the other direction, from an Instantto a java.util.Date. But you may lose information about the fractional second. An Instanttracks 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 Instantto Datemeans 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. 在这个例子中,从InstanttoDate意味着截断456789.

java.util.Date myUtilDate = java.util.Date.from(instant);

From java.util.Calendarto Instant

java.util.CalendarInstant

What about a java.util.Calendarinstead of a java.util.Date? Internal to the Calendarobject 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.0ZInstant

Instant instant = myUtilCalendar.toInstant() ;

From java.util.GregorianCalendarto ZonedDateTime

java.util.GregorianCalendarZonedDateTime

Even better, if your java.util.Calendarobject is actually a java.util.GregorianCalendaryou 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 Calendarto the concrete classof GregorianCalendar. Then call the toZonedDateTimeand frommethods to go back and forth.

垂头丧气接口Calendar具体类GregorianCalendar。然后调用toZonedDateTimefrom方法来回。

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 Instantwe 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 ZoneOffsetclass represents this idea. The result is an OffsetDateTimeobject.

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 OffsetDateTimeto a java.util.Date. Extract an Instantand 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 ZoneIdgets you a ZonedDateTimeobject. Use a proper time zone name(continent/region). Never use the 3-4 letter abbreviations commonly seen such as ESTor ISTas 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 ZonedDateTimeto a java.util.Date. Extract an Instantand 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 ZonedDateTimemay 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.LocalDateobject.

有时您可能需要一个只有日期的值,没有时间和时区。为此,请使用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 LocalDatedoes 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 LocalDateto 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 LocalTimeclass. As discussed above with LocalDate, we need a time zone to determine a LocalTimeeven though the LocalTimeobject does not contain (does not ‘remember') that time zone. So, again, we go through a ZonedDateTimeobject obtained from an Instantas seen above.

在极少数情况下,您可能只需要一个没有日期和时区的时间。这个概念由LocalTime类表示。如上所述LocalDate,我们需要一个时区来确定 ,LocalTime即使LocalTime对象不包含(不“记住”)该时区。因此,我们再次浏览ZonedDateTimeInstant上面看到的从 an 获得的对象。

LocalTime localTime = zdt.toLocalTime();

LocalDateTime

LocalDateTime

As with the other two Local…types, a LocalDateTimehas 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();

enter image description here

在此处输入图片说明



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 类?