Hounshell
Hounshell

Reputation: 5459

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:

Upvotes: 18

Views: 1311

Answers (3)

Basil Bourque
Basil Bourque

Reputation: 338326

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?

Upvotes: 4

Dave Newton
Dave Newton

Reputation: 160181

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.

Upvotes: 17

maerics
maerics

Reputation: 156404

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.

Upvotes: 1

Related Questions