将Java日期转换为OffsetDateTime

时间:2018-10-03 17:56:57

标签: java spring java-time java-date

我的eta值是OffsetDateTime,而ScheduledDate是日期类型。如果未设置eta,我想回到日期。

日期的一个示例是Tue Jul 21 10:32:28 PDT 2020。为了转换这个,我尝试做: OffsetDateTime.ofInstant(dto.getScheduledTime().ToInstant(), ZoneOffset.UTC) 由于Date已包含PDT,因此感觉utc偏移是错误的,但同时也不是像“ America / Los_Angeles”这样的timezoneId。

我对如何处理这个问题有些困惑。

1 个答案:

答案 0 :(得分:11)

tl; dr

OffsetDateTime target , eta ;   // Modern java.time class.
java.util.Date scheduledDate ;  // Terrible legacy class.


if( Objects.isNull( eta ) ) {   // If no eta, fall back to scheduledDate.
    target = scheduledDate.toInstant().atOffset( ZoneOffset.UTC ) ; // Never use legacy class `java.util.Date` -- when encountered, immediately convert to modern `java.time.Instant`. 
} else {  // Else not null.
    target = eta ;
}
return target ;

最好完全避免使用java.util.Date。遇到这种情况时,请立即转换为现代类Instant,并忘记有关Date对象的所有信息。

OffsetDateTime target, eta, scheduled ;
scheduled = incomingJavaUtilDate.toInstant().atOffset( ZoneOffset.UTC ) ;

target = Objects.isNull( eta ) ? scheduledDate : eta ;  // Ternary operator. Short way of saying: If eta is null, go with scheduledDate, otherwise go with eta. 
return target ;

Date::toString对你说谎

首先,要了解java.util.Date代表UTC中的时刻,始终代表UTC 。但是,其toString方法具有很好的意图,因为它混淆了动态应用JVM当前默认时区的反功能。这会产生一种错误的印象,即Date实际上具有时区,而实际上没有

避免使用旧的日期时间类

其次,您不必要地和可悲地将非常好的现代 java.time 类(OffsetDateTime)与可怕的旧式日期时间类(Date)混合在一起。不要这样做。完全避免使用旧类。他们在2014年被JSR 310所采用而被淘汰。

table of date-time classes in Java, both legacy and modern

使用 java.time

如果交给了java.util.Date对象,请立即转换为 java.time 。调用添加到旧类中的新转换方法。在UTC中,Instant类直接替换了Date,但具有纳秒级与毫秒级的更好分辨率。

Instant instant = myJavaUtilDate.toInstant() ;  // Convert from legacy class to modern class.

通常,您应该以UTC跟踪时刻。您可以将其设置为Instant常量,以OffsetDateTimeZoneOffset.UTC的形式进行操作。

OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;  // Same moment, no change in meaning whatsoever. 

特别是对于UTC,此处的代码中instantodt之间没有区别。它们都代表UTC的时刻。区别在于OffsetDateTime(a)可以带有备用的UTC偏移值(小时-分钟-秒),而(b)则更灵活,例如以标准{{3 }}。

理解ISO 8601仅仅是小时,分钟和秒的数量。而已。相比之下,offset-from-UTC还要很多。时区是特定区域的人们过去,现在和将来对偏移量的更改的历史记录。例如,使用America/Los_Angeles时区的该地区的人们每年从愚蠢的实践time zone两次更改其自UTC的偏移量,从-08:00到-07:00,然后再返回

因此,通常,时区优于仅偏移量。例如,要查看您的Date在美国西海岸大多数人使用的挂钟时间变成了Instant,请应用时区America/Los_Angeles({{1 }})移至ZoneId以获得Instant

ZonedDateTime

您可以通过提取ZoneId z = ZoneId.of( "America/Los_Angeles" ) ; ZonedDateTime zdt = instant.atZone( z ) ; 返回UTC。

Instant

然后从那里回到Instant instant = zdt.toInstant() ; (如果必须的话,否则避免)。

java.util.Date

实际上,java.util.Date d = java.util.Date.from( instant ) ; 确实有一个深埋在内部的时区。缺少任何访问器(获取/设置)方法,因此无法访问。它的行为与我们此处的讨论无关。令人困惑?是。避免可怕的旧式日期时间类的许多原因中的另一个。