我的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。
我对如何处理这个问题有些困惑。
答案 0 :(得分:11)
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所采用而被淘汰。
如果交给了java.util.Date
对象,请立即转换为 java.time 。调用添加到旧类中的新转换方法。在UTC中,Instant
类直接替换了Date
,但具有纳秒级与毫秒级的更好分辨率。
Instant instant = myJavaUtilDate.toInstant() ; // Convert from legacy class to modern class.
通常,您应该以UTC跟踪时刻。您可以将其设置为Instant
常量,以OffsetDateTime
或ZoneOffset.UTC
的形式进行操作。
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ; // Same moment, no change in meaning whatsoever.
特别是对于UTC,此处的代码中instant
和odt
之间没有区别。它们都代表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 ) ;
类确实有一个深埋在内部的时区。缺少任何访问器(获取/设置)方法,因此无法访问。它的行为与我们此处的讨论无关。令人困惑?是。避免可怕的旧式日期时间类的许多原因中的另一个。