Dealing with dates in Java is notoriously difficult. If you ask 10 Java programmers how they would represent "July 10, 2004" you will get about 4 different answers. This has lead to countless avoidable bugs as developers struggle to match their everyday concept of a 'date' to the API. Java needs a clear, simple class which encapsulates a 'date'.
Here are four situations involving dates that are much harder to program in Java than they should be:
import java.io.IOException; import java.io.Serializable; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; import java.util.TimeZone; public final class CalendarDate implements Comparable, Serializable { public static final int SUNDAY = 1; public static final int MONDAY = 2; public static final int TUESDAY = 3; public static final int WEDNESDAY = 4; public static final int THURSDAY = 5; public static final int FRIDAY = 6; public static final int SATURDAY = 7; public static final int JANUARY = 1; public static final int FEBRUARY = 2; public static final int MARCH = 3; public static final int APRIL = 4; public static final int MAY = 5; public static final int JUNE = 6; public static final int JULY = 7; public static final int AUGUST = 8; public static final int SEPTEMBER = 9; public static final int OCTOBER = 10; public static final int NOVEMBER = 11; public static final int DECEMBER = 12; public static final CalendarDate EARLIEST = new CalendarDate(1600, 1, 1); public static final CalendarDate LATEST = new CalendarDate(2999, 12, 31); public CalendarDate(int year, int month, int dayOfMonth); public CalendarDate(TimeZone tzone, Date instantInTime); public CalendarDate(TimeZone tzone); public int getDayOfMonth(); public int getDayOfWeek(); public int getMonth(); public int getYear(); public CalendarDate addDays(int numDays); public int daysUntil(CalendarDate otherDay); public CalendarDate addMonths(int numMonths); public int monthsUntil(CalendarDate otherDay); public static boolean isLeapYear(int year); public int compareTo(Object other); public boolean isBefore(CalendarDate other); public boolean isAfter(CalendarDate other); public boolean equals(Object other); public int hashCode(); public String toString(); private void writeObject(java.io.ObjectOutputStream out) throws IOException; private void readObject(java.io.ObjectInputStream in) throws IOException; public Date toDate(TimeZone timezone); public Date toDate(TimeZone timezone, int hour, int min, int sec); }
From Brian S O'Neill, Joda-Time development team member, 30 November 2004 06:48:
You list four points. On points three and four, I completely
agree. DateOnly made no sense to have a time zone. In the
latest version, 0.98, we chucked DateOnly. There are now two
classes in its place, DateMidnight and YearMonthDay.
DateMidnight is pretty much like DateOnly, but YearMonthDay
is completely time zone agnostic.
On point two, you question the need to have a new time zone class. We did this primarily to maintain consistency. Different JVMs have different time zone implementations, and some don't properly implement historical transitions. We've updated our FAQ because this is in fact a FAQ. Another reason is performance. The way Joda-Time works, it needs to perform frequent time zone lookups. The Joda time zone class is much faster than the standard one, even the jdk1.4 version.
As for point one, this is a matter of taste. Most of the classes in Joda-Time are not "user level" classes. We've updated our javadocs to reflect this. If you only look at the classes in the main package and in format, the set is much smaller.
Implementing a calendar system from scratch requires a lot of code. You just can't see it with the jdk classes. The implementation code is hidden. Joda-Time aims to provide much more flexibility for those that may wish to extend it.
CalendarDate provides a nice simple interface for performing "common" operations, but it relies internally on the jdk classes. All the complexity is hidden behind many levels of abstraction. CalendarDate can just as well be implemented with Joda-Time and you'd still have the simple interface you desire.
From Stephen Colebourne, Joda-Time development team member, 06 November 2004 17:03:
I would like to go through your comments on the website:
> 1. It is far too complicated. There are 100+ new classes with many levels of inheritance and interface implementations.
When we set out to do a complete cleanroom implementation it was always
going to get complicated ;-) Although sometimes even I think there are
places that it could have been simpler. However, when you target multiple
calendar systems, flexibiilty and high performance, size tends to be the
trade-off.
> 2. It replaces standard API classes that aren't broken (like java.util.TimeZone). Yes, the replacement is 'ISO-compliant' and immutable, but that isn't enough to make developers want to learn a new class. And if you want to use any of it, you're forced to reference all these replacement classes.
One problem with the JDK TimeZone is that there is no easy way to replace
the timezone rules. These rules are updated 8+ times a year in an OSS
database. By having our own timezone we can pick up the latest set of rules.
Plus its immutable and faster ;-)
> 3. It doesn't make a clear distinction between a 'date' and a 'time'.
For example, org.joda.time.DateOnly implements a ReadableInstant, so a date
is also a point in time. This means I can pass a date (of type DateOnly)
into a method which expects a time (of type ReadableInstant).
Yeh, that was a dumb mistake. It got corrected over the summer, and the 0.98
release introduces the solution. Now there is a category of date/time
classes without time zones. But we also now explicitly support the concept
of DateMidnight - a full datetime (with zone) but with the time fixed at
midnight.
> 4. The classes don't match the everyday concepts they try to represent.
For example, DateOnly has a getDateTimeZone() method - but what is the
timezone of Easter Sunday or John's Birthday?
See #3
You may also be interested in http://timeandmoney.sourceforge.net/ although I don't know how active the project is.