Converting java.sql.Date & java.util.Date to org.joda.time.LocalDate

ryvantage picture ryvantage · Dec 23, 2013 · Viewed 26.5k times · Source

I am trying to carefully and meticulously clean up some of my older (production) code. One thing I am trying to do is convert all my usages of java.util.Date to LocalDate and DateTime.

However, I noticed one big obstacle tonight as I was working. I had this code:

ResultSet results = stmt.executeQuery();

Date last = results.getDate("LAST_DELIVERY_DATE");
Date next = results.getDate("NEXT_DELIVERY_DATE");
boolean received;
if (last == null && next == null) {
    received = true; // order is not open
} else if (last == null) {
    received = false;
} else {
    received = true;
}

I converted last and next to:

LocalDate last = new LocalDate(results.getDate("LAST_DELIVERY_DATE"));
LocalDate next = new LocalDate(results.getDate("NEXT_DELIVERY_DATE"));

and Netbeans underlined the if == null and said:

Unnecessary test for null - the expression is never null

This makes sense, because a new LocalDate instance won't be null (no new Object() can be).

BUT, in this case and in many cases throughout my program, a null date communicates some essential information. In this case, it shows whether the order 1) is open (or not), 2) has been received (or not).

So, trying to find ways around it, I figured I could instead use this code:

LocalDate last = results.getDate("LAST_DELIVERY_DATE") == null? null : new LocalDate(results.getDate("LAST_DELIVERY_DATE"));
LocalDate next = results.getDate("NEXT_DELIVERY_DATE") == null? null : new LocalDate(results.getDate("NEXT_DELIVERY_DATE"));

But, this just seems ugly to me? Plus, it calls the "ResultSet#getDate()" function twice, which.... correct me if I'm wrong... makes two calls to the database, right?. So, now to convert my code to joda-time I am essentially doubling the time it takes to get java.sql.Date objects from the database...

LocalDate last = LocalDate.fromDateFields(results.getDate("LAST_DELIVERY_DATE"));
LocalDate next = LocalDate.fromDateFields(results.getDate("NEXT_DELIVERY_DATE"));

doesn't work, either, because fromDateFields throws a NullPointerException when it gets a null value.

So, my question is: how do you best handle null dates when your program necessitates having null dates and joda-time? Am I missing something? Is there an easier way to accomplish what I'm after?

Answer

djechlin picture djechlin · Dec 23, 2013

Your code using the ternary operator cannot be that terse precisely because you make two trips to the database. Consider writing a dateutil library with a method like this:

    LocalDate convertToLocalDate(Date date) {
        if(date == null) return null;
        return new LocalDate(date);
    }

IMO making this code clean up at the expense of an often used lightweight static method is a good trade.

Also consider not using Java. In Javascript you could just use || and not have this problem, for instance. I also hear Scala is a good language that solves this with more explicit support for Nullable types. As long as you're cleaning up old code, may as well do it right.