Should I use java.util.Date or java.sql.Date?
I have a VisualFox database and I have retrieved the entities with the IntelliJ Idea wizard using an appropiate jdbc type 4 driver.
The ide (or the driver) has created the date fields as Timestamp. However, the date fields are not timestamps but Date fields, they store year, month and day only.
So I wonder if I should switch to java.util.Date or java.sql.Date. At first glance I thought that java.sql.Date should be the appropiate one, but it has many methods declared as deprecated.
util. Date class which represents date without time information and it should be used only when dealing with databases. To conform with the definition of SQL DATE, the millisecond values wrapped by a java. sql.
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.
The standard alternate is using the Calendar Object. Calendar has one dangerous point (for the unwary) and that is the after / before methods. They take an Object but will only handle Calendar Objects correctly. Be sure to read the Javadoc for these methods closely before using them.
The java. sql. Date represents the date value in JDBC. The constructor of this class accepts a long value representing the desired date and creates respective Date object. Date(long date)
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
, use java.time.LocalDate
.
LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;
myPreparedStatement.setObject( ld , … ) ;
TIMESTAMP WITH TIME ZONE
, use java.time.Instant
.
Instant instant = myResultSet.getObject( … , Instant.class ) ;
myPreparedStatement.setObject( instant , … ) ;
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.
The core problem is:
DATE
data type stores a date-only, without a time-of-day. 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.
So when to use which? Simple, after cutting through the confusion.
java.sql.Date
as it clumsily tries to mask its time-of-day. java.util.Date
.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:
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.
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 ) ;
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)
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 by java.time.Instant
java.sql.Timestamp
is replaced by java.time.Instant
java.sql.Date
is replaced by java.time.LocalDate
. java.sql.Time
is replaced by java.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.
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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With