将 Java 日期转换为 OffsetDateTime

Converting Java Date to OffsetDateTime

我有一个 eta 值,它是一个 OffsetDateTime,我有一个 scheduledDate 是一个 Date 类型。如果未设置预计到达时间,我想回退到日期。

日期的一个例子是Tue Jul 21 10:32:28 PDT 2020。要转换它,我尝试这样做: OffsetDateTime.ofInstant(dto.getScheduledTime().ToInstant(), ZoneOffset.UTC) 感觉 utc 偏移量是错误的,因为 Date 中已经有 PDT,但同时它也不是像 "America/Los_Angeles".

这样的 timezoneId

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

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;

最好完全避免java.util.Date。遇到立即转现代classInstant,忘掉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 有时区的错误印象,而实际上它没有 .

避免遗留日期时间 classes

其次,您将非常好的现代 java.time classes (OffsetDateTime) 与非常糟糕的遗产混为一谈日期时间 classes (Date)。不要这样做。完全避免遗留 classes。它们在 2014 年因采用 JSR 310 而过时。

使用java.time

如果递给一个java.util.Date对象,立即转换为java.time。调用添加到旧 classes 的新转换方法。 Instant class 直接替换了 Date,作为 UTC 中的时刻,但纳秒与毫秒的分辨率更精细。

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,我们代码中的 instantodt 没有区别。它们都代表 UTC 中的一个时刻。不同之处在于 OffsetDateTime (a) 可以携带一个替代的与 UTC 的偏移值(小时-分钟-秒),并且 (b) 更灵活,例如以标准 [=47 以外的格式生成文本=].

了解 offset-from-UTC is merely a number of hours, minutes, and seconds. Nothing more. A time zone, in contrast, is much more. A time zone is a history of past, present, and future changes to the offset used by the people of a particular region. For example, the people in region using America/Los_Angeles time zone change their offset-from-UTC twice a year in a silly practice known as Daylight Saving Time (DST) 从 -08:00 到 -07:00 然后再返回。

所以通常时区比单纯的偏移更可取。例如,要查看您的 Date 我们通过美国西海岸大多数人使用的挂钟时间变成了 Instant,应用时区 America/Los_Angeles (ZoneId) 到 Instant 得到 ZonedDateTime.

ZoneId z = ZoneId.of("America/Los_Angeles");
ZonedDateTime zdt = instant.atZone(z);

您可以通过提取 Instant 返回 UTC。

Instant instant = zdt.toInstant();

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

java.util.Date d = java.util.Date.from(instant);

实际上,java.time.Date class 确实 有一个隐藏在深处的时区。缺少任何访问器 (get/set) 方法,它是不可访问的。它的行为与我们在这里的讨论无关。令人困惑?是的。避免可怕的遗留日期时间的另一个众多原因 classes.