Friday, March 5, 2010

The first Date sucked. Can a second Date fix it? JSR 310

Well technically, this is the third Date API. But, it forms a much better title!

JSR 310 is the new Date Time API specification. I'm overjoyed by the fact that Java will finally get the long overdue revamp to the infamous java.util.Date and java.util.Calendar classes. It is nice to see that JSR 310 builds on Joda Time API unlike some other APIs that didn't follow this approach (cough: java.util.logging).

The JSR 310 is in early draft review. And, they are looking for feedback about the API. So, I decided to take a crack at it.

There are a lot of things done right with this API. One of the nicest things is not having to mess around with the pesky Calendar.add(int,int) method. Among a lot of other things, JSR 310 introduces three new classes for date/time handling: LocalDate, LocalTime, LocalDateTime.

Now lets consider what could be better:

You got the money, now give me my constructors:
One thing I don't like is the absence of usable constructors in the three classes LocalDate, LocalTime, LocalDateTime. There are static factory methods that you can use to create the objects but having constructors for the simple usecases would be just nice.

Since LocalDate, LocalTime and LocalDateTime have similar interfaces, I'm going to pick on only one of them. The one that will take the beating is: LocalDate :-)

Compare the following:
Joda Time:
LocalDate date = new LocalDate(2010, 2, 20);

JSR 310:
LocalDate date = LocalDate.of(2010, 2, 20)
This may not be such a big deal to many folks, but I don't see why the constructors shouldn't be exposed especially given that this class is final!

Keep it simple 1: Printing Dates
Joda Time:
LocalDate date = ...
String dateString = date.toString("yyyy/MM/dd");

JSR 310:
LocalDate date = ...
DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendPattern("yyyy/MM/dd").toFormatter()
String dateString = formatter.print(date);

Looks like we could use an overloaded method in the LocalDate class that works like Joda Time. I can imagine that it won't consider all the cases that DateTimeFormatterBuilder handles. But, it can at least address the most general usecase. I could be wrong, I haven't had a chance to use the API much. If so, please feel free to comment and let me know.

Keep it simple 2: Parsing Dates
There is the static method parse in LocalDate
LocalDate date = LocalDate.parse("2010-2-20");
The format that you have to pass it is fixed. For the same reasons as above, it'll be nice to see an overloaded method that takes a string format.

DateAdjusters is awesome:
Example:
LocalDate friday = ...
LocalDate monday = DateAdjusters.nextNonWeekendDay().adjustDate(friday);

Consider a case where we want to obtain the next valid working/custom day instead of the next non weekend day. DateAdjuster is an interface, we could write a custom implementation, but providing a method where developers can hook into the DateAdjusters class would be great.

LocalDate nextWorkingDate = DateAdjusters.nextWorkingDay(new WorkingDayDeterminer() {
public boolean isWorkingDay(LocalDate date) {
return ...;
}
}).adjustDate(friday);

So lets start using it:
Not so fast there. We typically use Date/Time with APIs like JDBC (does anyone use straight JDBC anymore?), Quartz etc. Unless these APIs upgrade to using JSR 310 classes, we won't reap full benefits of using these new classes.

Also, the original Date and Calendar classes are the IE6 of the Java API now. They must die! Or at least be deprecated, so the adoption for these new classes increases.

Finally, what is with the javax.time package name? Not that it bothers me too much, but java.time has an unmatched sex appeal to it.

Ofcourse, you should follow me on twitter.

1 comment:

JodaStephen said...

Thanks for the excellent feedback.

The lack of constructors is deliberate and I would say considered best practice for immutable classes. Internally some of the factory methods perform caching, which is impossible with constructors.

We may need to add simpler printing and parsing methods.

The adjusters can be used directly from a date:

date = date.with(DateAdjusters.nextNonWeekendDay());

We'll need to do something with weekend days (as not everywhere has the same days), but I doubt we need another plugin point.

The javax package name allows the code to be used in JDK 1.6.

Persistance is the responsibility of other expert groups.

thanks for the feedback,
Stephen Colebourne (spec lead)