1. Overview

In this tutorial, we’re going to compare two date classes: java.util.Date and java.sql.Date.

Once we complete the comparison, it should be clear which one to use and why.

2. java.util.Date

The java.util.Date class represents a particular moment in time, with millisecond precision since the 1st of January 1970 00:00:00 GMT (the epoch time). The class is used to keep coordinated universal time (UTC).

We can initialize it in two ways.

By calling the constructor:

Date date = new Date();

which will create a new date object with time set to the current time, measured to the nearest millisecond.

Or by passing a number of milliseconds since the epoch:

long timestamp = 1532516399000; // 25 July 2018 10:59:59 UTC
Date date = new Date(timestamp);

Let’s note that other constructors, present prior to Java 8, are deprecated now.

However, Date has a number of issues and overall its usage isn’t recommended anymore.

It’s mutable. Once we initialize it, we can change its internal value. For example, we can call the setTime method:

date.setTime(0); // 01 January 1970 00:00:00

To learn more about the advantages of immutable objects, check out this article: Immutable Objects in Java.

It also doesn’t handle all dates very well. Technically, it should reflect coordinated universal time (UTC). However, that depends on an operating system of the host environment.

Most modern operating systems use 1 day = 24h x 60m x 60s = 86400 seconds, which as we can see, doesn’t take the “leap second” into account.

With the introduction of Java 8, java.time package should be used. Prior to Java 8, an alternative solution was available – Joda Time.

3. java.sql.Date

The java.sql.Date extends java.util.Date class.

Its main purpose is to represent SQL DATE, which keeps years, months and days. No time data is kept.

In fact, the date is stored as milliseconds since the 1st of January 1970 00:00:00 GMT and the time part is normalized, i.e. set to zero.

Basically, it’s a wrapper around java.util.Date that handles SQL specific requirements. java.sql.Date should be used only when dealing with databases.

However, as java.sql.Date doesn’t hold timezone information, the timezone conversion between our local environment and database server depends on an implementation of JDBC driver. This adds another level of complexity.

Finally, let’s note, in order to support other SQL data types: SQL TIME and SQL TIMESTAMP, two other java.sql classes are available: Time and Timestamp.

The latter, even though extends from java.util.Date, supports nanoseconds.

4. Conclusion

Class java.util.Date stores a date-time value as milliseconds since the epoch. java.sql.Date stores a date only value and is commonly used in JDBC.

Handling dates is tricky. We need to remember about special cases: leap seconds, different timezones etc. When dealing with JDBC we can use java.sql.Date with caution.

If we’re going to use java.util.Date, we need to remember about its shortcomings. If using Java 8 then better not to use java.util.Date at all.