Java8 java.util.Date 到 java.time.ZonedDateTime 的转换

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25376242/
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-08-11 00:15:20  来源:igfitidea点击:

Java8 java.util.Date conversion to java.time.ZonedDateTime

javadatedatetimejava-8java-time

提问by Ironluca

I am getting the following exception while trying to convert java.util.Dateto java.time.LocalDate.

尝试转换java.util.Datejava.time.LocalDate.

java.time.DateTimeException: Unable to obtain ZonedDateTime from TemporalAccessor: 2014-08-19T05:28:16.768Z of type java.time.Instant

The code is as follow:

代码如下:

public static Date getNearestQuarterStartDate(Date calculateFromDate){

    int[] quaterStartMonths={1,4,7,10};     
    Date startDate=null;

    ZonedDateTime d=ZonedDateTime.from(calculateFromDate.toInstant());
    int frmDateMonth=d.getMonth().getValue();

Is there something wrong in the way I am using the ZonedDateTimeclass?

我使用ZonedDateTime课程的方式有问题吗?

As per documentation, this should convert a java.util.Dateobject to ZonedDateTime. The date format above is standard Date?

根据文档,这应该将java.util.Date对象转换为ZonedDateTime. 上面的日期格式是标准日期?

Do I have to fallback on Joda time?

我必须退回到 Joda 时间吗?

If someone could provide some suggestion, it would be great.

如果有人可以提供一些建议,那就太好了。

采纳答案by JB Nizet

To transform an Instantto a ZonedDateTime, ZonedDateTimeoffers the method ZonedDateTime.ofInstant(Instant, ZoneId). So

将 an 转换Instant为 a ZonedDateTimeZonedDateTime提供了方法ZonedDateTime.ofInstant(Instant, ZoneId)。所以

So, assuming you want a ZonedDateTimein the default timezone, your code should be

所以,假设你想要一个ZonedDateTime在默认时区,你的代码应该是

ZonedDateTime d = ZonedDateTime.ofInstant(calculateFromDate.toInstant(),
                                          ZoneId.systemDefault());

回答by assylias

To obtain a ZonedDateTime from a Date you can use:

要从日期获取 ZonedDateTime,您可以使用:

calculateFromDate.toInstant().atZone(ZoneId.systemDefault())

You can then call the toLocalDatemethod if you need a LocalDate. See also: Convert java.util.Date to java.time.LocalDate

toLocalDate如果需要 LocalDate,则可以调用该方法。另请参阅:将 java.util.Date 转换为 java.time.LocalDate

回答by TheArchitect

The answer didn't work for me on Java 10 storing util.Date in UTC.

答案对我在 Java 10 中以 UTC 存储 util.Date 不起作用。

Date.toInstant() seems to convert the EpochMillis into the local time zone of the server.

Date.toInstant() 似乎将 EpochMillis 转换为服务器的本地时区。

ZDT.ofInstant(instant, zoneId) and instant.atZone(zoneId) seem to just tag on a TZ on the instant, but it's already messed up with.

ZDT.ofInstant(instant, zoneId) 和 instant.atZone(zoneId) 似乎只是在瞬间标记 TZ,但它已经搞砸了。

I couldn't find a way to prevent Date.toInstant() from messing with the UTC time with the system time zone.

我找不到防止 Date.toInstant() 将 UTC 时间与系统时区混淆的方法。

The only way I found to work around this was to go through the sql.Timestamp class:

我发现解决这个问题的唯一方法是通过 sql.Timestamp 类:

new java.sql.Timestamp(date.getTime()).toLocalDateTime()
                                      .atZone(ZoneId.of("UTC"))
                                      .withZoneSameInstant(desiredTZ)

回答by Basil Bourque

The Answer by assyliasand the Answer by JB Nizetare both correct:

通过assylias答案按JB Nizet答案都是正确的:

  1. Call the new conversion method added to the legacy class, java.util.Date::toInstant.
  2. Call Instant::atZone, passing a ZoneId, resulting in a ZonedDateTime.
  1. 调用添加到遗留类中的新转换方法,java.util.Date::toInstant
  2. 调用Instant::atZone,传递 a ZoneId,产生 a ZonedDateTime

enter image description here

在此处输入图片说明

But your code example is aimed at quarters. For that, read on.

但是您的代码示例是针对宿舍的。为此,请继续阅读。

Quarters

宿舍

No need to roll-your-own handling of quarters. Use a class already written and tested.

无需自行处理宿舍。使用已经编写和测试过的类。

org.threeten.extra.YearQuarter

org.threeten.extra.YearQuarter

The java.timeclasses are extended by the ThreeTen-Extraproject. Among the many handy classes provided in that library you will find Quarterand YearQuarter.

java.time类由扩展ThreeTen-EXTRA项目。在该库中提供的许多方便的类中,您会发现QuarterYearQuarter.

First get your ZonedDateTime.

首先得到你的ZonedDateTime.

ZonedId z = ZoneID.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = myJavaUtilDate.toInstant().atZone( z ) ;

Determine the year-quarter for that particular date.

确定该特定日期的年季度。

YearQuarter yq = YearQuarter.from( zdt ) ;

Next we need the start date of that quarter.

接下来我们需要该季度的开始日期。

LocalDate quarterStart = yq.atDay( 1 ) ;

While I do not necessarily recommend doing so, you could use a single line of code rather than implement a method.

虽然我不一定建议这样做,但您可以使用单行代码而不是实现方法。

LocalDate quarterStart =                    // Represent a date-only, without time-of-day and without time zone.
    YearQuarter                             // Represent a specific quarter using the ThreeTen-Extra class `org.threeten.extra.YearQuarter`. 
    .from(                                  // Given a moment, determine its year-quarter.
        myJavaUtilDate                      // Terrible legacy class `java.util.Date` represents a moment in UTC as a count of milliseconds since the epoch of 1970-01-01T00:00:00Z. Avoid using this class if at all possible.
        .toInstant()                        // New method on old class to convert from legacy to modern. `Instant` represents a moment in UTC as a count of nanoseconds since the epoch of 1970-01-01T00:00:00Z. 
        .atZone(                            // Adjust from UTC to the wall-clock time used by the people of a particular region (a time zone). Same moment, same point on the timeline, different wall-clock time.
            ZoneID.of( "Africa/Tunis" )     // Specify a time zone using proper `Continent/Region` format. Never use 2-4 letter pseudo-zone such as `PST` or `EST` or `IST`. 
        )                                   // Returns a `ZonedDateTime` object.
    )                                       // Returns a `YearQuarter` object.
    .atDay( 1 )                             // Returns a `LocalDate` object, the first day of the quarter. 
;

By the way, if you can phase out your use of java.util.Datealtogether, do so. It is a terribleclass, along with its siblings such as Calendar. Use Dateonly where you must, when you are interfacing with old code not yet updated to java.time.

顺便说一句,如果您可以java.util.Date完全淘汰您的使用,请这样做。这是一个可怕的类,以及它的兄弟姐妹,例如Calendar. Date当您与尚未更新为java.time 的旧代码交互时,仅在必须的地方使用。



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

The ThreeTen-Extraproject extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

ThreeTen-额外项目与其他类扩展java.time。该项目是未来可能添加到 java.time 的试验场。你可能在这里找到一些有用的类,比如IntervalYearWeekYearQuarter,和更多