java.util.Date vs java.sql.Date
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. Additionallysql.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 thatutil.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.
Choosing between java.util.Date or java.sql.Date
tl;dr
Should I use java.util.Date or java.sql.Date?
Neither.
Both are obsolete as of JDBC 4.2 and later. Use java.time classes instead.
- date-only value
For a database type akin to SQL-standardDATE
, usejava.time.LocalDate
.LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;
myPreparedStatement.setObject( ld , … ) ;
- date with time-of-day in UTC value
For a database type akin to SQL-standardTIMESTAMP WITH TIME ZONE
, usejava.time.Instant
.Instant instant = myResultSet.getObject( … , Instant.class ) ;
myPreparedStatement.setObject( instant , … ) ;
Details
The question and other answers seem to be over-thinking the issue. A java.sql.Date is merely a java.util.Date with its time set to 00:00:00
.
From the java.sql.Date doc (italicized text is mine)…
Class Date
java.lang.Object
java.util.Date ← Inherits from j.u.Date
java.sql.Date
…
A thin wrapper around a millisecond value that allows JDBC to identify this as an SQL DATE value. A milliseconds value represents the number of milliseconds that have passed since January 1, 1970 00:00:00.000 GMT. ← Time-of-day set to Zero, midnight GMT/UTC
To conform with the definition of SQL DATE, the millisecond values wrapped by a java.sql.Date instance must be 'normalized' by setting the hours, minutes, seconds, and milliseconds to zero in the particular time zone with which the instance is associated.
Date-Only versus Date-Time
The core problem is:
- SQL
In SQL, theDATE
data type stores a date-only, without a time-of-day. - JAVA
In the badly designed date-time library bundled with the early versions of Java, they failed to include a class to represent a date-only.
Instead of creating a date-only class, the Java team made a terrible hack. They took their date-time class (the misnamed java.util.Date
class, containing both date and time) and extended it to have an instance set its time-of-day to midnight UTC, 00:00:00
. That hack, that subclass of j.u.Date, is java.sql.Date
.
All this hacking, poor design, and misnaming has made a confusing mess.
Which To Use
So when to use which? Simple, after cutting through the confusion.
- When reading or writing to a database’s date-only column, use
java.sql.Date
as it clumsily tries to mask its time-of-day. - Everywhere else in Java, where you need a time-of-day along with your date, use
java.util.Date
. - When you have a java.sql.Date in hand but need a java.util.Date, simply pass the java.sql.Date. As a subclass, a java.sql.Date is a java.util.Date.
Even Better
In modern Java, you now have a choice of decent date-time libraries to supplant the old and notoriously troublesome java.util.Date, Calendar, SimpleTextFormat, and java.sql.Date classes bundled with Java. The main choices are:
- Joda-Time
- java.time
(inspired by Joda-Time, defined by JSR 310, bundled with Java 8, extended by the ThreeTen-Extra project)
Both offer a LocalDate
class to represent a date only, with no time-of-day and no time zone.
A JDBC driver updated to JDBC 4.2 or later can be used to directly exchange java.time objects with the database. Then we can completely abandon the ugly mess that is the date-time classes in the java.util.* and java.sql.* packages.
setObject | getObject
This article published by Oracle explains that the JDBC in Java 8 has been updated transparently to map a SQL DATE
value to the new java.time.LocalDate type if you call getObject
and setObject
methods.
In obtuse language, the bottom of the JDBC 4.2 update spec confirms that article, with new mappings added to the getObject
and setObject
methods.
myPreparedStatement.setObject( … , myLocalDate ) ;
…and…
LocalDate myLocalDate = myResultSet.getObject( … , LocalDate.class ) ;
Convert
The spec also says new methods have been added to the java.sql.Date class to convert back and forth to java.time.LocalDate.
public java.time.instant toInstant()
public java.time.LocalDate toLocalDate()
public static java.sql.Date valueOf(java.time.LocalDate)
Time Zone
The old java.util.Date
, java.sql.Date
, and java.sql.Timestamp
are always in UTC. The first two (at least) have a time zone buried deep in their source code but is used only under-the-surface such as the equals
method, and has no getter/setter.
More confusingly, their toString
methods apply the JVM’s current default time zone. So to the naïve programmer it seems like they have a time zone but they do not.
Both the buried time zone and the toString
behavior are two of many reasons to avoid these troublesome old legacy classes.
Write your business logic using java.time (Java 8 and later). Where java.time lacks, use Joda-Time. Both java.time and Joda-Time have convenient methods for going back and forth with the old classes where need be.
Replacements:
java.util.Date
is replaced byjava.time.Instant
java.sql.Timestamp
is replaced byjava.time.Instant
java.sql.Date
is replaced byjava.time.LocalDate
.java.sql.Time
is replaced byjava.time.LocalTime
.
The Instant
class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
All three java.time.Local…
classes are all lacking any concept of time zone or offset-from-UTC.
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
.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
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.
Where to obtain the java.time classes?
- Java SE 8, Java SE 9, Java SE 10, and later
- Built-in.
- Part of the standard Java API with a bundled implementation.
- Java 9 adds some minor features and fixes.
- Java SE 6 and Java SE 7
- Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
- Android
- Later versions of Android bundle implementations of the java.time classes.
- For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). 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.
What is the difference between java.util.Date and java.sql.Date?
Difference between java.util.Date and java.sql.Date in Java from site. It is well explained.
Here are few differences on java.sql.Date and java.util.Date in Java in point format, if you any other difference between them which is worth noting then please post in comments :
As per Javadoc 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 represent both Date and Time information. This is the major differences why java.util.Date can not directly map to java.sql.Date.
In order to suppress time information and to confirm with 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 timezone with with DATE instance is associated. In other words all time related information is removed from java.sql.Date class.
How to convert java.util.Date to java.sql.Date?
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 ) |
How to compare java.sql.Timestamp and java.util.Date
tl;dr
originalInstant.equals(
org.threeten.bp.DateTimeUtils.toInstant( mySqlTimestamp )
)
Avoid legacy date-time classes
The old date-time classes bundled with the earliest versions of Java are an awful mess, with poor designs and awkward hacks. One of those bad hacks is making java.sql.Timestamp
a subclass of java.util.Date
while telling you to ignore that fact of inheritance.
To quote the class doc (emphasis mine):
Due to the differences between the Timestamp class and the java.util.Date class mentioned above, it is recommended that code not view Timestamp values generically as an instance of java.util.Date. The inheritance relationship between Timestamp and java.util.Date really denotes implementation inheritance, and not type inheritance.
You were told to pretend they are not related classes. So your attempt to compare objects of each type is inappropriate.
Data loss
The Timestamp
has a resolution up to nanoseconds. The java.util.Date
class is limited to milliseconds. So the two will not compare as equal.
Using java.time
Instead, use the java.time classes. Much of their functionality is available as a back-port to Java 6 – see below.
When you get your Timestamp
, immediately convert to the java.time types. In Java 8 and later you could call the new methods added to those old classes for conversion. In the ThreeTen-Backport library for Java 6 & 7, use org.threeten.bp.DateTimeUtils.toInstant( Timestamp )
An Instant
is a moment on the timeline in UTC with a resolution of nanoseconds.
Instant instant = DateTimeUtils.toInstant( mySqlTimestamp ) ;
Now compare to your original Instant
.
boolean isOriginal = originalInstant.equals( instant ) ;
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
.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
- Java SE 8, Java SE 9, and later
- Built-in.
- Part of the standard Java API with a bundled implementation.
- Java 9 adds some minor features and fixes.
- Java SE 6 and Java SE 7
- Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
- Android
- The ThreeTenABP project adapts ThreeTen-Backport (mentioned above) for Android specifically.
- See How to use ThreeTenABP….
Why was getMonth deprecated on java.sql.Date and java.util.Date
Prior to JDK 1.1, the class Date had two additional functions. It
allowed the interpretation of dates as year, month, day, hour, minute,
and second values. It also allowed the formatting and parsing of date
strings. Unfortunately, the API for these functions was not amenable
to internationalization. As of JDK 1.1, the Calendar class should be
used to convert between dates and time fields and the DateFormat class
should be used to format and parse date strings. The corresponding
methods in Date are deprecated.
The JavaDoc explains. Internationalization.
"in case anyone suggests I should use dates from java.time
"
There is nothing to stop you from converting to java.time
classes as soon as possible, performing whatever calculations/modifications you need and, if you need to re-insert, converting back to java.sql.Date
again.
Related Topics
How to Use Scanner to Accept Only Valid Int as Input
Hibernate Throws Multiplebagfetchexception - Cannot Simultaneously Fetch Multiple Bags
Servlet For Serving Static Content
Why Aren't Java Collections Remove Methods Generic
Catching Java.Lang.Outofmemoryerror
How to Run Eclipse in Clean Mode? What Happens If We Do So
When Does System.Gc() Do Something
Program Not Accessing Method Paintcomponent() of Extended Jpanel Class
Why Can't I Define a Static Method in a Java Interface
How to Use a Servlet Filter in Java to Change an Incoming Servlet Request Url
What Components Are MVC in Jsf MVC Framework
Sort Objects in Arraylist by Date
How to Dynamically Compile and Load External Java Classes
Compare Two Objects With .Equals() and == Operator
How to Use Utf-8 in Resource Properties With Resourcebundle