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
Java8 java.util.Date conversion to java.time.ZonedDateTime
提问by Ironluca
I am getting the following exception while trying to convert java.util.Date
to java.time.LocalDate
.
尝试转换java.util.Date
为java.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 ZonedDateTime
class?
我使用ZonedDateTime
课程的方式有问题吗?
As per documentation, this should convert a java.util.Date
object 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 Instant
to a ZonedDateTime
, ZonedDateTime
offers the method ZonedDateTime.ofInstant(Instant, ZoneId)
. So
将 an 转换Instant
为 a ZonedDateTime
,ZonedDateTime
提供了方法ZonedDateTime.ofInstant(Instant, ZoneId)
。所以
So, assuming you want a ZonedDateTime
in 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 toLocalDate
method 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答案都是正确的:
- Call the new conversion method added to the legacy class,
java.util.Date::toInstant
. - Call
Instant::atZone
, passing aZoneId
, resulting in aZonedDateTime
.
- 调用添加到遗留类中的新转换方法,
java.util.Date::toInstant
。 - 调用
Instant::atZone
,传递 aZoneId
,产生 aZonedDateTime
。
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 Quarter
and YearQuarter
.
该java.time类由扩展ThreeTen-EXTRA项目。在该库中提供的许多方便的类中,您会发现Quarter
和YearQuarter
.
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.Date
altogether, do so. It is a terribleclass, along with its siblings such as Calendar
. Use Date
only 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 类?
- 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 。
- 安卓
- java.time类的更高版本的 Android 捆绑实现。
- 对于早期的 Android(<26),ThreeTenABP项目采用了ThreeTen-Backport(上面提到过)。请参阅如何使用ThreeTenABP ...。
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 的试验场。你可能在这里找到一些有用的类,比如Interval
,YearWeek
,YearQuarter
,和更多。