Monday, July 12, 2021

How to convert java.sql.Date to java.util.Date in Java - JDBC Example

You often need to convert java.sql.Date to java.util.Date while interacting with databases from Java application. Since JDBC the Java API for database connectivity uses java.sql.Date to represent and most of the java code accepts java.util.Date, you have no choice but to convert SQL date to util date in Java. Though, there is some fundamental difference between them e.g. java.sql.Date only contains date part e.g. day, month, and year, it doesn't contain any time attributes, but java.util.Date contains both date and time attributes e.g. hour, minutes, seconds, and milliseconds. So, when you convert a java.sql.Date to java.util.Date, the resultant java.util.Date instance has the time part as zero i.e 00:00:00 to reflect midnight.

Btw, I am going to use the same trick to convert an SQL date to the util date, which we have used in the first part to convert java.util.Date to java.sql.Date. The trick involves the getTime() method which returns the number of milliseconds from Epoch time.

Since both java.util.Date and java.sql.Date can be created by passing long millisecond value, this method acts as a bridge between two different classes from java.sql package and java.util package. It's one of the must-know techniques for java programmers working in JDBC. As you can use this to convert java.sql.Date to java.sql.Timestamp as well, as shown in the earlier article.

Btw, if you are new to JDBC and looking for a comprehensive online course to learn JDBC in-depth then I also suggest you check out these free JDBC courses to learn JDBC fundamentals like DAte and Time classes in Java. 

One of the important things to know about java.sql.Date is that it's a subclass of java.util.Date, don't believe me? You can check the source code of java.sql.Date class by yourself, you will find "public class Date extends java.util.Date".

This reminds me of an old incident, I used to teach Java long back and I remember when I was teaching about SQL date to Util date conversion, one of my students asked me, why do we need to convert java.sql.Date to java.util.Date if it's a subclass, can't we just pass it directly to a method expecting java.util.Date?



Good question? No, I like this kind of question and student because it shows they are not just listening but also applying their mind, to be honest, it's very important. Every new information should be validated against existing information we know. This makes learning fast and improves reasoning skills.

The answer is no, you cannot pass java.sql.Date to a method which is expecting java.util.Date. Even though Inheritance will allow you to pass because it's a subclass, it could break your code because of java.sql.Date violates the Liskov Substitution principle. This principle states that a subclass can stand in place of the parent class, which java.sql.Date does not follow.

In order to confirm the definition of SQL DATE, the millisecond values are wrapped by a java.sql.Date instance is normalized by setting the time part e.g. hours, minutes, seconds, and milliseconds to zero in the particular time zone with which the instance is associated. This means all the time-related methods either throws java.lang.IllegalArgumetnException as shown below:

public int getHours() {
   throw new java.lang.IllegalArgumentException();
}

If the method is expecting a java.util.Date calling the getHours() method, then it will break when you pass a java.sql.Date object. This is why it's important for a class to obey the Liskov substitution principle.  See these Java JDBC courses to learn more about SQL date and time classes.


java.sql.Date to java.util.Date Conversion - Example

Now, let's see our sample Java program to convert a java.sql.Date to java.util.Date in JDBC code. In this program, we are connecting to Microsoft SQL Server and then call the Microsoft SQL Server's GETDATE() method using a PreparedStatement.

This method returns today's date which you can read using getDate() method of ResultSet. This gives you an instance of java.sql.Date. After that we cal the getTime() method of java.sql.Date and pass that long millisecond value to java.util.Date to create an instance of the util date. Since SQL date doesn't have a time part you can see the util date also has time part as zero.

import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

/*
 * Java Program to convert java.sql.Date to java.util.Date
 * in JDBC.
 */

public class SQLToUtilDate{

    public static void main(String[] args) {

        java.sql.Date sqlDate = readDateFromDatabase();
        java.util.Date utilDate = new java.util.Date(sqlDate.getTime());
        System.out.println("sql date from database: " + sqlDate);
        System.out.println("util date in Java: " + utilDate);

    }

    public static java.sql.Date readDateFromDatabase() {
        Connection con = null;
        java.sql.Date dateFromDatabse = null;
        try {
            Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
            String url = "jdbc:sqlserver://localhost:42588;";
            DriverManager.setLogWriter(new PrintWriter(System.out, true));
            con = DriverManager.getConnection(url, "root", "root");

            PreparedStatement ps = con.prepareStatement("select GETDATE()");
            ResultSet rs = ps.executeQuery();

            rs.next(); // move the cursor to first column
            dateFromDatabse = rs.getDate(1);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return dateFromDatabse;
    }

}

Output
Output
DriverManager.getConnection("jdbc:sqlserver://localhost:42588;")
trying sun.jdbc.odbc.JdbcOdbcDriver
*Driver.connect (jdbc:sqlserver://localhost:42588;)
trying com.microsoft.sqlserver.jdbc.SQLServerDriver
getConnection returning com.microsoft.sqlserver.jdbc.SQLServerDriver
sql date from database: 2016-06-17
utl date in Java: Fri Jun 17 00:00:00 PDT 2016

You can see that the time part is always zero when you convert java.sql.Date to java.util.Date because SQL date doesn't have any time element in it.

Here is a nice summary of SQL date and time classes from JDBC API:

How to convert java.sql.Date to java.util.Date in Java


That's all about how to convert java.sql.Date to java.util.Date in Java. It's easy, you just need to remember about getTime() method, which is a bridge between the two date classes from different API.

You should also keep in mind to use the fully qualified name of Date classes like java.sql.Date and java.util.Date instead of writing just Date, as it may create confusion to both compiler and fellow programmer. It's a best practice to use the fully qualified name to avoid ambiguity when we have two classes with the same name used in the same class.

Other JDBC tutorials for Java Programmers
  • Top 10 JDBC Best Practices Every Programmer Should Follow (list)
  • How to convert java.util.Date to java.sql.Date in JDBC? (example)
  • Top 10 JDBC Interview Questions for Programmers (list)
  • 6 tips to improve the performance Java Database layer? (tips)
  • How to use DAO (Data Access Object) design pattern in Java? (answer)
  • How to connect the MySQL database from Java? (guide)

No comments :

Post a Comment