DATE4J

But, soft! what code in yonder program breaks?
It is the Date, and dim grows the Sun!
Arise, fair Sun, and kill the egregious Date,
Who is already sick and pale with grief,
That we, perchance, art more fair than she.

This site offers a Java tool called date4j. It's an alternative to Date, Calendar, and related Java classes. The JDK's treatment of dates is likely the single most suctorial aspect of the Java core libraries. It needs improvement.

The main goals of date4j are:

Problem

For reference, here are the JDK classes related to dates.

Date and its subclasses:

The calendar and time zone classes:

The formatting and parsing classes:

The problem is that the above classes are widely regarded as being of disturbingly poor quality, for various reasons:

Joda Time

The Joda Time library is used by some programmers as an alternative to the JDK date classes. Although it's a significant improvement over the JDK, Joda Time is not without its own drawbacks:

How Databases Treat Dates

Most databases model dates and times using the Gregorian Calendar in an aggressively simplified form, in which:

How Databases Treat Time Zones

For storing time zone information, many databases don't include any data types at all. DB2, MySQL, and SQLServer are all in this category. Applications which find it necessary to store explicit time zones will, when using such databases, need to create their own solution. Given the problems noted below, such ad hoc solutions are not necessarily a bad thing.

Some databases, such as Oracle and PostgreSQL, do indeed supply data types explicitly for handling time zones, but the implementations are a mess.

First of all, take the ANSI SQL standard. Its very definition of time zone doesn't match the definition of TimeZone in Java. Why? Because ANSI SQL defines time zones as a fixed offset from Universal Time. But an offset is not a time zone. Since they don't take into account summer hours, they don't match what most people think of as a proper time zone. Such a glaring mismatch of fundamental abstractions is bound to be a fruitful source of error, annoyance, and widespread confusion.

PostgreSQL
PostgreSQL has 2 data types named TIME WITH TIME ZONE and TIMESTAMP WITH TIME ZONE. These columns store time zone/offset information, right? Wrong. Neither a time zone nor an offset is stored in these fields. From their documentation:

"All timezone-aware dates and times are stored internally in UTC. They are converted to local time in the zone specified by the timezone configuration parameter before being displayed to the client."

So, what you have here is a misrepresentation of what is being stored. The name of the data type clearly implies that a time zone/offset is being stored, but that's clearly not the case. There is unequivocally no explicit time zone/offset is stored in these columns. None whatsoever. Rather, an implicit offset is used, and a calculation is applied to the data, using particular policies defined by the database, involving the difference between 2 offsets.

Oracle
Oracle has 2 data types named TIMESTAMP WITH TIME ZONE and TIMESTAMP WITH LOCAL TIME ZONE.

TIMESTAMP WITH TIME ZONE stores an offset in the column. Again, an offset is not the same thing as a time zone.

TIMESTAMP WITH LOCAL TIME ZONE doesn't store explicit offset information at all. Rather, it implicitly uses the database's offset. Again, when returning this data to a client, a database-defined policy is applied (using a difference in offsets), a calculation is performed, and the altered value is returned.

The difference in offsets is usually (but not always) calculated using DBTIMEZONE (the database default) and SESSIONTIMEZONE (the session setting). Again, such policies may or may not be relevant or appropriate for an application.

Oracle does mention the idea of time zones as opposed to offsets (as in 'America/Montreal'), but these items are apparently not stored anywhere in a database column.

Database Offset Calculations
Clearly, databases that do attempt to manage time zones for you are applying a number of 'baked-in' policies. But such calculations are a major annoyance. Here's why:

Solution

The date4j tool chooses to focus on how databases can store dates and times in a simple style (without time zone/offset), and not on modeling the arcane details of civil timekeeping.

In summary:

Recommendations for using date4j:

Examples

Here are some quick examples of using date4j's DateTime class (more examples are available here):
DateTime dateAndTime = new DateTime("2010-01-19 23:59:59");
DateTime dateAndTime = new DateTime("2010-01-19T23:59:59.123456789");
DateTime dateOnly = new DateTime("2010-01-19");
DateTime timeOnly = new DateTime("23:59:59");
DateTime dateOnly = DateTime.forDateOnly(2010,01,19);
DateTime timeOnly = DateTime.forTimeOnly(23,59,59,0);

DateTime dt = new DateTime("2010-01-15 13:59:15");
boolean leap = dt.isLeapYear(); //false
dt.getNumDaysInMonth(); //31
dt.getStartOfMonth(); //2010-01-01, 00:00:00.000000000
dt.getEndOfDay(); //2010-01-15, 23:59:59.999999999
dt.format("YYYY-MM-DD"); //formats as '2010-01-15'
dt.plusDays(30); //30 days after Jan 15
dt.numDaysFrom(someDate); //returns an int
dueDate.lt(someDate); //less-than
dueDate.lteq(someDate); //less-than-or-equal-to

Although DateTime carries no TimeZone information internally, there are methods that take a TimeZone as a parameter:

DateTime now = DateTime.now(someTimeZone);
DateTime today = DateTime.today(someTimeZone);
DateTime fromMilliseconds = DateTime.forInstant(31313121L, someTimeZone);
birthday.isInFuture(someTimeZone);
dt.changeTimeZone(fromOneTimeZone, toAnotherTimeZone);

Explicit Time Zones

Many protest that it shouldn't be necessary to pass the time zone explicitly to the now and today methods. Naturally enough, they have become used to the JDK's style, after many years of use:
Date now = new Date();
Date4j's style of requiring the time zone is not an oversight, but a deliberate decision. Here are its justifications: In summary, the date4j library takes the position that passing a time zone explicitly to its now and today methods helps it accomplish the main goal of a well-designed API: to increase the clarity of the code, and decrease the likelihood of programmer error.

Contributors

The contributors to the date4j project are: For interacting with JSON data, Giampaolo Trapasso (Italy) wrote a small adaptor to make DateTime compatible with the GSON library.

Maven, Gradle, Buildr Etc

For users of tools that can source the Maven Central Repository, Ian Darwin has kindly provided the following:

WEB4J

The date4j code was extracted out of a Java web application framework called WEB4J. Both date4j and web4j were created by John O'Hanley.

In WEB4J, there is a class of the same name as in date4j, DateTime. It's structure is almost the same as that of date4j's version. The main differences are: