Differences between Java 8 Date Time API (java.time) and Joda-Time
I know there are questions relating to java.util.Date and Joda-Time. But after some digging, I couldn't find a thread about the differences between the java.time API (new in Java 8, defined by JSR 310) and Joda-Time.
I have heard that Java 8’s java.time API is much cleaner and can do much more than Joda-Time. But I cannot find examples comparing the two.
- What can java.time do that Joda-Time cannot?
- What can java.time do better than Joda-Time?
- Is the performance better with java.time?
a) Both libraries use immutable types. Joda-Time also offers additional mutable types like MutableDateTime.
b) Furthermore: Both libraries are inspired by the design study "TimeAndMoney" from Eric Evans or ideas from Martin Fowler about domain driven style so they strive more or less for a fluent programming style (although not always perfect ;-)).
c) With both libraries we get a real calendar date type (called LocalDate), a real wall time type (called LocalTime) and the composition (called LocalDateTime). That is a very big win compared with old java.util.Calendar and java.util.Date.
d) Both libraries use a method-centric approach meaning they encourage the user to use getDayOfYear() instead of get(DAY_OF_YEAR). This causes a lot of extra methods compared with java.util.Calendar (although latter is not type-safe at all due to excessive use of ints).
See the other answer by @OO7 pointing to the analysis of Mikhail Vorontsov although point 3 (exception catching) is probably obsolete - see this JDK-bug. The different performance (which is in general favour of JSR-310) is mainly due to the fact that the internal implementation of Joda-Time always use a machine-time-like long-primitive (in milliseconds).
Joda-Time often use NULL as default for system timezone, default locale, current timestamp etc. while JSR-310 almost always rejects NULL values.
An overview about supported fields in Java-8 (JSR-310) is given by some classes in the temporal-package (for example ChronoField and WeekFields) while Joda-Time is rather weak on this area - see DateTimeFieldType. The biggest lack of Joda-Time is here the absence of localized week-related fields. A common feature of both field implementation design is that both are based on values of type long (no other types, not even enums).
a) JSR-310 offers more timezone features than Joda-Time. Latter is not able to yield a programmatical access to the history of timezone offset transitions while JSR-310 is capable to do this.
b) For your information: JSR-310 has moved its internal timezone repository to a new location and a different format. The old library folder lib/zi does not exist any more.
Adjuster vs. Property
JSR-310 has introduced the TemporalAdjuster-interface as a formalized way to externalize temporal calculations and manipulations, especially for library or framework-writers this is a nice and relative easy way to embed new extensions of JSR-310 (a kind of equivalent to static helper classes for former java.util.Date).
For most users however, this feature has very limited value because the burden to write code is still with the user. Built-in solutions based on the new TemporalAdjuster-concept are not so many, there is currently only the helper class TemporalAdjusters with a limited set of manipulations (and the enums Month or other temporal types).
Joda-Time offers a field-package but practice has shown evidence that new field implementations are very hard to code. On the other side Joda-Time offers so-called properties which make some manipulations much easier and more elegant than in JSR-310, for example property.withMaximumValue().
JSR-310 offers 4 extra calendar systems. The most interesting one is Umalqura (used in Saudi Arabia). The other 3 are: Minguo (Taiwan), Japanese (only the modern calendar since 1871!) and ThaiBuddhist (only correct after 1940).
Joda-Time offers an Islamic calendar based on calculatory base - not a sighting-based calendar like Umalqura. Thai-Buddhist is also offered by Joda-Time in a similar form, Minguo and the japanese one not. Otherwise Joda-Time offers coptic and ethiopic calendar, too (but without any support for internationalization).
More interesting for Europeans: Joda-Time also offers a Gregorian, Julian and mixed-gregorian-julian calendar. However, the practical value for real historical calculations is limited because important features like different year starts in date history are not supported at all (the same criticism is valid for old java.util.GregorianCalendar).
JSR-310 has no interface (a design mistake) but an abstract class java.time.Clock which can be used for any clock dependency injection. Joda-Time offers the interface MillisProvider and some helper methods in DateTimeUtils instead. So this way Joda-Time is also capable of supporting test-driven models with different clocks (mocking etc.).
Both libraries support the calculation of time distances in one or more temporal units. However, when handling single-unit-durations the JSR-310-style is obviously nicer (and long-based instead of using int):
JSR-310 => long days = ChronoUnit.DAYS.between(date1, date2);
Joda-Time => int days = DAYS.daysBetween(date1, date2).getDays();
Handling of multiple-unit-durations are also different. Even the calculation results can differ - see this closed Joda-Time issue. While JSR-310 use a very simple and limited approach to use just the classes Period (duration based on years, months and days) and Duration (based on seconds and nanoseconds), Joda-Time uses a more sophisticated way using the class PeriodType in order to control in which units a duration (Joda-Time call it "Period") shall be expressed. While the PeriodType-API is somehow awkward to use a similar way is not offered by JSR-310 at all. Especially it is not yet possible in JSR-310 to define mixed date and time durations (based on days and hours for example). So be warned if it comes to migration from one library to another. The libraries in discussion are incompatible - despite of partially same class names.
JSR-310 does not support this feature while Joda-Time has limited support. See also this SO-answer.
Formatting and Parsing
Best way to compare both libraries is to view the equal-named classes DateTimeFormatterBuilder (JSR-310) and DateTimeFormatterBuilder (Joda-Time). The JSR-310-variant is a little bit more powerful (can also handle any kind of TemporalField provided the field implementor has managed to code some extension points like resolve()). Most important difference is however - in my opinion:
JSR-310 can much better parse timezone names (format pattern symbol z) while Joda-Time could not do this at all in its earlier versions and now only in a very limited way.
Another advantage of JSR-310 is support for standalone month names which is important in languages like Russian or Polish etc. Joda-Time has no access to such resources - not even on Java-8 platforms.
The pattern syntax in JSR-310 is also more flexible than in Joda-Time, allows for optional sections (using square brackets), is more orientated towards CLDR-standard and offers padding (letter symbol p) and more fields.
Otherwise it should be noted that Joda-Time can format durations using PeriodFormatter. JSR-310 cannot do this.
Hope this overview helps. All the gathered information is mainly there due to my efforts and investigations how to design and implement a better date-and-time library (nothing is perfect).
Update from 2015-06-24:
Meanwhile I have found the time to write and publish a tabular overview for different time libraries in Java. The tables also contain a comparison between Joda-Time v2.8.1 and Java-8 (JSR-310). It is more detailed than this post.
Java 8 Date/Time :
- Java 8 classes are built around the human time. It makes them fast for human datetime arithmetics/conversion.
- Date/time component getters like getDayOfMonth have O(1) complexity in Java 8 implementation.
- Parsing of OffsetDateTime/OffsetTime/ZonedDateTime is very slow in Java 8 ea b121 due to exceptions thrown and caught internally in the JDK.
- A set of packages: java.time.*, java.time.chrono.*, java.time.format.*, java.time.temporal.*, java.time.zone.*
- Instants (timestamps) Date and Time Partial Date and Time Parser and Formatter Time zones Different chronologies (calendars).
- Existing classes have issues like Date has no support for I18N or L10N. They are mutable!
- Simpler & more robust.
- Clocks can be injected.
- Clocks can be created with various properties - Static clocks, Mocked clocks, Low-precision clocks (whole seconds, whole minutes, etc).
- Clocks can be created with specific time zones. Clock.system(Zone.of("America/Los_Angeles")).
- Makes code handling date and time testable.
- Makes tests independent of timezone.
- Joda-Time is using machine time inside. A manual implementation based on int/long values would be much faster.
- Joda-Time getters require the computer-to-human time calculation on every getter call, which makes Joda-Time a bottleneck in such scenarios.
- It is composed of immutable classes it handles Instants, Date & Time, Partials, and Durations It is flexible It is well designed.
- Represents dates as instants. But a date&time may correspond to more than one instant. Overlap hour when daylight savings end. As well as not have any instant that corresponds to it at all. Gap hour when daylight starts. Has to perform complex computations for simple operations.
- Accepts nulls as valid values on most of its methods. Leads to subtle bugs.
For more detailed comparision see :-