Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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

like image 704
Andreas Lundgren Avatar asked Mar 05 '15 12:03

Andreas Lundgren


People also ask

What is the replacement of Joda-time Library in Java 8?

If your project still uses Joda-Time but would like to migrate to java. time then read on. The release of Java SE 8 included a new and improved standard Date and Time API commonly referred to as java. time (JSR-310).

How do I get time from ZonedDateTime?

now() now() method of a ZonedDateTime class used to obtain the current date-time from the system clock in the default time-zone. This method will return ZonedDateTime based on system clock with default time-zone to obtain the current date-time.

What is ZonedDateTime in Java?

ZonedDateTime is an immutable representation of a date-time with a time-zone. This class stores all date and time fields, to a precision of nanoseconds, and a time-zone, with a zone offset used to handle ambiguous local date-times.

How do I convert ZonedDateTime to another timezone?

To convert a ZonedDateTime instance from one timezone to another, follow the two steps: Create ZonedDateTime in 1st timezone. You may already have it in your application. Convert the first ZonedDateTime in second timezone using withZoneSameInstant() method.


2 Answers

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.

like image 133
Muhip Tezcan Avatar answered Sep 28 '22 08:09

Muhip Tezcan


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();
like image 41
JodaStephen Avatar answered Sep 28 '22 07:09

JodaStephen