将 Java 日期转换为 OffsetDateTime

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/52633045/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 00:32:40  来源:igfitidea点击:

Converting Java Date to OffsetDateTime

javaspringjava-timejava-date

提问by user6728767

I have an eta value that is an OffsetDateTime and I have a scheduledDate that is a Date type. If the eta isn't set I want to fall back to the Date.

我有一个 eta 值,它是一个 OffsetDateTime,我有一个 scheduleDate 是一个日期类型。如果 eta 未设置,我想回退到日期。

An example of the date is Tue Jul 21 10:32:28 PDT 2020. To convert this, I tried doing: OffsetDateTime.ofInstant(dto.getScheduledTime().ToInstant(), ZoneOffset.UTC) It feels like the utc offset is wrong since the Date has PDT in it already, but at the same time that's also not a timezoneId like "America/Los_Angeles".

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

I'm a little confused on how to handle this.

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

采纳答案by Basil Bourque

tl;dr

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;

Better to completely avoid java.util.Date. When encountered, immediately convert to modern class Instant, and forget all about the Dateobject.

最好完全避免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::toStringlies to you

Date::toString对你说谎

Firstly, understand that java.util.Daterepresents a moment in UTC, always in UTC?. However, its toStringmethod has the well-intentioned by terribly confusing anti-feature of dynamically applying the JVM's current default time zone. This creates the false impression that Datehas a time zone when in fact it does not?.

首先,了解java.util.Date代表 UTC 的时刻,始终是 UTC吗?. 然而,它的toString方法是善意的,因为动态应用 JVM 的当前默认时区这一非常令人困惑的反特性。这会造成错误的印象,即Date有时区,而实际上没有时区.

Avoid legacy date-time classes

避免遗留的日期时间类

Secondly, you are needlessly and tragically mixing the very good modern java.timeclasses (OffsetDateTime) with the terribly awful legacy date-time classes (Date). Do not do this. Avoid the legacy classes entirely. They were obsoleted by the adoption of JSR 310back in 2014.

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

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

Java 中的日期时间类表,包括旧的和现代的

Use java.time

使用java.time

If handed a java.util.Dateobject, immediately convert to java.time. Call the new conversion methods added to the old classes. The Instantclass directly replaces Date, as a moment in UTC, but with finer resolution of nanoseconds versus milliseconds.

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

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

You should generally be tracking moments in UTC. You can do this as an Instantor as a OffsetDateTimewith its offset set to ZoneOffset.UTCconstant.

您通常应该在 UTC 中跟踪时刻。您可以将其作为偏移量设置为常量的anInstant或 aOffsetDateTime来执行ZoneOffset.UTC

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

For UTC specifically, there is no difference between the instantand the odtin our code here. They both represent a moment in UTC. The difference is that OffsetDateTime(a) could carry an alternate offset-from-UTC value (hours-minutes-seconds), and (b) is more flexible, such as generating text in formats other than standard ISO 8601.

特别是对于 UTC,这里的代码中的instant和之间没有区别odt。它们都代表 UTC 中的一个时刻。不同之处在于OffsetDateTime(a) 可以携带一个替代的 UTC 偏移值(小时-分钟-秒),并且 (b) 更灵活,例如以标准ISO 8601以外的格式生成文本。

Understand that an offset-from-UTCis merely a number of hours, minutes, and seconds. Nothing more. A time zone, in contrast, is muchmore. 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_Angelestime zone change their offset-from-UTC twice a year in a silly practice known as Daylight Saving Time (DST)going from -08:00 to -07:00 and back again.

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

So generally a time zone is preferable over a mere offset. For example, to see your Datewe turned into a Instantthrough the wall-clock time used by most people on the west coast of US, apply the time zone America/Los_Angeles(ZoneId) to the Instantto get a ZonedDateTime.

所以通常时区比单纯的偏移更可取。例如,看到你Date,我们变成了Instant通过对美国西海岸使用的大多数人的挂钟时间,申请的时区America/Los_AngelesZoneId)的Instant获得ZonedDateTime

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

You can get back to UTC by extracting a Instant.

您可以通过提取Instant.

Instant instant = zdt.toInstant();

And from there get back to a java.util.Date(if you must, otherwise avoid).

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

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


?Actually, the java.time.Dateclass doeshave a time zone buried deep inside. Lacking any accessor (get/set) methods, it is unreachable. Its behaviors do not relate to our discussion here. Confusing? Yes. Yet another of many reasons to avoid the terrible legacy date-time classes.

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