我在尝试将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
代码如下:
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();
我使用ZonedDateTime
课程的方式有什么问题吗?
根据文档,这应该将java.util.Date
对象转换为ZonedDateTime
。上面的日期格式是标准日期?
我是否必须回到Joda时间?
如果有人可以提供一些建议,那就太好了。
为了将Instant
变换为ZonedDateTime
,ZonedDateTime
提供了方法ZonedDateTime.ofInstant(Instant, ZoneId)
。所以
因此,假设您需要在默认时区中使用ZonedDateTime
,那么您的代码应该是
ZonedDateTime d = ZonedDateTime.ofInstant(calculateFromDate.toInstant(),
ZoneId.systemDefault());
要从日期获取ZonedDateTime,您可以使用:
calculateFromDate.toInstant().atZone(ZoneId.systemDefault())
如果需要LocalDate,则可以调用toLocalDate
方法。另见:Convert java.util.Date to java.time.LocalDate
Answer by assylias和Answer by JB Nizet都是正确的:
java.util.Date::toInstant
的新转换方法。Instant::atZone
,通过一个ZoneId
,产生一个ZonedDateTime
。但是你的代码示例针对的是季度。为此,请继续阅读。
无需自己处理宿舍。使用已经编写和测试的类。
org.threeten.extra.YearQuarter
java.time类由ThreeTen-Extra项目扩展。在该图书馆提供的许多便利课程中,你会发现Quarter
和YearQuarter
。
首先得到你的ZonedDateTime
。
ZonedId z = ZoneID.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = myJavaUtilDate.toInstant().atZone( z ) ;
确定该特定日期的年度。
YearQuarter yq = YearQuarter.from( zdt ) ;
接下来我们需要该季度的开始日期。
LocalDate quarterStart = yq.atDay( 1 ) ;
虽然我不一定建议这样做,但您可以使用单行代码而不是实现方法。
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.
;
顺便说一下,如果你可以完全逐步停止使用java.util.Date
,那就这样做吧。这是一个可怕的阶级,以及像Calendar
这样的兄弟姐妹。当您与尚未更新到java.time的旧代码连接时,请仅在必要时使用Date
。
java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,如java.util.Date
,Calendar
和SimpleDateFormat
。
要了解更多信息,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规格是JSR 310。
现在在Joda-Time的maintenance mode项目建议迁移到java.time班。
您可以直接与数据库交换java.time对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*
类。
从哪里获取java.time类?
ThreeTen-Extra项目使用其他类扩展了java.time。该项目是未来可能添加到java.time的试验场。你可能会在这里找到一些有用的类,如Interval
,YearWeek
,YearQuarter
和more。
在Java 10中存储util.Date的Java 10中,答案对我不起作用。
Date.toInstant()似乎将EpochMillis转换为服务器的本地时区。
ZDT.ofInstant(instant,zoneId)和instant.atZone(zoneId)似乎只是瞬间标记在TZ上,但它已经搞砸了。
我找不到阻止Date.toInstant()使用系统时区搞乱UTC时间的方法。
我找到解决这个问题的唯一方法是通过sql.Timestamp类:
new java.sql.Timestamp(date.getTime()).toLocalDateTime()
.atZone(ZoneId.of("UTC"))
.withZoneSameInstant(desiredTZ)