将 org.joda.time.DateTime 转换为 java.time.OffsetDateTime 的最佳方法是什么?

Ale*_*ing 3 java jodatime datetime-conversion java-time

long以下方法有效,但将时间转换为 a ,然后Instant将时区转换为 aTimeZone然后 a似乎有点笨拙ZoneId。有没有更干净的方法来做到这一点?

java.time.Instant instant = java.time.Instant.ofEpochMilli(jodaDateTime.getMillis());
OffsetDateTime offsetDateTime = OffsetDateTime.ofInstant(instant,
        jodaDateTime.getZone().toTimeZone().toZoneId());
Run Code Online (Sandbox Code Playgroud)

小智 6

这似乎是进行此类转换的一般方法。

由于两个 API 中的类彼此不可互操作(不能将 JodaDateTime与 Java TimeDateTimeFormatter等一起使用),因此它们之间的共同因素似乎是long epochMilli值。

因此,我认为没有比创建 ajava.time.Instant然后将其转换为OffsetDateTime使用 Joda 对象中的时区更好的方法了。

嗯,我认为有一件事可以稍微改进。这段代码:

jodaDateTime.getZone().toTimeZone().toZoneId()
Run Code Online (Sandbox Code Playgroud)

toTimeZone()方法创建一个java.util.Timezone实例,该实例用于创建java.time.ZoneIdviatoZoneId()方法。

您可以通过执行以下操作来避免创建此临时TimeZone对象:

ZoneId.of(jodaDateTime.getZone().getID())
Run Code Online (Sandbox Code Playgroud)

此代码不会创建临时TimeZone对象,而是直接创建ZoneId。由于 JodaDateTimeZone不支持短 ID(例如ISTPST),因此我们可以假设该 ID 可以通过ZoneId类进行识别(因为它也适用于长 ID 名称,例如Europe/London)。如果 Joda 的DateTimeZoneID 是偏移量(例如+01:00),它也适用。

不确定避免创建一个临时对象是否足够干净,但无论如何这是一种改进(虽然很小,但仍然是)。

因此,最终的代码将与您的代码非常相似,只有上面建议的更改:

// java.time.Instant
Instant instant = Instant.ofEpochMilli(jodaDateTime.getMillis());

// create the OffsetDateTime
OffsetDateTime.ofInstant(instant, ZoneId.of(jodaDateTime.getZone().getID()));
Run Code Online (Sandbox Code Playgroud)

还有另一种选择(非常相似,但不确定是否更干净):获取总偏移量(而不是时区)并使用它来创建java.time.ZoneOffset

long millis = jodaDateTime.getMillis();
// java.time.Instant
Instant instant = Instant.ofEpochMilli(millis);

// get total offset (joda returns milliseconds, java.time takes seconds)
int offsetSeconds = jodaDateTime.getZone().getOffset(millis) / 1000;
OffsetDateTime.ofInstant(instant, ZoneOffset.ofTotalSeconds(offsetSeconds));
Run Code Online (Sandbox Code Playgroud)

您还可以使用@assylias' comment提出的建议,但我不确定格式化为 aString然后将其解析为OffsetDateTime是否比这更干净(尽管它也有效)。