Monday nights are research-something-new nights, and todays entry is Joda Time. Does it kick J2SE dates arse, is it wonderful, or is it yet another date fuckup.
Joda Time (0.95) comes in a 450k jar file. Chunky ’tis true, but I’m sure we’re all so tired of java.util.Calendar that we’ll happily swalllow this lump.
The Olympics plus a need to go read Tolkien and exercise mean I’m surprisingly out of time already on my research-something-new-night, but I managed to see pass a few facets of J-T.
First off, we can print out the current moment:
// Now System.out.println( “Now: ” + new DateTime() ); System.out.println( “Today: ” + new DateOnly() ); System.out.println( “Time: ” + new TimeOnly() );
I assume clashes with util.Date, sql.Date and sql.Time lead them to use the slightly ungainly Only class names. This is probably worthwhile as we would think a new Date() was both a date and a time. Here’s the output:
Now: 2004-08-16T21:43:18.289-04:00Today: 2004-08-16Time: 21:43:18.594
Next up, making a historic date:
// Printing a date DateOnly bday = new DateOnly(1975, 11, 13); System.out.println( “BDay: ” + bday );
Output:
BDay: 1975-11-13
One of the best new things we get with Joda-Time is a Duration/Interval structure. This is sorely missed in the J2SE Date system, and is worth it alone.
// Working out my age DateOnly now = new DateOnly(); DateOnly bday = new DateOnly(1975, 11, 13); Interval age = new Interval(bday, now); System.out.println( “Age: ” + DurationFormat.getInstance() .getDefault().print(age.getDuration()) );
Output:
Age: 28 years, 9 months and 14 days
Leap years are often a big deal. Let’s roll over from Feb 28th to Feb 29th:
// Roll into a leap year DateOnly feb28 = new DateOnly(2000, 02, 28); MutableDateTime feb29 = feb28.toMutableDateTime(); feb29.addDays(1); System.out.println( “Leap: ” + feb29 );
Output:
Leap: 2000-02-29T00:00:00.000-05:00
And is a date in a leap year?
// Is it a leap year? DateOnly feb28 = new DateOnly(2000, 05, 05); System.out.println( “Leap? ” + feb28.year().isLeap() );
Which outputs true. I like this code, I can ask a date, time, or datetime for its year(), hourOfDay(), weekOfYear() and many others. These return DateTimeFieldProperty objects and let you ask questions about the year etc.
Last up, formatting a DateTime. I’ve left off parsing as I’m trusting that it’s a nice inverse of this:
DateTime now = new DateTime(); DateTimeFormatter fmt = DateTimeFormat.getInstance() .forPattern(”h:mm a ‘on the’ dd’th’ ‘of’ MMMM, yyyy”); System.out.println( “Now: ” + fmt.print(now) );
which prints out:
Now: 9:43 PM on the 16th of August, 2004
Note, the ‘th’ is hardcoded. So a bit of a cheat by me. Would love to see that in the library
These Formatter classes are modelled after the JDK ones with a few extra bits, (though the javadoc doesn’t say which bits are extra), and have Parser equivalents, however they don’t extend java.text.Format. One thing I’d like to see here is a bridge to the java.text.Format stuff.
So let’s review.
Durations. Yum. With formatting.
Date and Time only classes.
NO CALENDAR! You can treat a date like a date, not like a moment in time.
In case that last statement has you thinking it’s Java 1.0 all over again, there’s an Instant class which is equivalent to the undeprecated parts of java.util.Date, and can be used for the optimised part of the systems I presume.
There’s one thing I still want to check, but will do that at work with JProfiler. What’s the memory usage and what’s the speed to create these things. I notice that Instant still has a Chronology class, which is the J-T equivalent of a Calendar it seems. Does this make it a lot worse than java.util.Date?
Will hopefully find time at work to have a look at that and see what it’s like.
Unless it’s terrible, I’m going to be pushing it as a standard library at work.
=============================
- Joda-Time is BSD-compatible licenced. It’s 0.4 version was released back at the start of 2002, so it’s at least 2 and a half years mature.
It’s primary author, Stephen Colebourne, is a Jakarta Commons committer. I therefore may be exhibiting biast.