Congratulations, you've hit my favorite pet peeve with JDBC: Date class handling.

Basically databases usually support at least three forms of datetime fields which are date, time and timestamp. Each of these have a corresponding class in JDBC and each of them extend java.util.Date. Quick semantics of each of these three are the following:

  • java.sql.Date corresponds to SQL DATE which means it stores years, months and days while hour, minute, second and millisecond are ignored. Additionally sql.Date isn't tied to timezones.
  • java.sql.Time corresponds to SQL TIME and as should be obvious, only contains information about hour, minutes, seconds and milliseconds.
  • java.sql.Timestamp corresponds to SQL TIMESTAMP which is exact date to the nanosecond (note that util.Date only supports milliseconds!) with customizable precision.

One of the most common bugs when using JDBC drivers in relation to these three types is that the types are handled incorrectly. This means that sql.Date is timezone specific, sql.Time contains current year, month and day et cetera et cetera.

Finally: Which one to use?

Depends on the SQL type of the field, really. PreparedStatement has setters for all three values, #setDate() being the one for sql.Date, #setTime() for sql.Time and #setTimestamp() for sql.Timestamp.

Do note that if you use ps.setObject(fieldIndex, utilDateObject); you can actually give a normal util.Date to most JDBC drivers which will happily devour it as if it was of the correct type but when you request the data afterwards, you may notice that you're actually missing stuff.

I'm really saying that none of the Dates should be used at all.

What I am saying that save the milliseconds/nanoseconds as plain longs and convert them to whatever objects you are using (obligatory joda-time plug). One hacky way which can be done is to store the date component as one long and time component as another, for example right now would be 20100221 and 154536123. These magic numbers can be used in SQL queries and will be portable from database to another and will let you avoid this part of JDBC/Java Date API:s entirely.

Answer from Esko on Stack Overflow
Top answer
1 of 7
634

Congratulations, you've hit my favorite pet peeve with JDBC: Date class handling.

Basically databases usually support at least three forms of datetime fields which are date, time and timestamp. Each of these have a corresponding class in JDBC and each of them extend java.util.Date. Quick semantics of each of these three are the following:

  • java.sql.Date corresponds to SQL DATE which means it stores years, months and days while hour, minute, second and millisecond are ignored. Additionally sql.Date isn't tied to timezones.
  • java.sql.Time corresponds to SQL TIME and as should be obvious, only contains information about hour, minutes, seconds and milliseconds.
  • java.sql.Timestamp corresponds to SQL TIMESTAMP which is exact date to the nanosecond (note that util.Date only supports milliseconds!) with customizable precision.

One of the most common bugs when using JDBC drivers in relation to these three types is that the types are handled incorrectly. This means that sql.Date is timezone specific, sql.Time contains current year, month and day et cetera et cetera.

Finally: Which one to use?

Depends on the SQL type of the field, really. PreparedStatement has setters for all three values, #setDate() being the one for sql.Date, #setTime() for sql.Time and #setTimestamp() for sql.Timestamp.

Do note that if you use ps.setObject(fieldIndex, utilDateObject); you can actually give a normal util.Date to most JDBC drivers which will happily devour it as if it was of the correct type but when you request the data afterwards, you may notice that you're actually missing stuff.

I'm really saying that none of the Dates should be used at all.

What I am saying that save the milliseconds/nanoseconds as plain longs and convert them to whatever objects you are using (obligatory joda-time plug). One hacky way which can be done is to store the date component as one long and time component as another, for example right now would be 20100221 and 154536123. These magic numbers can be used in SQL queries and will be portable from database to another and will let you avoid this part of JDBC/Java Date API:s entirely.

2 of 7
69

LATE EDIT: Starting with Java 8 you should use neither java.util.Date nor java.sql.Date if you can at all avoid it, and instead prefer using the java.time package (based on Joda) rather than anything else. If you're not on Java 8, here's the original response:


java.sql.Date - when you call methods/constructors of libraries that use it (like JDBC). Not otherwise. You don't want to introduce dependencies to the database libraries for applications/modules that don't explicitly deal with JDBC.

java.util.Date - when using libraries that use it. Otherwise, as little as possible, for several reasons:

  • It's mutable, which means you have to make a defensive copy of it every time you pass it to or return it from a method.

  • It doesn't handle dates very well, which backwards people like yours truly, think date handling classes should.

  • Now, because j.u.D doesn't do it's job very well, the ghastly Calendar classes were introduced. They are also mutable, and awful to work with, and should be avoided if you don't have any choice.

  • There are better alternatives, like the Joda Time API (which might even make it into Java 7 and become the new official date handling API - a quick search says it won't).

If you feel it's overkill to introduce a new dependency like Joda, longs aren't all that bad to use for timestamp fields in objects, although I myself usually wrap them in j.u.D when passing them around, for type safety and as documentation.

🌐
Baeldung
baeldung.com › home › java › java dates › java.util.date vs java.sql.date
java.util.Date vs java.sql.Date | Baeldung
January 8, 2024 - 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.
🌐
Blogger
javarevisited.blogspot.com › 2012 › 04 › difference-between-javautildate-and.html
Difference Between java.util.Date and java.sql.Date in Java - JDBC Interview Question
The Timestamp is mapped to DATETIME data type in SQL Server, java.sql.Date is mapped to Date and similar types in other database. ... Unknown said... ... Join My Newsletter .. Its FREE · Everything Bundle (Java + Spring Boot + SQL Interview) for a discount ... How to Solve UnrecognizedPropertyException: Unreco... java.lang.ClassNotFoundException: org.postgresql.D...
🌐
Dariawan
dariawan.com › tutorials › java › java-util-date-vs-java-sql-date
java.util.Date vs java.sql.Date | Dariawan
August 1, 2019 - The millisecond values wrapped ... And the result, as you can see, java.util.Date has both date and time information, but java.sql.Date only retain date information....
🌐
Coderanch
coderanch.com › t › 682321 › databases › java-util-date-java-sql
java.util.date v/s java.sql.date (JDBC and Relational Databases forum at Coderanch)
But that would be shoehorning the util.Date based on the requirements for a different framework. Creating a new Date (well, a wrapper) that handles the specific requirements for mapping between a database column and Java makes some sense. In any case a sql.Date is a util.Date, it's just a wrapper ...
Top answer
1 of 2
1
java.sql.Date is a thin wrapper around millisecond value which is used by JDBC to identify an SQL DATE type.java.sql.Date just represent DATE without time information while java.util.Date represents both Date and Time information. This is the major difference why java.util.Date can not directly map to java.sql.Date. To suppress time information and to confirm with the definition of ANSI SQL DATE type, the millisecond values used in java.sql.Date instance must be "normalized by setting the hours, minutes, seconds and milliseconds to zero in the time-zone with DATE instance is associated. In other words, all time-related information is removed from java.sql.Date class.Thank you, I hope this will help you to understand the difference and If you need to know more about Java, join our Java online course today.
2 of 2
0
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).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.
🌐
Baeldung
baeldung.com › home › java › java dates › convert java.util.date to java.sql.date
Convert java.util.Date to java.sql.Date | Baeldung
January 13, 2024 - Actually, we don’t need to convert a java.sql.Date to a java.util.Date. This is because, both java.sql.Date and java.sql.Timestamp are subclasses of java.util.Date. Therefore, a java.sql.Date or java.sql.Timestamp is a java.util.Date.
🌐
Quora
quora.com › What-are-the-differences-between-java-sql-Date-vs-java-util-Date-vs-TimeStamp-vs-Calendar
What are the differences between java.sql.Date vs java.util.Date vs TimeStamp vs Calendar? - Quora
Answer (1 of 2): All the classes you mention are model objects for representing points in time, but yes, Java has got a bit messy with this over the years. * java.util.Date is a very simple model of time, which just models "milliseconds since 1/1/1970" without any proper concept of timezone Th...
Find elsewhere
Top answer
1 of 16
531

Nevermind....

public class MainClass {

  public static void main(String[] args) {
    java.util.Date utilDate = new java.util.Date();
    java.sql.Date sqlDate = new java.sql.Date(utilDate.getTime());
    System.out.println("utilDate:" + utilDate);
    System.out.println("sqlDate:" + sqlDate);

  }

}

explains it. The link is http://www.java2s.com/Tutorial/Java/0040__Data-Type/ConvertfromajavautilDateObjecttoajavasqlDateObject.htm

2 of 16
137

tl;dr

How to convert java.util.Date to java.sql.Date?

Don’t.

Both Date classes are outmoded. Sun, Oracle, and the JCP community gave up on those legacy date-time classes years ago with the unanimous adoption of JSR 310 defining the java.time classes.

  • Use java.time classes instead of legacy java.util.Date & java.sql.Date with JDBC 4.2 or later.
  • Convert to/from java.time if inter-operating with code not yet updated to java.time.
Legacy Modern Conversion
java.util.Date java.time.Instant java.util.Date.toInstant()
java.util.Date.from( Instant )
java.sql.Date java.time.LocalDate java.sql.Date.toLocalDate()
java.sql.Date.valueOf( LocalDate )

Example query with PreparedStatement.

myPreparedStatement.setObject( 
    … ,                                         // Specify the ordinal number of which argument in SQL statement.
    myJavaUtilDate.toInstant()                  // Convert from legacy class `java.util.Date` (a moment in UTC) to a modern `java.time.Instant` (a moment in UTC).
        .atZone( ZoneId.of( "Africa/Tunis" ) )  // Adjust from UTC to a particular time zone, to determine a date. Instantiating a `ZonedDateTime`.
        .toLocalDate()                          // Extract a date-only `java.time.LocalDate` object from the date-time `ZonedDateTime` object.
)

Replacements:

  • Instant instead of java.util.Date
    Both represent a moment in UTC. but now with nanoseconds instead of milliseconds.
  • LocalDate instead of java.sql.Date
    Both represent a date-only value without a time of day and without a time zone.

Details

If you are trying to work with date-only values (no time-of-day, no time zone), use the LocalDate class rather than java.util.Date.

java.time

In Java 8 and later, the troublesome old date-time classes bundled with early versions of Java have been supplanted by the new java.time package. See Oracle Tutorial. Much of the functionality has been back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP.

A SQL data type DATE is meant to be date-only, with no time-of-day and no time zone. Java never had precisely such a class† until java.time.LocalDate in Java 8. Let's create such a value by getting today's date according to a particular time zone (time zone is important in determining a date as a new day dawns earlier in Paris than in Montréal, for example).

LocalDate todayLocalDate = LocalDate.now( ZoneId.of( "America/Montreal" ) );  // Use proper "continent/region" time zone names; never use 3-4 letter codes like "EST" or "IST".

At this point, we may be done. If your JDBC driver complies with JDBC 4.2 spec, you should be able to pass a LocalDate via setObject on a PreparedStatement to store into a SQL DATE field.

myPreparedStatement.setObject( 1 , localDate );

Likewise, use ResultSet::getObject to fetch from a SQL DATE column to a Java LocalDate object. Specifying the class in the second argument makes your code type-safe.

LocalDate localDate = ResultSet.getObject( 1 , LocalDate.class );

In other words, this entire Question is irrelevant under JDBC 4.2 or later.

If your JDBC driver does not perform in this manner, you need to fall back to converting to the java.sql types.

Convert to java.sql.Date

To convert, use new methods added to the old date-time classes. We can call java.sql.Date.valueOf(…) to convert a LocalDate.

java.sql.Date sqlDate = java.sql.Date.valueOf( todayLocalDate );

And going the other direction.

LocalDate localDate = sqlDate.toLocalDate();

Converting from java.util.Date

While you should avoid using the old date-time classes, you may be forced to when working with existing code. If so, you can convert to/from java.time.

Go through the Instant class, which represents a moment on the timeline in UTC. An Instant is similar in idea to a java.util.Date. But note that Instant has a resolution up to nanoseconds while java.util.Date has only milliseconds resolution.

To convert, use new methods added to the old classes. For example, java.util.Date.from( Instant ) and java.util.Date::toInstant.

Instant instant = myUtilDate.toInstant();

To determine a date, we need the context of a time zone. For any given moment, the date varies around the globe by time zone. Apply a ZoneId to get a ZonedDateTime.

ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant ( instant , zoneId );
LocalDate localDate = zdt.toLocalDate();

† The java.sql.Date class pretends to be date-only without a time-of-day but actually does a time-of-day, adjusted to a midnight time. Confusing? Yes, the old date-time classes are a mess.


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes. Hibernate 5 & JPA 2.2 support java.time.

Where to obtain the java.time classes?

  • Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
    • Java 9 brought some minor features and fixes.
  • Java SE 6 and Java SE 7
    • Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
  • Android
    • Later versions of Android (26+) bundle implementations of the java.time classes.
    • For earlier Android (<26), a process known as API desugaring brings a subset of the java.time functionality not originally built into Android.
      • If the desugaring does not offer what you need, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above) to Android. See How to use ThreeTenABP….

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.

🌐
Codemia
codemia.io › knowledge-hub › path › javautildate_vs_javasqldate
java.util.Date vs java.sql.Date
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises
🌐
Oracle
docs.oracle.com › javase › 8 › docs › api › java › sql › Date.html
Date (Java Platform SE 8 )
1 week ago - Java™ Platform Standard Ed. 8 ... A thin wrapper around a millisecond value that allows JDBC to identify this as an SQL DATE value.
🌐
Java67
java67.com › 2012 › 12 › how-to-convert-sql-date-to-util-date.html
JDBC - How to Convert java.sql.Date to java.util.Date in Java with Example | Java67
July 16, 2025 - Hello Shantha and Vivek, the java.sql.Date only captures date part, If you need both date and time then please use java.sql.Timestamp class instead of java.sql.Date. Delete ... Load more... Feel free to comment, ask questions if you have any doubt. ... How to Convert a Comma Separated String to an Arr... How to Show Open Save File Dialog in Java Swing Ap...
🌐
Oracle
docs.oracle.com › en › java › javase › 11 › docs › api › java.sql › java › sql › Date.html
Date (Java SE 11 & JDK 11 )
January 20, 2026 - Creates a LocalDate instance using the year, month and day from this Date object. ... This method always throws an UnsupportedOperationException and should not be used because SQL Date values do not have a time component.
🌐
Java67
java67.com › 2014 › 02 › how-to-convert-javautildate-to-javasqldate-example.html
How to Convert java.util.Date to java.sql.Date - Example | Java67
Since java.util.Date is standard way to represent date and time in Java, I only keep java.sql.Date up-to JDBC or DAO Layer, by the way if you need date with time, then use SQL TIMESTAMP type instead of DATE.
🌐
Delft Stack
delftstack.com › home › howto › java › java util date to java sql date
How to Fix java.util.date to java.sql.date in Java | Delft Stack
December 20, 2021 - In essence, it streamlines the communication of date information, adhering to SQL conventions and optimizing the interaction between Java and databases. In Java programming, the java.util.Date class is a fundamental component for handling date and time information.
🌐
Oracle
docs.oracle.com › javase › 7 › docs › api › java › sql › Date.html
Date (Java Platform SE 7 )
This method is deprecated and should not be used because SQL Date values do not have a time component. ... Java™ Platform Standard Ed. 7 ... Submit a bug or feature For further API reference and developer documentation, see Java SE Documentation. That documentation contains more detailed, developer-targeted descriptions, with conceptual overviews, definitions of terms, workarounds, and working code examples.
🌐
Codedamn
codedamn.com › news › java
How do you convert java.util.Date to java.sql.Date in Java?
December 27, 2022 - Both the packages, java.util and ... java.util.Date is a class used to represent dates and times in java. It provides methods for parsing and formatting date values. as well as you can use it to access other related classes such as Calendar, Duration, and TimeZoneInfo. Instead java.sql.Date is required when you need to read or access date-related information in SQL...
🌐
Blogger
javarevisited.blogspot.com › 2015 › 10 › how-to-convert-javautildate-to-javasqldate-jdbc-example.html
How to convert java.util.Date to java.sql.Date - JDBC Example
By the way, if you are using Java 8 then consider using LocalDate and LocalTime which are both immutable and thread-safe but yes again converting LocalDate to SQL Date or LocalTime to SQL date is not easy and I will show you how to do it on next article, till then keep learning. ... SARAL SAXENA said... @javin what about this alternative approach dude .. java.util.Calendar cal = Calendar.getInstance(); java.util.Date utilDate = new java.util.Date(); // your util date cal.setTime(utilDate); cal.set(Calendar.HOUR_OF_DAY, 0); cal.set(Calendar.MINUTE, 0); cal.set(Calendar.SECOND, 0); cal.set(Calendar.MILLISECOND, 0); java.sql.Date sqlDate = new java.sql.Date(cal.getTime().getTime()); // your sql date System.out.println("utilDate:" + utilDate); System.out.println("sqlDate:" + sqlDate);