2015-03-05 4 views
7

У меня есть источник данных с сохраненными объектами DateTime времени Joda. Мне нужно преобразовать их в объекты java ZonedDateTime, сохраняя исходный часовой пояс.Как конфертировать из org.joda.time.DateTime в java.time.ZonedDateTime

Недостаточно сохранить смещение, так как некоторые объекты DateTime представляют собой ежедневные повторяющиеся задачи, и эти задачи должны выполняться в определенное время в конкретном часовом поясе для каждой даты. Таким образом, они должны следовать указанным переходам TimeZone, например, летнему и зимнему периодам. Я не могу сказать окончательное использование объектов DateTime, поэтому мне нужно сохранить информацию о часовом поясе на всех объектах в безопасности.

Как конфертировать из org.joda.time.DateTime в java.time.ZonedDateTime?

Will все

ord.joda.time.DateTimeZone.getId()

карта идентификатору доступна в

java.time.ZoneId

ответ

15

Не все временные зоны строки из Joda-Time будут соответствовать java.time, но подавляющее большинство будет, поскольку они оба основаны на данных IANA tz. Сравните DateTimeZone.getAvailableIDs() с номером ZoneId.getAvailableZoneIds(), чтобы определить несоответствие. Дополнительные идентификаторы могут быть сопоставлены с использованием ZoneId.of(String, Map).

Для основного преобразования в наиболее эффективным образом, вы должны пройти в каждом поле:

ZonedDateTime zdt = ZonedDateTime.ofLocal(
    LocalDateTime.of(
     dt.getYear(), 
     dt.getMonthOfYear(), 
     dt.getDayOfMonth(), 
     dt.getHourOfDay(), 
     dt.getMinuteOfHour(), 
     dt.getSecondOfMinute(), 
     dt.getMillisOfSecond() * 1_000_000), 
    ZoneId.of(dt.getZone().getID(), ZoneId.SHORT_IDS), 
    ZoneOffset.ofTotalSeconds(dt.getZone().getOffset(dt)/1000)); 

Обратите внимание на использование ZoneId.SHORT_IDS как Map в этом случае.

Для более простого решения, которое обрабатывает большинство случаев использования, но при более низкой производительности, используйте:

ZonedDateTime zdt = dt.toGregorianCalendar().toZonedDateTime(); 
+0

Есть ли определенное подмножество, которое не в одном или другом? Возможно, некоторые из старых зон совместимости POSIX? Я надеюсь, что все современные зоны стиля «Район/Местность» будут доступны в обоих. –

+2

Единственное отличие - это ROC, который был заменен на ROK. Зоны EST, HST и MST можно получить с помощью 'ZoneId.SHORT_IDS'. В противном случае любые различия могут быть получены только из более поздней версии базы данных часовых поясов в Joda-Time. – JodaStephen

+1

@JodaStephen Вместо 'ZoneId.of (dt.getZone().getID(), ZoneId.SHORT_IDS)) 'не будет' dt.toTimeZone(). toZoneId() 'работает тоже? он, кажется, оставляет nitty gritty для JodaTime и Java соответственно. – NomeN

3

Вы должны избегать предоставления каждого поля в отдельности, если вы работаете с сохранением дневного света переходов. Вместо этого конвертируйте с помощью epochMillis, как в следующем примере.

Instant instant = Instant.ofEpochMilli(dt.getMillis()); 
ZoneId zoneId = ZoneId.of(dt.getZone().getId(), ZoneId.SHORT_IDS); 
ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, zoneId); 

В противном случае вы потеряете один час в день перехода. Например, Германия перешла с летнего времени (GMT + 2) на зимнее время (GMT + 1) 29.10.2017 в 03:00 GMT + 2, что составляет 02:00 GMT + 1. В этот день у вас есть 2 экземпляра 02:00 - более ранний с GMT + 2 и более поздний с GMT + 1.

Поскольку вы работаете с ZoneIds, а не с помощью смещений, нет способа узнать, какой из двух экземпляров вы хотите. По умолчанию, первый принимается во время преобразования. Оба 02:00 GMT + 2 и 02:00 GMT + 1 будут конвертированы в 02:00 GMT + 2, если вы предоставите hourOfDay вместе с ZoneId.

Смежные вопросы