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
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).
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.
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.
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.
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.
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();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With