将 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,我们代码中的 instant
和 odt
没有区别。它们都代表 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.
我有一个 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".
我对如何处理这个问题有点困惑。
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,我们代码中的 instant
和 odt
没有区别。它们都代表 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.