How to convert from org.joda.time.DateTime to java.time.ZonedDateTime

23,335

Solution 1

Not all time-zone strings from Joda-Time will match java.time but the vast majority will as they are both based on the IANA tz data. Compare DateTimeZone.getAvailableIDs() to ZoneId.getAvailableZoneIds() to determine the mismatch. Additional identifiers can be mapped using ZoneId.of(String, Map).

To do the main conversion in the most efficient way, you have to pass in each field:

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));

Note the use of ZoneId.SHORT_IDS as the Map in this case.

For a simpler solution that handles most use cases, but at lower performance, use this:

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

Solution 2

You should avoid providing each field separately if you are working with daylight saving transitions. Convert using epochMillis instead, as in the following example.

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

Otherwise you will lose one hour on the date of transition. For example, Germany transitioned from summer time (GMT+2) to winter time (GMT+1) on 29.10.2017 at 03:00 GMT+2, which becomes 02:00 GMT+1. On that day, you have 2 instances of 02:00 - an earlier one with GMT+2 and a later one with GMT+1.

Since you are working with ZoneIds and not with offsets, there's no way of knowing which one of the 2 instances you want. By default, the first one is assumed during conversion. Both 02:00 GMT+2 and 02:00 GMT+1 are going to be converted to 02:00 GMT+2 if you provide hourOfDay along with ZoneId.

Share:
23,335
Andreas Lundgren
Author by

Andreas Lundgren

Updated on July 09, 2022

Comments

  • Andreas Lundgren
    Andreas Lundgren almost 2 years

    I have a data source with joda time DateTime objects stored. I need to convert them into java ZonedDateTime objects, keeping the original timezone.

    It is not sufficient to keep the offset since some DateTime objects represents daily repetitive tasks, and these tasks must occur at a specific time in a specific time zone for every date. They must thus follow the specified TimeZone transitions for example summer and winter time. I cannot tell the final usage of the DateTime objects, so I need to keep the Time Zone information on all objects to be safe.

    How to convert from org.joda.time.DateTime to java.time.ZonedDateTime?

    Will all

    ord.joda.time.DateTimeZone.getId()

    map to the id's available in

    java.time.ZoneId