Каков наилучший способ преобразовать org.joda.time.DateTime в java.time.OffsetDateTime?

Следующее работает, но кажется немного неуклюжим, чтобы преобразовать время в longи затем Instant а также преобразование часового пояса в TimeZone а затем ZoneId, Есть ли более чистый способ сделать это?

java.time.Instant instant = java.time.Instant.ofEpochMilli(jodaDateTime.getMillis());
OffsetDateTime offsetDateTime = OffsetDateTime.ofInstant(instant,
        jodaDateTime.getZone().toTimeZone().toZoneId());

1 ответ

Похоже, что это общий способ сделать такое преобразование.

Так как классы из обоих API не совместимы друг с другом (вы не можете использовать Joda's DateTime с Java времени DateTimeFormatter и так далее), общий фактор между ними, кажется, long значениеэпохиМилли.

Так что я не вижу лучшего способа, чем создать java.time.Instant а затем преобразовать его в OffsetDateTime используя часовой пояс от объекта Йоды.

Ну, я думаю, что есть кое-что, что можно немного улучшить. Этот код:

jodaDateTime.getZone().toTimeZone().toZoneId()

toTimeZone() метод создает java.util.Timezone экземпляр, который используется для создания java.time.ZoneId с помощью toZoneId() метод.

Вы можете избежать создания этого временного TimeZone возражать, делая:

ZoneId.of(jodaDateTime.getZone().getID())

Этот код не создает временный TimeZone объект, и создает ZoneId непосредственно. Как йода DateTimeZone не работает с короткими идентификаторами (например, IST или же PST), мы можем предположить, что идентификатор будет ZoneId класс (так как он также работает с длинными именами идентификаторов, таких как Europe/London). Это также работает, если Йода DateTimeZone ID является смещением (например, +01:00).

Не уверен, что избегать создания одного временного объекта достаточно чище, но в любом случае это улучшение (крошечное, но так и есть).

Итак, окончательный код будет очень похож на ваш, только с предложенным выше изменением:

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

// create the OffsetDateTime
OffsetDateTime.ofInstant(instant, ZoneId.of(jodaDateTime.getZone().getID()));

Есть еще одна альтернатива (очень похожая, но не уверенная в чистоте): получить общее смещение (вместо часового пояса) и использовать его для создания 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));

Вы также можете использовать предложение, сделанное в комментарии @assylias, но я не уверен, что форматирование в String а затем анализировать его OffsetDateTime чище, чем это (хотя это также работает).

Другие вопросы по тегам