Date Handling in Java

Posted on February 16, 2005 by Scott Leberknight

There has been a thread going around an internal forum at work the past few days on calculating the difference between two dates in weeks, and how to implement that using Java. Of course since working with dates is Java is not at all fun, the code was very verbose and had lots of conversion from Strings to Dates to longs to perform subtraction on the time in milliseconds and then a bunch of basic math to convert milliseconds to weeks. Ugh. Since I've been dabbling a little in Python lately (that is, going through the tutorial very slowly whenever I get a few minutes here and there) I decided to see how this would be accomplished in Python. Here it is:

date_from = date(2004, 2, 17)
date_to = date(2005, 2, 17)
diff = date_to - date_from
diff_in_weeks = diff.days / 7
print diff_in_weeks

And of course the answer it prints is 52. So that was five lines of code including the print statement.

The equivalent code in Java might look something like the following:

GregorianCalendar fromCalendar = new GregorianCalendar(2004, 1, 17); // month is zero-based
long fromDate = fromCalendar.getTimeInMillis();

GregorianCalendar toCalendar = new GregorianCalendar(2005, 1, 17); // month is zero-based
long toDate = toCalendar.getTimeInMillis();

long diffInMillis = toDate - fromDate;
long diffInWeeks = diffInMillis / (1000 * 60 * 60 * 24 * 7); // lots of yuckiness here to convert millis to weeks
System.out.println(diffInWeeks);

So that's seven lines of code including the print statement. That's not that much of a difference, but the difference in readability is a rather large difference. In the Python version, we create two dates and subtract them to get a timedelta object which "represents a duration, the difference between two dates or times" according to the Python docs. We are now working with an object that inherently represents a difference between times and thus the code is very clean. On the other hand, in the Java code we have to convert from a Calendar to a Date to a long, compute the difference in a primitive type that does not inherently represent the difference between times, and do some yucky but still relatively simple math to convert from milliseconds to weeks.

And though I could have used the Date constructor that takes a year, month, and day I decided against that because that constructor and similar ones are deprecated. So I used a GregorianCalendar to obtain the date and then converted to a completely non-natural way to represent a date - a Java primitive long value.

The point is that dealing with dates, times, calendars, etc. in Java is not a very pleasing experience most of the time, and it is beyond me why the Java language does not directly support the notion of ranges, whether they are numeric or dates or times. At the least the Date or perhaps Calendar class could have included a diff() method that would allow you to compute the difference between two dates. Isn't this a pretty common thing to do in many applications? So of course everyone has to write their own version in some DateUtils class just like they have to create StringUtils classes to deal with omissions in String, such as checking if a string is empty or not empty, splitting and joining (prior to JDK 1.4), capitalizing, etc.

And to top it all off, the date and number formatting classes DateFormat and NumberFormat along with MessageFormat are not thread safe. That to me was a very poor design decision since now everyone needs to create their own wrappers or utility classes to be able to use a shared date formatter perhaps using a ThreadLocal to ensure thread safety. Until JDK 1.4 Sun didn't even bother to inform people of potential multithreading issues in the JavaDocs.

This is sort of a silly rant about relatively low-level details, but I think it points out that making your code read along the lines of your domain ensures readability and maintainability, since the code reflects the language of the problem domain and not the programming language. In this case the Python example more cleanly mirrors how you typically think about dates than the Java example, which makes for cleaner and more efficient code.



Post a Comment:
Comments are closed for this entry.