How to convert from java.sql.Timestamp to java.util.Date?
i.e. this code
startDate = new Date(timestampValue.getTime));
gives me :
2012-16-02 05:16:17
when
System.out.println(timestampValue);
return :
2012-01-02 05:16:17.0
Class java.sql.TimeStamp
extends from java.util.Date
.
You can directly assign a TimeStamp
object to Date
reference:
TimeStamp timeStamp = //whatever value you have;
Date startDate = timestampValue;
You should use a Calendar instead:
Calendar start = Calendar.getInstance();
start.setTimeInMillis( timeStampValue.getTime() );
tl;dr
Instant instant = myResultSet.getObject( … , Instant.class ) ;
…or, if your JDBC driver does not support the optional Instant
, it is required to support OffsetDateTime
:
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
Avoid both java.util.Date
& java.sql.Timestamp
. They have been replaced by the java.time classes. Specifically, the Instant
class representing a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
Different Values → Unverified Problem
To address the main part of the Question: "Why different dates between java.util.Date and java.sql.Timestamp objects when one is derived from the other?"
There must be a problem with your code. You did not post your code, so we cannot pinpoint the problem.
First, that string value you show for value of java.util.Date did not come from its default toString
method, so you obviously were doing additional operations.
Secondly, when I run similar code I do indeed get exact same date-time values.
First create a java.sql.Timestamp object.
// Timestamp
long millis1 = new java.util.Date().getTime();
java.sql.Timestamp ts = new java.sql.Timestamp(millis1);
Now extract the count-of-milliseconds-since-epoch to instantiate a java.util.Date object.
// Date
long millis2 = ts.getTime();
java.util.Date date = new java.util.Date( millis2 );
Dump values to console.
System.out.println("millis1 = " + millis1 );
System.out.println("ts = " + ts );
System.out.println("millis2 = " + millis2 );
System.out.println("date = " + date );
When run.
millis1 = 1434666385642
ts = 2015-06-18 15:26:25.642
millis2 = 1434666385642
date = Thu Jun 18 15:26:25 PDT 2015
So the code shown in the Question is indeed a valid way to convert from java.sql.Timestamp to java.util.Date, though you will lose any nanoseconds data.
java.util.Date someDate = new Date( someJUTimestamp.getTime() );
Different Formats Of String Output
Note that the output of the toString
methods is a different format, as documented. The java.sql.Timestamp follows SQL format, similar to ISO 8601 format but without the T
in middle.
Ignore Inheritance
As discussed on comments on other Answers and the Question, you should ignore the fact that java.sql.Timestamp inherits from java.util.Date. The j.s.Timestamp doc clearly states that you should not view one as a sub-type of the other: (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.
If you ignore the Java team’s advice and take such a view, one critical problem is that you will lose data: any microsecond or nanosecond part of a second that may be coming from the database is lost as a Date has only millisecond resolution.
Basically, all the old date-time classes from early Java are a big mess: java.util.Date
, j.u.Calendar
, java.text.SimpleDateFormat
, java.sql.Timestamp
/.Date
/.Time
. They were one of the first valiant efforts at a date-time framework in the industry, but ultimately they fail. Specifically here, java.sql.Timestamp is a java.util.Date with nanoseconds tacked on; this is a hack, not good design.
java.time
Avoid the old date-time classes bundled with early versions of Java.
Instead use the java.time package (Tutorial) built into Java 8 and later whenever possible.
Basics of java.time… An Instant
is a moment on the timeline in UTC. Apply a time zone (ZoneId
) to get a ZonedDateTime
.
Example code using java.time as of Java 8. With a JDBC driver supporting JDBC 4.2 and later, you can directly exchange java.time classes with your database; no need for the legacy classes.
Instant instant = myResultSet.getObject( … , Instant.class) ; // Instant is the raw underlying data, an instantaneous point on the time-line stored as a count of nanoseconds since epoch.
You may want to adjust into a time zone other than UTC.
ZoneId z = ZoneId.of( "America/Montreal" ); // Always make time zone explicit rather than relying implicitly on the JVM’s current default time zone being applied.
ZonedDateTime zdt = instant.atZone( z ) ;
Perform your business logic. Here we simply add a day.
ZonedDateTime zdtNextDay = zdt.plusDays( 1 ); // Add a day to get "day after".
At the last stage, if absolutely needed, convert to a java.util.Date for interoperability.
java.util.Date dateNextDay = Date.from( zdtNextDay.toInstant( ) ); // WARNING: Losing data (the nanoseconds resolution).
Dump to console.
System.out.println( "instant = " + instant );
System.out.println( "zdt = " + zdt );
System.out.println( "zdtNextDay = " + zdtNextDay );
System.out.println( "dateNextDay = " + dateNextDay );
When run.
instant = 2015-06-18T16:44:13.123456789Z
zdt = 2015-06-18T19:44:13.123456789-04:00[America/Montreal]
zdtNextDay = 2015-06-19T19:44:13.123456789-04:00[America/Montreal]
dateNextDay = Fri Jun 19 16:44:13 PDT 2015
Conversions
If you must use the legacy types to interface with old code not yet updated for java.time, you may convert. Use new methods added to the old java.util.Date and java.sql.* classes for conversion.
Instant instant = myJavaSqlTimestamp.toInstant() ;
…and…
java.sql.Timestamp ts = java.sql.Timestamp.from( instant ) ;
See the Tutorial chapter, Legacy Date-Time Code, for more info on conversions.
Fractional Second
Be aware of the resolution of the fractional second. Conversions from nanoseconds to milliseconds means potentially losing some data.
-
Milliseconds
- java.util.Date
- Joda-Time (the framework that inspired java.time)
-
Nanoseconds
- java.sql.Timestamp
- java.time
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.
The problem is probably coming from the fact that Date is deprecated.
Consider using
java.util.Calendar
or
Joda-Time
Edit 2015:
Java 8 and later has built-in the new java.time package, which is similar to Joda-Time.
The fancy new Java 8 way is Date.from(timestamp.toInstant())
. See my similar answer elsewhere.