18

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
Hounshell
  • 5,321
  • 4
  • 34
  • 51
  • 2
    I'm upvoting cause I agree (sadly) that the whole Calendar mishmash is a huge pile of doo. I end up using just Date, or even System.currentTimeMillis(), far too often. – user949300 Dec 14 '11 at 20:53
  • It's no joke! It's just the sad state of affairs of the date APIs in Java... – maerics Dec 14 '11 at 20:54
  • See also: [What's wrong with Java Date & Time API?](https://stackoverflow.com/q/1969442/642706) – Basil Bourque Jan 14 '18 at 23:49
  • 1
    @BasilBourque I’m not sure resurrecting such an old question is worth the effort. – Dave Newton Jan 15 '18 at 01:59
  • @DaveNewton By "resurrecting" do you mean my linking to related Question, or answering this one? Either way, "ignore old Questions" must be a new policy on Stack Overflow, so please point me to documentation on that. Previously this site handed out awards for new activity on old questions. – Basil Bourque Jan 15 '18 at 22:07
  • 1
    @BasilBourque Just because you get a shiny for tickling old questions doesn't mean it's a great idea, or that there aren't more recent questions that are more relevant. You can be sad and crabby all you want--I just don't see the point in un-corpsing seven-year old questions when there are more-recent, more-relevant questions more deserving of attention. – Dave Newton Jan 15 '18 at 22:11

3 Answers3

17

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.

Arjan Tijms
  • 37,782
  • 12
  • 108
  • 140
Dave Newton
  • 158,873
  • 26
  • 254
  • 302
  • Edited question to reflect that. – Hounshell Dec 14 '11 at 20:53
  • @Hounshell It should work on Android, AFAIK, but I haven't done it myself. – Dave Newton Dec 14 '11 at 20:54
  • 2
    It works perfectly fine on Android, when you add the jar to your project. And it's by far, the best date framework. +1 – Guillaume Dec 14 '11 at 20:57
  • What is JSE? (Stupid minimum comment length) – Hounshell Dec 14 '11 at 21:01
  • I agree that Joda-Time is the best solution for date wrangling in Java, in general, but I think it's more important as an API designer to not force unnecessary dependencies on your users (what if their application depends on a different version of Joda-Time than the one your SDK does?). Although, if Joda-Time provides functionality that is essential to your API then go with it and depend on it explicitly. – maerics Dec 14 '11 at 21:02
  • @Hounshell Java Standard Edition. Java. – Dave Newton Dec 14 '11 at 21:03
  • Ah, didn't see the "Joda time" part. Unfortunately I need to stick with core jars shipped with Android, no third-party jars (mostly for the drawbacks that @maerics points out) – Hounshell Dec 14 '11 at 21:04
  • @Hounshell The drawbacks are less interesting than you think since internally your library can do any conversions necessary. Jodatime version differences are a *potential* issue. – Dave Newton Dec 14 '11 at 21:06
  • 1
    The [Joda-Time](http://www.joda.org/joda-time/) project is now in [maintenance mode](https://en.wikipedia.org/wiki/Maintenance_mode), with the team advising migration to the [java.time](http://docs.oracle.com/javase/9/docs/api/java/time/package-summary.html) classes. See [Tutorial by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). – Basil Bourque Jan 14 '18 at 22:51
4

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 deprecated
    Instant replaces java.util.Date. AFAIK, nothing is deprecated in java.time in Java 8 & Java 9.
  • Date's Year is offset from 1900
    Years have sane numbering in java.time, 2018 is the year 2018.
  • Date's Month is zero-indexed while day is one-indexed
    Months 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 mutable
    Virtually 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 GregorianCalendar
    ZonedDateTime 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.
  • Calendar.getTime() returns a Date
    Just 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 count
      Look 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 stuff
    Yes 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?

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
1

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.

maerics
  • 151,642
  • 46
  • 269
  • 291
  • FYI, the troublesome old date-time classes such as [`java.util.Date`](https://docs.oracle.com/javase/9/docs/api/java/util/Date.html), [`java.util.Calendar`](https://docs.oracle.com/javase/9/docs/api/java/util/Calendar.html), and `java.text.SimpleDateFormat` are now [legacy](https://en.wikipedia.org/wiki/Legacy_system), supplanted by the [java.time](https://docs.oracle.com/javase/9/docs/api/java/time/package-summary.html) classes built into Java 8 & Java 9. See [Tutorial by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html). – Basil Bourque Jan 14 '18 at 22:51