java.util.Date vs java.sql.Date

java.util.Date

The java.util.Date represents a specific instant in time, with millisecond precision since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT.

java.util.Date date = new java.util.Date(0L);
System.out.println(date);
                    

Thu Jan 01 07:30:00 SGT 1970

java.sql.Date

The java.sql.Date extends java.util.Date class, is a thin wrapper around a millisecond value (since the "epoch" -January 1, 1970, 00:00:00 GMT) to represent SQL DATE, which keeps years, months and days with no time data.

java.sql.Date sqlDate = new java.sql.Date(0L);
System.out.println(sqlDate);
                    

1970-01-01

You only use java.sql.Date when working with JDBC and databases, like to set a date on a java.sql.PreparedStatement, get a date from a java.sql.ResultSet, etc.

How to Convert java.util.Date to java.sql.Date

java.util.Date to java.sql.Date conversion is necessary when a java.util.Date object needs to be written in a database which the column is used to store Date only, without time. Example of this date are birthdate, passport issue date, etc. java.sql.Date used by JDBC to identify an SQL DATE type.

UtilDateToSqlDateExample.java
import java.text.DateFormat;
import java.text.SimpleDateFormat;

public class UtilDateToSqlDateExample {
    
    public static void main(String[] args) {
        java.util.Date utilDate = new java.util.Date();
        System.out.println("java.util.Date time: " + utilDate);
        java.sql.Date sqlDate = new java.sql.Date(utilDate.getTime());
        System.out.println("java.sql.Date time : " + sqlDate);
        
        DateFormat df = new SimpleDateFormat("dd/MM/YYYY hh:mm:ss");
        System.out.println("Date formatted     : " + df.format(utilDate));
    }
}
                    

java.util.Date time: Thu Aug 01 01:49:48 SGT 2019 java.sql.Date time : 2019-08-01 Date formatted : 01/08/2019 01:49:48

In the above example, we use getTime() method of java.util.Date to java.sql.Date constructor. The millisecond values wrapped by a java.sql.Date instance is 'normalized' by setting the hours, minutes, seconds, and milliseconds to zero in the particular time zone with which the instance is associated. And the result, as you can see, java.util.Date has both date and time information, but java.sql.Date only retain date information.

How to Convert java.sql.Date to java.util.Date

Vice versa, java.sql.Date to java.util.Date conversion is necessary when we need to read from database, and pass it to a java.util.Date variable.

SqlDateToUtilDateExample.java
import java.text.DateFormat;
import java.text.SimpleDateFormat;

public class SqlDateToUtilDateExample {
    
    public static void main(String[] args) {
        java.sql.Date sqlDate = java.sql.Date.valueOf("1980-04-09");
        System.out.println("java.sql.Date time : " + sqlDate);
        java.util.Date utilDate = new java.util.Date(sqlDate.getTime());
        System.out.println("java.util.Date time: " + utilDate);
        
        DateFormat df = new SimpleDateFormat("dd/MM/YYYY hh:mm:ss");
        System.out.println("Date formatted     : " + df.format(utilDate));
    }
}
                    

java.sql.Date time : 1980-04-09 java.util.Date time: Wed Apr 09 00:00:00 SGT 1980 Date formatted : 09/04/1980 12:00:00

In above example, we set java.sql.Date to 9 April 1980. When we convert it to java.util.Date, the time component are set to 00:00:00.

Putting it All Together

In following example, we will implement what we have learn so far in a complete SQL INSERT example. First, we create a test table in our database. In this example, I'll use PostgreSQL.

create table test_date ( curr_date date );

The following example demonstrates every step you need to insert the current date (get via new java.util.Date()) into the date field of an SQL database table.

SqlDateInsertExample.java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;

public class SqlDateInsertExample {
 
    public static void main(String[] args) throws Exception {
        // (1) connect to postgresql database
        String url = "jdbc:postgresql://localhost/coffeeshop";
        Class.forName("org.postgresql.Driver");

        try (Connection conn = DriverManager.getConnection(url, "barista", "espresso")) {
            // (2) set java.sql.Date with current Date (and time)
            java.util.Date utilDate = new java.util.Date();
            java.sql.Date sqlDate = new java.sql.Date(utilDate.getTime());
            // (3) insert java.sql.Date to DB
            String query = "INSERT INTO test_date(curr_date) VALUES (?)";
            try (PreparedStatement pst = conn.prepareStatement(query)) {
                pst.setDate(1, sqlDate);
                
                // (4) execute update
                pst.executeUpdate();
            }
        }
    }
}
                    

The example shows how to connect to a PostgreSQL database, construct a java.util.Date object, convert those java.util.Date object into a java.sql.Date object, create and use an SQL INSERT statement in a Java PreparedStatement, then execute this SQL INSERT statement. It resulted that our date is inserted into database. Let's confirm that:

$ psql coffeeshop barista
Password for user barista:
psql (9.2.1)
Type "help" for help.

coffeeshop=> select * from test_date;
 curr_date
------------
 2019-08-01
(1 row)

Yes, it's confirmed. The conversion and insertion worked as expected. Now, to read from database:

SqlDateQueryExample.java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;

public class SqlDateQueryExample {
 
    public static void main(String[] args) throws Exception {
        // (1) connect to postgresql database
        String url = "jdbc:postgresql://localhost/coffeeshop";
        Class.forName("org.postgresql.Driver");

        try (Connection conn = DriverManager.getConnection(url, "barista", "espresso")) {
            // (2) create statement and query
            Statement stmt = conn.createStatement();
            ResultSet rs = stmt.executeQuery("SELECT curr_date FROM test_date");
            while ( rs.next() ) {
                java.sql.Date currSqlDate = rs.getDate("curr_date");
                java.util.Date currDate = new java.util.Date(currSqlDate.getTime());
                
                // (3) print java.util.Date result
                System.out.println(currDate);
            }
        }
    }
}
                    

Thu Aug 01 00:00:00 SGT 2019

The example above shows how to create and use an SQL QUERY statement in a Java Connection, get the result as java.sql.Date and convert it to java.util.Date.

Conclusion

java.sql.Date used in JDBC to store (and use to retrieve) a date only value. java.util.Date able to keeps both date and time, and used in general scenario, but considered as obsolete after Java 8. If you are using Java 8, then better to use new Date/Time API in java.time.* package.

Reference: