Wednesday, July 1

5 Reasons to Insulate Yourself from Java Dates

Java's Date implementation sucks. That's no secret to anyone. Calendar sucks just as much... also no secret. They are difficult to work with and sometimes they make absolutely no sense at all. For instance, why are all the seemingly useful methods in java.util.Date deprecated? What is the real point of java.sql.Date, it provides little value and has all the shortcomings of java.util.Date. Then there's Calendar. A land where something like JANUARY=0 and SUNDAY=1 is perfectly logical. If you want to set a Calendar date, there's a nice method that does this, accepting 3 parameters, year, month, and day. To the uninitiated, should be perfectly reasonable to say:

cal.set(2009,1,1);

The only problem is, it is completely counter-intuitive to the way normal people understand date notation. The result is that a completely reasonable statement ends up setting the incorrect month. Additionally, the numbering method is inconsistent when using days of the week. The constant for Sunday is 1 instead of 0. Lets say you have all that straight, Calendar has one more counter-intuitive "feature". In the normal world, knowing that day values start with 1, what would you expect from the following code?

Calendar cal = Calendar.getInstance();
cal.set(Calendar.DAY_OF_MONTH, 0);
System.out.println(cal.getTime());
cal.set(Calendar.DAY_OF_WEEK, 0);
System.out.println(cal.getTime());


I would personally expect an IndexOutOfBoundsException since days are supposed to start with 1. Not so. Calendar KNOWS you meant to subtract a day, so it nicely rolls the date for you. Which means you will end up with a day you probably didn't intend AND you could also end up with the wrong month and year. Nice.

Those are a few of many complaints about Java Date/Calendar. Do a Google search on "java date suck" and you'll get a longer list than you want to read, but I think I've made my point. At some point, whether via OpenJDK or by the JSR process or finally deciding to improve their API(not likely), this general crappyness is going to have to change.

The end result is a lot of ugly, non-OO, util code meant to overcome Date/Calendar's shortcomings. If you've been coding in Java for long enough, you've probably seen something like:

Date dt = DateUtil.newDate("01-01-2009");

It's better than doing the dance with Calendar to set the date every time, but to plagarize a saying from a colleague of mine, we're putting a band-aid on cancer here. Those kinds of things make working with dates simpler, but they don't actually correct the issues.

So, reason #1 to insulate yourself from Java dates... the implementation sucks and it's sucked since the beginning of time in Java.

Reason 2: Not everyone requires millisecond precision. If you only need precision to days, why use all the extra memory to pass around useless information for hours, minutes, seconds, and milliseconds. At that point you could use in an int instead of a long.

Reason 3: You can expose methods that make sense in your application or enterprise. If you don't need a "getTime()" method because you're never going to use a long, don't confuse other developers by providing it. If you are an architect and you put in methods you don't intend to use just because they are in the standard implementation, developers will use it and, if you don't intend for them to use it, they will probably end up with something like:

java.util.Date date = new Date(new MyDate("01-01-2009").getTime());

Let's face it, that's a Daily WTF in the making and you, as an architect, have created opportunity for a developer to write this kind of code by exposing methods you don't intend to use.

Reason 4: Your own implementation of Date allows you to wrap the best date implementation available and swap it in and out of your application. This idea is pretty familiar to most people who use a lot of third party libraries and some even like to do this for database adapters. Here's the thing... in reality, you're more likely to change your date implementation than your database. If you're date-related code is based on your own abstraction this becomes a lot easier.

Reason 5: It regulates date handling across the application/enterprise. No one has to question if we're using joda time, java.util.Date, java.sql.Date, or any other date-related functionality. We use our implementation... period.

It's simple to do, it takes very little code, and it will make your date handling code not suck. To me, that's worth the small amount of time it will take to implement.

2 comments:

Vinny said...

I can see pros of using such an implementation. What is your opinion on using this in a project that already has had several iterations and is in it's 7th version?

Also, many of the current libraries out there use java.util.Date. This means, you would have to provide functionality to make your custom date or calendar return a util Date or Calendar at some point.

Do you think there is some room for wtf misuse?

Michael Nishizawa said...

There's room in the best implementations for WTF misuse. Unfortunately, making things easy to use also means that sometimes people who have no business writing code will use it in a way that the builder could not conceive.

As for third party libraries, that is an excellent point. You need a way to convert it to a raw date type but you would want to encapsulate that in some adapter code that is not available to the rest of the code base. It's not a perfect way to do it, but adapter code can be messy anyway. The key is to keep it out of your main codebase.

For a project that is in it's 7th version(I assume you're talking about 7th rewrite), it sounds like that project may have some issues that are in more urgent need of assistance than date issues. However, perhaps improving the way some things are implemented would prevent an 8th rewrite.