Differences between Java 8 Date Time API (java.time) and Joda-Time - java

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?

Common features
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).
Performance
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).
Null
Joda-Time often use NULL as default for system timezone, default locale, current timestamp etc. while JSR-310 almost always rejects NULL values.
Precision
JSR-310 handles nanosecond precision while Joda-Time is limited to millisecond precision.
Supported fields:
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).
Enum
JSR-310 offers enums like DayOfWeek or Month while Joda-Time does not offer this because it was mainly developed in years 2002-2004 before Java 5.
Zone API
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().
Calendar systems
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).
Other calendars like Hebrew or Persian or Hindu are completely missing in both libraries.
Epoch days
JSR-310 has the class JulianFields while Joda-Time (version 2.0) offers some helper methods in the class DateTimeUtils.
Clocks
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.).
Duration arithmetic
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.
Intervals
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 :
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 :-
Java 8 Date/Time library performance (as well as Joda-Time 2.3 and j.u.Calendar). &
New Date & Time API in Java 8

Joda-Time is now in maintenance-mode
Not a direct answer to the question but the Joda-Time project is no longer in active development. The team suggests users migrate to the newer java.time API. See tutorial by Oracle.
From the official GitHub project page:
Joda-time is no longer in active development except to keep timezone
data up to date. From Java SE 8 onwards, users are asked to migrate to
java.time (JSR-310) - a core part of the JDK which replaces this
project. For Android users, java.time is added in API 26+. Projects
needing to support lower API levels can use the ThreeTenABP library.

The project has been led jointly by the author of Joda-Time (Stephen Colebourne) and Oracle, under JSR 310, and will appear in the new Java SE 8 package java.time.
https://www.oracle.com/technical-resources/articles/java/jf14-date-time.html

Related

How can I represent and operate on time values greater than 24:00 in Java?

I'm currently doing some work in an application domain that uses time values greater than 24:00 to represent times after midnight that are still associated with the previous day's details. For instance, it might use 25:15 on Monday to represent 1:15 AM on Tuesday, since from a domain standpoint, this value is still associated with Monday's data.
This type of time usage is briefly mentioned in the Wikipedia article for the 24-hour clock:
Time-of-day notations beyond 24:00 (such as 24:01 or 25:00 instead of 00:01 or 01:00) are not commonly used and not covered by the relevant standards. However, they have been used occasionally in some special contexts in [various countries] where business hours extend beyond midnight, such as broadcast television production and scheduling.
Java provides the LocalTime model class to represent times. However, LocalTime is constrained to be between midnight of the given day (inclusive) and midnight the next day (exclusive), i.e. in the range [0:00-23:59:59.999999999].
The Java Time API was written to be flexible, but with more specialized concepts excluded from the core API. As mentioned in the ThreeTen Extra project curated by the primary author of the Java 8 date & time library:
Not every piece of date/time logic is destined for the JDK. Some concepts are too specialized or too bulky to make it in.
I have not had luck finding an existing type or other straightforward way to model this less-constrained time type through the core Java libraries or ThreeTen Extra. It is however, very possible that I'm missing something, perhaps something fairly obvious.
How can I model this sort of less-constrained time in Java, ideally using the java.time API or an extension thereof a la the ThreeTen-Extra project? I would like to be able to use it to textually represent the time value ("25:15") and ideally perform temporal calculations with it (e.g. convert "Monday # 25:15" to "Tuesday # 1:15 AM").
If there isn't a straightforward approach, I'll probably end up opening an issue at the Threeten-Extra project.
My first thought is to store that as a Duration object. You could easily use the getters on that class to construct the HH:mm string when you want to display the value, or use something like the Apache Commons DurationFormatUtils.
The LocalDate and LocalDateTime classes support operations like adding and subtracting Durations.
No that does not exist
I am convinced that no class in the three-ten family or commonly used class from elsewhere supports what you want. The closest my search could get was the DayCycles class of the Time4J library (link at the bottom). It consists of a time of day (a PlainTime) and a count of days relative to an unspecified date, so what you ask for; but it’s specifically for returning the result of adding or subtracting time from a PlainTime and doesn’t offer any functionality of its own.
Spin your own
I wouldn’t think that developing your own class that could interoperate with java.time would be too hard. Likely base it off java.time.Duration as Mark B suggests, depending on more precise requirements.
Parsing and formatting may be the hardest part if you have demanding requirements for these. Possibly it’s worth taking inspiration from the source code for the Joda-Time library since this includes facilities for formatting and parsing durations.
Another source of inspiration would be the source of java.time.LocalTime.
Here are the very first few bits:
public class SpecializedTime {
private Duration timeSince0000;
private SpecializedTime(Duration timeSince0000) {
this.timeSince0000 = timeSince0000;
}
static SpecializedTime parse(String text, DateTimeFormatter formatter) {
ParsePosition position = new ParsePosition(0);
TemporalAccessor parsed = formatter.parseUnresolved(text, position);
if (position.getErrorIndex() != -1) {
throw new DateTimeParseException("Parse error", text, position.getErrorIndex());
}
if (position.getIndex() != text.length()) {
throw new DateTimeParseException("Unparsed text", text, position.getIndex());
}
if (! parsed.isSupported(ChronoField.HOUR_OF_DAY)) {
throw new DateTimeParseException("Cannot resolve", text, 0);
}
Duration time = Duration.ofHours(parsed.getLong(ChronoField.HOUR_OF_DAY));
if (parsed.isSupported(ChronoField.MINUTE_OF_HOUR)) {
int minuteOfHour = parsed.get(ChronoField.MINUTE_OF_HOUR);
// Should validate, 0..59
time = time.plusMinutes(minuteOfHour);
}
// Same for seconds and nanoseconds
return new SpecializedTime(time);
}
#Override
public String toString() {
return String.format("%02d:%02d", timeSince0000.toHours(), timeSince0000.toMinutesPart());
}
}
Demonstration:
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("H:m");
SpecializedTime st = SpecializedTime.parse("25:15", timeFormatter);
System.out.println(st);
Output:
25:15
Link
Documentation of DayCycles form Time4J
There is not currently a type which directly models this concept in ThreeTen-Extra or in the core Java libraries. However, a feature request now exists in ThreeTen-Extra requesting this functionality (threeten-extra#169).
ThreeTen-Extra project maintainer Stephen Colebourne has commented that this would be a sensible addition to the library, so it's seems to be mostly a matter of when or whether anybody steps up to implement the feature.
Stephen Colebourne also suggested a few ways of implementing this feature within the library. One of these suggested approaches could be used as part of a custom solution to this problem.
It could be a combination of LocalTime and a number of days, or something closer to LocalTime. Various design options.

Oracle database: using Char(X) or Numeric(X) instead of Date

I have found some issues with the date type in Oracle databases. I have to manage an important amount of data, and they don't seem to work as well as expected with indexes and other stuff. The important thing is that I have decided to use another type for it.
My options are:
numeric(8) for "date" and numeric(6) for "time"
char(8) for "date" and char(6) for "time"
The fields are formatted as YYYYMMAA for date and HHMMSS for time.
The order of priorities (pondered) are:
Performance querying the fields separately (x3.5)
Performance querying the fields joined as one (date + time) (x3)
Usability from java (x2)
Legibility of the database (x1)
Which type would you suggest to use and why?
Thanks! :)
I would recommend to use still a date type. It will be stored as a number anyway ;) . But if you preffer to store it as a number or char, the 20151019 as a number makes more sense :) (also from size & performance perspective) btw, date format will be even smaller
ISO 8601
When you must serialize a date-time value as a string, use the standard ISO 8601 formats. Here are examples of a few of the formats:
Date-only example: 2015-10-18
Date-time example: 2015-10-18T14:26:16Z
Week-of-year: 2015-W42
This entire standard is surprisingly well thought-out and practical. The strings alphabetical order also happen to be chronological (when in UTC, and when consistent with resolving to whole or fraction of the second).
The hyphens are optional, considered by the spec to be the the "basic" version of the formats; I suggest including the hyphens unless storage/memory is critically scarce. The hyphens make the strings recognizable as date-time representations, and are easier to read by humans.
When creating reports, exporting data, writing XML or JSON, or otherwise exchanging data, I suggest almost always using these standard formats. Both (a) the new java.time framework built into Java 8 and later, (b) the Joda-Time library use these formats by default when parsing and generating string representations of date-time values.
Specifications Discordance
Note that while both ISO 8601 and the SQL standard are decades old, they seemed to have not crossed paths. The SQL standard has similar formats but not quite the same. Specifically ISO 8601 uses a T between the date and time-of-day portions whereas the SQL spec never does so.
Also some proprietary types use their own string formats, such as Oracle 11g using DD-MON-YY as the default for DATE type, for example '13-NOV-92'.
java.time
The java.time framework built into Java 8 and later has extended the ISO 8601 format for date-time by appending the name of the time zone in brackets.
The standard uses only an offset-from-UTC. A true time zone is an offset plus a set of rules for making adjustments for anomalies such as Daylight Savings Time (DST).
Use The Data-Type, Luke
Like the others commenting, I strongly recommend you learn and use your database’s native data types for date-time work. Some like SQLite have weak support for date-time, but most have decent to excellent support (such as H2 and Postgres).
These data types vary widely. The SQL spec defines some, but some databases such as Oracle additionally have proprietary types. Often those proprietary types are old outmoded types.
Even the standard data types are not so standard. You should play around and experiment outside your project so as to cement your understanding of their behavior.
The "issues" you experienced are most likely a misunderstanding of the specific type or of date-time handling in general. If so, rolling you own data type (via strings) will only exacerbate your problems in the long run. Invest some time in searching StackOverflow to learn about date-time handling. The subject of date-time is surprisingly tricky.
Numbers
As for using numbers as a roll-your-own date-time type, nearly all the native date-time data types use numbers internally. So no performance advantage in doing your own.

Java Dates - What's the correct class to use?

So the whole Java Date/Calendar/GregorianCalendar thing is obviously a joke. What's the right Date class to use?
Edit: Building an SDK for third parties on Android where the application needs to provide a date
More Edit: Things that make this so obviously a joke:
99% of Date is deprecated
Date's Year is offset from 1900
Date's Month is zero-indexed while day is one-indexed
Dates are mutable
You're supposed to use a Calendar to create a date...
... except you really have to use a GregorianCalendar
Do a significant percent of developers want to use a different calendar?
Calendar.getTime() returns a Date
There's no Date math (like how far apart are two dates in years)
Messing with milliseconds since epoch doesn't count
You can't chain parts together to get an expression (like the date one year ago today)
Probably more stuff
Joda-Time. Even on Android.
If you want to stick to Java SE classes, it depends on what you're trying to do.
Edit: You keep changing your question. Date and Calendar.
Avoid the legacy date-time classes
So the whole Java Date/Calendar/GregorianCalendar thing is obviously a joke.
Yes, the old date-time classes bundled with the earliest versions of Java are an awful mess. Badly designed, clumsy attempts at improvements, many hacks.
But to be fair, those classes were a valiant effort in addressing a surprisingly tricky topic that the entire information industry has ignored for decades. Based on prior work at Taligent and IBM, the authors of those classes at least made an attempt where virtually all other programming languages, platforms, and tools take a pass with only the barest minimum of support for date-time handling.
Fortunately we now have the industry-leading java.time classes (JSR 310) built into Java 8 and later. These were inspired by the success of the Joda-Time project. Indeed both efforts were led by the same man, Stephen Colebourne.
java.time
Every single one of your bullet items of complaint is rectified by using java.time instead.
99% of Date is deprecatedInstant replaces java.util.Date. AFAIK, nothing is deprecated in java.time in Java 8 & Java 9.
Date's Year is offset from 1900Years have sane numbering in java.time, 2018 is the year 2018.
Date's Month is zero-indexed while day is one-indexedMonths have sane numbering in java.time, 1-12 for January-December. Even better, the Month enum provides objects to represent each month of the year rather than a mere integer number. So you get valid values, type-safety, and self-documenting code.
Dates are mutableVirtually all of java.time is immutable. Any calls to alter some aspect of a java.time object returns a new and distinct object. Even constructors are hidden, with static factory methods used instead.
You're supposed to use a Calendar to create a date...ZonedDateTime replaces java.util.Calendar.
... except you really have to use a GregorianCalendarZonedDateTime replaces java.util.GregorianCalendar too. The java.time framework uses interfaces mostly for internal-use only, encouraging apps to use only the concrete classes. This was a design decision specific to the needs of java.time as a framework and does not mean you should the same in your apps.
Do a significant percent of developers want to use a different calendar?Yes. Other calendaring systems are used by many people around the globe. The java.time framework provides for this via the Chronology interface and AbstractChronology class. The default chronology is IsoChronology following the ISO 8601 standard used generally in the West. In Java 8 & 9, other bundled chronologies include Thai Buddhist, Hijrah (Islamic), Minguo (Taiwan), and Japanese Imperial. Third-parties may implement others. In the ThreeTen-Extra project, you’ll find additional chronologies for Accounting (proleptic 52/53-week per US IRS Publication 538 and the International Financial Reporting Standards), the British Julian-Gregorian cutover, Coptic (Christian Egypt), Discordian (Erisian), Ethiopic, International Fixed (Cotsworth plan, the Eastman plan), proleptic Julian, Pax, and Symmetry010 & Symmetry454. If only someone would implement the French Republican Calendar.
Calendar.getTime() returns a DateJust use Instant as your basic building-block class in java.time, always representing a moment in UTC with a resolution of nanoseconds. The other types such as OffsetDateTime & ZonedDateTime can convert back-and-forth with Instant.
There's no Date math (like how far apart are two dates in years)The java.time classes have many convenient plus…/minus… methods. Furthermore, java.time provides powerful TemporalAduster implementations as well as enabling you to write your own. Also look to the ChronoUnit::between method, such as ChronoUnit.YEARS.between( thisLocalDate , that LocalDate ).
Messing with milliseconds since epoch doesn't countLook to Instant::toEpochMilli and Instant.ofEpochMilli if you must use count-from-epoch, but certainly not advisable. Better to use java.time objects and ISO 8601 strings to represent date-time values.
You can't chain parts together to get an expression (like the date one year ago today)The java.time classes are definitely designed for call-chaining. Example: LocalDate.now( ZoneId.of( "Europe/Paris" ) ).minusYears( 1 ).getDayOfWeek().getDisplayName( TextStyle.FULL , Locale.FRANCE ) > dimanche. Sometimes appropriate, but don’t go nuts with it — that’s my advice.
Probably more stuffYes many more problems with the old legacy classes. You will find java.time to be a radical departure from the old stuff, thoroughly modern and well-designed, a gigantic improvement.
One of the other problem areas is exchanging date-time values with a database. Note that with a JDBC driver compliant with JDBC 4.2 or later (JSR 221), you can avoid the date-time related java.sql classes such as java.sql.Timestamp classes. Those old classes are related to the troublesome old legacy classes, and are no longer needed.
myPreparedStatement.setObject( … , instant ) ;
…and…
Instant instant = myResultSet.getObject( … , Instant.class ) ;
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The "right" date type totally depends on your application; however, java.util.Calendar is generally accepted as the replacement for java.util.Date as it provides more functionality (especially regarding extraction of individual date elements like year, month, etc). In reality, Date can be much easier to use for certain situations (and is the one used by Java's own DateFormat classes), so it's a judgement call.
It's not difficult to convert between the two so I would pick one and stick with it consistently for your API. If I were to pick one I'd use Date because it's the simplest, IMHO.

Why were most java.util.Date methods deprecated?

When you look at the javadoc of the java.util.Date class, most of the methods are deprecated. Why was this done?
Well, for two related reasons. It was a very poor implementation of the concept of Dates and Times and it was replaced by the Calendar class.
The Calendar class, although an improvement, leaves a lot to be desired as well, so for serious Date/Time work, everyone recommends Joda-Time. Java 8 brings the new java.time.* package, inspired by Joda-Time, defined by JSR-310, and intended to supplant the old Date/Calendar classes.
Edit: In response to the specific question of why the implementation is poor, there are many reasons. The JavaDoc sums it up as follows:
Unfortunately, the API for these functions was not amenable to internationalization.
In addition to this general deficiency (which covers issues like the lack of a Time Zone component as well as the date formatting which is better handled in DateFormat and the inability to have a non-Gregorian calendar representation), there are specific issues which really hurt the Date class, including the fact that year is presented in an offset of 1900 from Common Era year.
Calendar has its own problems, but even as early as JDK 1.1 it was obvious that java.util.Date was not going to cut it. Even though Calendar is arguable the worst JDK API, it has taken until version 7 to attempt to address it.
Date is mutable
Date doesn't have support for time zones
The latter led to it being replaced by Calendar. And the former, combined with the ease-of-use, lead to both being replaced by Joda-Time / JSR-310 (java.time.* package)
They're deprecated because Date was written as fast as possible back in the day when they wanted to rush the JDK out the door.
It turns out the Dates and Calendars are Hard. So, they created the Calendar class, which much more thought, in order to handle the Hard Parts of working with calendars.
They deprecated the Date methods and delegated to Calendar because they didn't want to change the behavior of the existing Date methods, and possibly break existing applications.
Here's a good answer straight from Oracle: http://www.oracle.com/technetwork/articles/java/jf14-date-time-2125367.html
A long-standing bugbear of Java developers has been the inadequate support for the date and time use cases of ordinary developers.
For example, the existing classes (such as java.util.Date and SimpleDateFormatter) aren’t thread-safe, leading to potential concurrency issues for users—not something the average developer would expect to deal with when writing date-handling code.
Some of the date and time classes also exhibit quite poor API design. For example, years in java.util.Date start at 1900, months start at 1, and days start at 0—not very intuitive.
... java.util.Date represents an instant on the timeline—a wrapper around the number of milli-seconds since the UNIX epoch—but if you call toString(), the result suggests that it has a time zone, causing confusion among developers.
I don't know the official reason why it has been deprecated, but as far as I can tell GregorianCalendarand Joda-Time support operations on dates, meaning that you can add, for instance, a day to a date and have its month and year updated accordingly.
For instance, say you want to compute the day after the current date and today is May 31st; with java.util.Date, you just have getDays() +1, which returns 32, and you have to handle the knowledge that the current month doesn't have 32 days by yourself; with GregorianCalendaror Joda.time, adding a day to May 31st results in an object representing June 1st, hiding the complexity from your sight.

Java Date vs Calendar

Could someone please advise the current "best practice" around Date and Calendar types.
When writing new code, is it best to always favour Calendar over Date, or are there circumstances where Date is the more appropriate datatype?
Date is a simpler class and is mainly there for backward compatibility reasons. If you need to set particular dates or do date arithmetic, use a Calendar. Calendars also handle localization. The previous date manipulation functions of Date have since been deprecated.
Personally I tend to use either time in milliseconds as a long (or Long, as appropriate) or Calendar when there is a choice.
Both Date and Calendar are mutable, which tends to present issues when using either in an API.
The best way for new code (if your policy allows third-party code) is to use the Joda Time library.
Both, Date and Calendar, have so many design problems that neither are good solutions for new code.
Date and Calendar are really the same fundamental concept (both represent an instant in time and are wrappers around an underlying long value).
One could argue that Calendar is actually even more broken than Date is, as it seems to offer concrete facts about things like day of the week and time of day, whereas if you change its timeZone property, the concrete turns into blancmange! Neither objects are really useful as a store of year-month-day or time-of-day for this reason.
Use Calendar only as a calculator which, when given Date and TimeZone objects, will do calculations for you. Avoid its use for property typing in an application.
Use SimpleDateFormat together with TimeZone and Date to generate display Strings.
If you're feeling adventurous use Joda-Time, although it is unnecessarily complicated IMHO and is soon to be superceded by the JSR-310 date API in any event.
I have answered before that it is not difficult to roll your own YearMonthDay class, which uses Calendar under the hood for date calculations. I was downvoted for the suggestion but I still believe it is a valid one because Joda-Time (and JSR-310) are really so over-complicated for most use-cases.
tl;dr
advise the current "best practice" around Date and Calendar
is it best to always favour Calendar over Date
Avoid these legacy classes entirely. Use java.time classes instead.
For a moment in UTC, use Instant(the modern equivalent of Date)
For a moment in a particular time zone, use ZonedDateTime(the modern equivalent of GregorianCalendar)
For a moment in a particular offset-from-UTC, use OffsetDateTime(no equivalent in legacy classes)
For a date-time (not a moment) with unknown time zone or offset, use LocalDateTime(no equivalent in legacy classes)
Details
The Answer by Ortomala Lokni is right to suggest using the modern java.time classes rather than the troublesome old legacy date-time classes (Date, Calendar, etc.). But that Answer suggests the wrong class as equivalent (see my comment on that Answer).
Using java.time
The java.time classes are a vast improvement over the legacy date-time classes, night-and-day difference. The old classes are poorly-designed, confusing, and troublesome. You should avoid the old classes whenever possible. But when you need to convert to/from the old/new, you can do so by calling new methods add to the old classes.
For much more information on conversion, see my Answer and nifty diagram to another Question, Convert java.util.Date to what “java.time” type?.
Searching Stack Overflow gives many hundreds of example Questions and Answers on using java.time. But here is a quick synopsis.
Instant
Get the current moment with an Instant. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
Instant instant = Instant.now();
ZonedDateTime
To see that same simultaneous moment through the lens of some particular region’s wall-clock time, apply a time zone (ZoneId) to get a ZonedDateTime.
Time zone
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone();
Offset
A time zone is a region’s history of changes in its offset-from-UTC. But sometimes you are given only an offset without the full zone. In that case, use the OffsetDateTime class.
ZoneOffset offset = ZoneOffset.parse( "+05:30" );
OffsetDateTime odt = instant.atOffset( offset );
Use of a time zone is preferable over use of a mere offset.
LocalDateTime
The “Local” in the Local… classes means any locality, not a particular locality. So the name can be counter-intuitive.
LocalDateTime, LocalDate, and LocalTime purposely lack any information about offset or time zone. So they do not represent actual moments, they are not points on the timeline. When in doubt or in confusion, use ZonedDateTime rather than LocalDateTime. Search Stack Overflow for much more discussion.
Strings
Do not conflate date-time objects with strings that represent their value. You can parse a string to get a date-time object, and you can generate a string from a date-time object. But the string is never the date-time itself.
Learn about standard ISO 8601 formats, used by default in the java.time classes.
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Using a JDBC driver compliant with JDBC 4.2 or later, you may exchange java.time objects directly with your database. No need for strings nor java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
Date is best for storing a date object. It is the persisted one, the Serialized one ...
Calendar is best for manipulating Dates.
Note: we also sometimes favor java.lang.Long over Date, because Date is mutable and therefore not thread-safe. On a Date object, use setTime() and getTime() to switch between the two. For example, a constant Date in the application (examples: the zero 1970/01/01, or an applicative END_OF_TIME that you set to 2099/12/31 ; those are very useful to replace null values as start time and end time, especially when you persist them in the database, as SQL is so peculiar with nulls).
I generally use Date if possible. Although it is mutable, the mutators are actually deprecated. In the end it basically wraps a long that would represent the date/time. Conversely, I would use Calendars if I have to manipulate the values.
You can think of it this way: you only use StringBuffer only when you need to have Strings that you can easily manipulate and then convert them into Strings using toString() method. In the same way, I only use Calendar if I need to manipulate temporal data.
For best practice, I tend to use immutable objects as much as possible outside of the domain model. It significantly reduces the chances of any side effects and it is done for you by the compiler, rather than a JUnit test. You use this technique by creating private final fields in your class.
And coming back to the StringBuffer analogy. Here is some code that shows you how to convert between Calendar and Date
String s = "someString"; // immutable string
StringBuffer buf = new StringBuffer(s); // mutable "string" via StringBuffer
buf.append("x");
assertEquals("someStringx", buf.toString()); // convert to immutable String
// immutable date with hard coded format. If you are hard
// coding the format, best practice is to hard code the locale
// of the format string, otherwise people in some parts of Europe
// are going to be mad at you.
Date date = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH).parse("2001-01-02");
// Convert Date to a Calendar
Calendar cal = Calendar.getInstance();
cal.setTime(date);
// mutate the value
cal.add(Calendar.YEAR, 1);
// convert back to Date
Date newDate = cal.getTime();
//
assertEquals(new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH).parse("2002-01-02"), newDate);
Dates should be used as immutable points in time; Calendars are mutable, and can be passed around and modified if you need to collaborate with other classes to come up with a final date. Consider them analogous to String and StringBuilder and you'll understand how I consider they should be used.
(And yes, I know Date isn't actually technically immutable, but the intention is that it should not be mutable, and if nothing calls the deprecated methods then it is so.)
With Java 8, the new java.time package should be used.
Objects are immutable, time zones and day light saving are taken into account.
You can create a ZonedDateTime object from an old java.util.Date object like this:
Date date = new Date();
ZonedDateTime zonedDateTime = date.toInstant().atZone(ZoneId.systemDefault());
I always advocate Joda-time. Here's why.
the API is consistent and intuitive. Unlike the java.util.Date/Calendar APIs
it doesn't suffer from threading issues, unlike java.text.SimpleDateFormat etc. (I've seen numerous client issues relating to not realising that the standard date/time formatting is not thread-safe)
it's the basis of the new Java date/time APIs (JSR310, scheduled for Java 8. So you'll be using APIs that will become core Java APIs.
EDIT: The Java date/time classes introduced with Java 8 are now the preferred solution, if you can migrate to Java 8
A little bit late at party, but Java has a new Date Time API in JDK 8. You may want to upgrade your JDK version and embrace the standard. No more messy date/calendar, no more 3rd party jars.
Date should be re-developed. Instead of being a long interger, it should hold year, month, date, hour, minute, second, as separate fields. It might be even good to store the calendar and time zone this date is associated with.
In our natural conversation, if setup an appointment at Nov. 1, 2013 1pm NY Time, this is a DateTime. It is NOT a Calendar. So we should be able to converse like this in Java as well.
When Date is stored as a long integer (of mili seconds since Jan 1 1970 or something), calculating its current date depends on the calendar. Different calendars will give different date. This is from the prospective of giving an absolute time (eg 1 trillion seconds after Big Bang). But often we also need a convenient way of conversation, like an object encapsulating year, month etc.
I wonder if there are new advances in Java to reconcile these 2 objectives. Maybe my java knowledge is too old.
Btw "date" is usually tagged as "obsolete / deprecated" (I dont know exactly why) - something about it is wrote there
Java: Why is the Date constructor deprecated, and what do I use instead?
It looks like it's a problem of the constructor only- way via new Date(int year, int month, int day), recommended way is via Calendar and set params separately .. (Calendar cal = Calendar.getInstance();
)
I use Calendar when I need some specific operations over the dates like moving in time, but Date I find it helpful when you need to format the date to adapt your needs, recently I discovered that Locale has a lot of useful operations and methods.So I'm using Locale right now!

Categories

Resources