Forget about java.util.Date, it’s Joda-Time!

Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedIn

Once upon a time all we had was java.util.Date and it was not good… then Sun introduced java.util.Calendar, and it got worse! How often do you sit at your keyboard and wonder how you can avoid writing date manipulation code just because you hate to look at the resulting mess? Maybe your project uses service or utility classes to hide the ugliness, but you know it’s still there. Well, stop hiding, there’s something better: Joda-Time!


What’s so amazing about Joda-Time? It makes dealing with time in Java intuitive, simple and clean. No, really! Let’s take an example of a common mistake that crops up every now and then when using java.util.Date. The project has a class that handles rental agreements, and one of the methods checks if the lease is still valid: ie, leaseEndDate >= today. A test was written (yay! the project has tests!) with the following assert:

AssertTrue(xxx.isLeaseValid(2010,12,1));

The implementation code looks like this:

function boolean isLeaseValid(int year, int month, int day){
Calendar calender = Calendar.getInstance();
calendar.clear();
calendar.set(year, month - 1, day);
return calendar.before( Calendar.getInstance() );
}

The test definitely passes today, but come December 1, 2010 it will start to fail. So how does the organization fix this? The team puts their heads together and decides to allow the method to take in the calendar representing the current time as well, so the test can override the current value… then they realize that this kind of thing is all over the code, maybe they should have a DateService instead so that the tests can override it and set the current time… and then somebody says “why don’t we switch to Joda-Time instead?”. What does this same method look like when you use Joda-Time?

function boolean isLeaseValid(int year, int month, int day){
DateTime endDate = new DateTime(year, month, day, 0, 0, 0, 0);
return endDate.isBeforeNow();
}

At first glance it looks like this didn’t buy us much, sure we didn’t have to subtract one from the month, and now endDate is a DateTime object and not some mysterious “Calendar” object, but it’s still comparing the end date with the current date, and the test will fail on December 1st.

Now comes the best part! Just add one line to your test class:

DateTimeUtil.setCurrentMillisFixed(new DateTime(2010, 9, 19, 0, 0, 0, 0).getMillis());

This sets the current time to September 19, 2010! So the test will not start failing on December 1. No messy Calendar calculations, no overriding methods, super simple, super clean, really easy.

Want to learn more? Check out the excellent documentation @ http://joda-time.sourceforge.net/ The project was started in 2002, and there’s an active forum.

What libraries do you use? Or do you actually like Calendar?

Disclaimer: The code used in this article is written to illustrate a point, it is not production quality!

2 Comments

  • 1
    2010-09-20 - 08:29 | Permalink

    Excellent! I would suggest adding code to reset the current time to normal behaviour after the test is run to prevent pontential failure in the other tests in your test suite and to isolate the specific current time to the specific test case only.

    For example adding this line in a tearDown (@After) method.

    
    DateTimeUtils.setCurrentMillisSystem()
    
    
  • 2
    2010-09-27 - 09:59 | Permalink

    Absolutely!

  • Leave a Reply

    Your email address will not be published. Required fields are marked *

    This site uses Akismet to reduce spam. Learn how your comment data is processed.