将Java Date转换为OffsetDateTime

use*_*767 7 java spring java-time java-date

我的eta值是OffsetDateTime,我有一个DateDate类型的scheduledDate.如果没有设置eta,我想回到日期.

这个日期的一个例子是Tue Jul 21 10:32:28 PDT 2020.要转换这个问题,我想这样做: OffsetDateTime.ofInstant(dto.getScheduledTime().ToInstant(), ZoneOffset.UTC) 感觉就像UTC偏移量是错误的,因为日期中有PDT了,但同时这也是不喜欢"美国/洛杉矶"一timezoneId.

我对如何处理这个问题感到有些困惑.

Bas*_*que 26

TL;博士

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;
Run Code Online (Sandbox Code Playgroud)

最好完全避免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;
Run Code Online (Sandbox Code Playgroud)

Date::toString 对你说谎

首先,要了解java.util.Date代表UTC的时刻,始终是UTC .但是,它的toString方法具有动态应用JVM当前默认时区的非常混乱的反特征.这会产生Date具有时区的错误印象,而事实上它并非.

避免遗留日期时间类

其次,你将这些非常好的现代java.time类(OffsetDateTime)与非常糟糕的遗留日期时间类(Date)混合在一起.不要这样做.完全避免遗留类.它们在2014年被JSR 310采用后被淘汰.

使用java.time

如果交了一个java.util.Date对象,立即转换为java.time.调用添加到旧类的新转换方法.该Instant班可直接替换Date,作为UTC了一下,但纳秒与毫秒更高的分辨率.

Instant instant = myJavaUtilDate.toInstant();  // Convert from legacy class to modern class.
Run Code Online (Sandbox Code Playgroud)

您通常应该跟踪UTC中的时刻.您可以将其设置为Instant或将OffsetDateTime其偏移设置为ZoneOffset.UTC常量.

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

对于UTC,具体来说,这里的代码instantodt代码之间没有区别.它们都代表了UTC时刻.不同之处在于OffsetDateTime(a)可以携带替代的UTC偏移值(小时 - 分钟 - 秒),(b)更灵活,例如以标准ISO 8601以外的格式生成文本.

了解到UTC偏移量仅仅是小时数,分钟数和秒数.而已.一个时区,与此相反,是了.时区是特定地区人民使用的偏移的过去,现在和将来变化的历史.例如,使用America/Los_Angeles时区的人们每年两次更改其与UTC的偏移量,这是一种愚蠢的做法,称为夏令时(DST),从-08:00到-07:00再返回.

因此,通常时区优于仅仅偏移.例如,要看到Date我们Instant在美国西海岸的大多数人使用的挂钟时间,我们应用时区America/Los_Angeles(ZoneId)Instant来获得a ZonedDateTime.

ZoneId z = ZoneId.of("America/Los_Angeles");
ZonedDateTime zdt = instant.atZone(z);
Run Code Online (Sandbox Code Playgroud)

你可以通过提取一个回到UTC Instant.

Instant instant = zdt.toInstant();
Run Code Online (Sandbox Code Playgroud)

然后从那里回到java.util.Date(如果你必须,否则避免).

java.util.Date d = java.util.Date.from(instant);
Run Code Online (Sandbox Code Playgroud)

实际上,这个java.time.Date班级确实有一个深埋在里面的时区.缺少任何访问器(获取/设置)方法,它是无法访问的.它的行为与我们在这里的讨论无关.混乱?是.避免可怕的遗留日期时间类的许多原因的另一个原因.