When I test this code:
java.util.Date date = new java.util.Date(); java.util.Date stamp = new java.sql.Timestamp(date.getTime()); assertTrue(date.equals(stamp)); assertTrue(date.compareTo(stamp) == 0); assertTrue(stamp.compareTo(date) == 0); assertTrue(stamp.equals(date));
I´ll be expecting a true, true, true, false. Because of this:
In the javadoc for java.sql.Timestamp, it states:
Note: This type is a composite of a java.util.Date and a separate nanoseconds value. Only integral seconds are stored in the java.util.Date component. The fractional seconds - the nanos - are separate. The Timestamp.equals(Object) method never returns true when passed a value of type java.util.Date because the nanos component of a date is unknown. As a result, the Timestamp.equals(Object) method is not symmetric with respect to the java.util.Date.equals(Object) method. Also, the hashcode method uses the underlying java.util.Date implementation and therefore does not include nanos in its computation.
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.
But instead I´ll get a true, false, true, false. Any ideas?
EDIT: This problem appear when a I was checking two Dates with the equals method, but one of the Date object come from a Hibernate class and debugging I see that the object contains a TimeStamp. So the equals method evaluate to false, then I found this: http://mattfleming.com/node/141
But when I try the code I get different results...if I can´t use neither equals and compareTo, what I should use to check if 2 Dates are the same?!?!
In Java, two dates can be compared using the compareTo() method of Comparable interface. This method returns '0' if both the dates are equal, it returns a value "greater than 0" if date1 is after date2 and it returns a value "less than 0" if date1 is before date2.
The compareTo() method of Timestamp class returns : Integer value 0 if this Timestamp object is equal to given Timestamp object. A value less than 0 if this Timespan object is before the given argument. A value greater than 0 if this Timespan object is after the given argument.
The date object allows us to perform comparisons using the > , < , = , or >= comparison operators, but not the equality comparison operators like == , != , === , and !== (unless we attach date methods to the date Object).
Date compareTo() method in Java with examplesIt returns the value 0 if the argument Date is equal to this Date. It returns a value less than 0 if this Date is before the Date argument. It returns a value greater than 0 if this Date is after the Date argument.
Use the modern java.time classes instead of those troublesome legacy date-time classes.
myPreparedStatement.setObject( … , Instant.now() // Capture the current moment in UTC. )
Put more bluntly, the java.sql.Timestamp/.Date/.Time classes are a hack, a bad hack. Like java.util.Date/.Calendar, they are the result of poor design choices.
The java.sql types should be used as briefly as possible, used only for transfer of data in/out of the database. Do not use for business logic and further work.
The old date-time classes have been replaced by the java.time framework built into Java 8 and later. These new classes are defined by JSR 310, inspired by the highly successful Joda-Time library, and extended by the ThreeTen-Extra project.
Eventually we should see JDBC drivers updated to work directly with these java.time types. But until that day we need to convert to/from java.sql types. For such conversions, call new methods added to the old classes.
An Instant
is a moment on the timeline in UTC to a resolution of nanoseconds.
Instant instant = myJavaSqlTimestamp.toInstant();
To go the other direction:
java.sql.Timestamp ts = java.sql.Timestamp.valueOf( instant );
Apply a time zone to get wall-clock time.
ZoneId zoneId = ZoneId.of( "America/Montreal" ); ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
The java.time classes have a clean wisely-chosen class design. So you can use the equals
and compareTo
as expected. Note that the classes with an offset-from-UTC or time zone also offer isEqual
, isBefore
, and isAfter
methods. These methods compare by considering moments on the timeline, their chronological order. The equals
and compareTo
methods also consider the offset or time zone.
Minimizing the use of java.sql while maximizing the use of java.time renders the Question’s issues moot.
In Hibernate, use converters for java.time.
As of JDBC 4.2 and later, you need not use the legacy classes at all. You can directly exchange java.time objects with your database via the getObject
& setObject
methods.
myPreparedStatement.setObject( … , instant ) ;
And retrieval.
Instant instant = myResultSet.getObject( … , Instant.class ) ;
Note that many databases cannot store a moment with a resolution as fine as the nanoseconds used in java.time. You may want to truncate explicitly rather than letting your JDBC driver do so implicitly.
Instant instant = Instant.now().truncatedTo( ChronoUnit.MILLIS ) ; // Lop off any nanoseconds & microseconds, keeping only the milliseconds, to match limitations of database.
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.
Nican explained the equals
part, about compareTo
:
Timestamp
has a compareTo(Date)
method that converts it to Timestamp
internally Date
does the comparison by downcasting (since Timestamp
is a subclass of it); but as the javadoc states: "The inheritance relationship between Timestamp and java.util.Date really denotes implementation inheritance, and not type inheritance"Which of course is an horrible idea, in my opinion.
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