Wednesday, 12 November 2014

Converting from Joda-Time to java.time

What steps are needed to upgrade from Joda-Time to Java SE 8 date and time (JSR-310)?

From Joda-Time to java.time

Joda-Time has been a very successful date and time library, widely used and making a real difference to many applications over the past 12 years or so. But if you are moving your application to Java SE 8, its time to consider moving on to java.time, formerly known as JSR-310.

The java.time library contains many of the lessons learned from Joda-Time, including stricter null handling and a better approach to multiple calendar systems. I use the phraseology that java.time is "inspired by Joda-Time", rather than an exact derivation, however many concepts will be familiar.

Converting types

Classes not including a time-zone:

Joda-Time java.time Notes
LocalDate LocalDate Same concept - date without time or time-zone
YearMonthDay
LocalTime LocalTime Same concept - time without date or time-zone
TimeOfDay
LocalDateTime LocalDateTime Same concept - date and time without time-zone
MonthDay MonthDay Same concept - month and day without time-zone
YearMonth YearMonth Same concept - year and month without time-zone
- Year New concept - a value type for the year
- Month New concept - an enum for the month-of-year
- DayOfWeek New concept - an enum for the day-of-week
Partial - Not included in java.time

Classes including a time-zone or representing an instant:

Joda-Time java.time Notes
DateTime ZonedDateTime Same concept - Date and time with time-zone
OffsetDateTime New concept - Date and time with offset from Greenwich/UTC
MutableDateTime - Not included in java.time, use immutable ZonedDateTime instead
DateMidnight - Deprecated as a bad idea in Joda-Time, Use LocalDate or ZonedDateTime
- OffsetTime New concept - Time with offset from Greenwich/UTC
Instant Instant Same concept - Instantaneous point on timeline
DateTimeZone ZoneId Same concept - Identifier for a time-zone, such as Europe/Paris
ZoneOffset New concept - An offset from Greenwich/UTC, such as +02:00

Amounts of time:

Joda-Time java.time Notes
Duration Duration Same concept - Amount of time, based on fractional seconds
Period Period and/or Duration Similar concept - Amount of time
Joda-Time Period includes years to milliseconds, java.time only year/month/day (see also (ThreeTen-Extra PeriodDuration)
MutablePeriod - Not included in java.time, use immutable Period or Duration instead
Years - Not included in java.time, use Period instead (or ThreeTen-Extra)
Months
Weeks
Days
Hours - Not included in java.time, use Duration instead (or ThreeTen-Extra)
Minutes
Seconds
Interval - Not included in java.time (see ThreeTen-Extra)
MutableInterval - Not included in java.time

Formatting:

Joda-Time java.time Notes
DateTimeFormatter DateTimeFormatter Same concept - an immutable formatter
DateTimeFormatterBuilder DateTimeFormatterBuilder Same concept - a builder of the formatter
DateTimeFormat DateTimeFormatter Concepts exposed as static methods on DateTimeFormatter
ISODateTimeFormat
PeriodFormatter - Not included in java.time (see ThreeTen-Extra for limited support)
PeriodFormatterBuilder
PeriodFormat
ISOPeriodFormat

Other classes and interfaces:

Joda-Time java.time Notes
- Clock New concept - Standard way to pass around the current time
Chronology Chronology Similar concept - Very different API and implementation
ISOChronology IsoChronology Similar concept - Very different API and implementation
DateTimeFieldType ChronoField Similar concept - Very different API and implementation
DateTimeField
DurationFieldType ChronoUnit Similar concept - Very different API and implementation
DurationField
PeriodType - Not included in java.time
Readable* Temporal* The Readable* interfaces are most closely replaced by the Temporal* interfaces
It is strongly recommended to use the value types, not the temporal interfaces

Odds and Ends

In most cases, the table above will be sufficient to identify the class to convert to. After that, in most cases the method needed will be obvious. Some special cases are noted below.

Rounding. Joda-Time has considerable support for rounding, java.time has less, based only on truncation. See the truncatedTo() methods.

End of month. Joda-Time has the withMaximumValue() method on the property object to change a field to the last day of the month. java.time has a more general mechanism, see TemporalAdjusters.lastDayOfMonth().

Nulls. Joda-Time accepts null as an input and handles it with a sensible default value. java.time rejects null on input.

Construction. Joda-Time has a constructor that accepts an Object and performs type conversion. java.time only has factory methods, so conversion is a user problem, although a parse() method is provided for strings.

Time between. Joda-Time provides methods on amount classes such as Days.between(a, b). java.time provides a similar method on the ChronoUnit classes - ChronoUnuit.DAYS.between(a, b).

Additional fields. Joda-Time provides a fixed set of fields in DateTimeFieldType. java.time allows the set of fields to be extended by implementing TemporalUnit, see IsoFields, JulianFields and WeekFields.

Summary

This blog post has outlined the key mappings between Joda-Time and java.time in Java SE 8. If you are writing code in Java SE 8, its time to migrate to java.time, perhaps using ThreeTen-Extra to fill any gaps.

12 comments:

  1. Thanks for the nice summary. For us, the biggest blocker to upgrading is that java.time doesn't have the nice holiday support that Joda Time has through use of Jollyday http://jollyday.sourceforge.net/ ... the site claims it will be upgraded to java.time, but not sign of any action....

    ReplyDelete
    Replies
    1. Maybe keep an eye on the OpenGamma holiday calendar? https://github.com/OpenGamma/OG-Commons/blob/master/basics/src/main/java/com/opengamma/basics/date/HolidayCalendar.java

      Delete
    2. Update: OpenGamma holiday calendar was moved here: https://github.com/OpenGamma/Strata/blob/master/modules/basics/src/main/java/com/opengamma/strata/basics/date/HolidayCalendar.java

      Delete
  2. Hi Stephen, could you add this table somewhere in documentation?

    ReplyDelete
  3. Jollyday has been ported to Java 8 time from version 0.5.1

    ReplyDelete
  4. Is there a way to convert Joda-time Instant to Java-time Instant?

    ReplyDelete
    Replies
    1. Questions like this should be asked at StackOverflow

      Delete
  5. Do you know why Interval was not ported to java time ?

    ReplyDelete
  6. One more "odds and ends" which is important to be aware of:

    the Joda DateTimeFormat (http://www.joda.org/joda-time/apidocs/org/joda/time/format/DateTimeFormat.html) uses "Y" for "year of era", and "y" for "year". The Java 8 DateTimeFormatter (https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html) uses "Y" for "week based year", and "y" for "year of era". If you're currently using a Joda DateTimeFormat object with "Y" as part of the pattern, this may introduce an off-by-one error (https://stackoverflow.com/questions/26431882/difference-between-year-of-era-and-week-based-year) if you change it to a Java 8 DateTimeFormatter without also replacing "Y" with "y" in the pattern string.

    ReplyDelete
  7. There are a few typos where Greenwich is spelt Greewich. Can you correct these please?

    ReplyDelete
  8. I authored an OpenRewrite recipe to migrate from JodaTime to JavaTime. https://github.com/openrewrite/rewrite-migrate-java/tree/main/src/main/java/org/openrewrite/java/migrate/joda

    ReplyDelete

Please be aware that by commenting you provide consent to associate your selected profile with your comment. Long comments or those with excessive links may be deleted by Blogger (not me!). All spam will be deleted.