Каков наилучший способ преобразовать 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
чище, чем это (хотя это также работает).