user> (let [milli (.getTime (.getTime (java.util.Calendar/getInstance))) ts (java.sql.Timestamp. milli) d (java.util.Date. milli)] [(= (.getTime d) (.getTime ts)) (= ts d) (= d ts)]) [true false true]
Really, Java? Really? Come on now.
Documenting it doesn't make it any better either:
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 an object that isn't an instance of java.sql.Timestamp, 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.
The internet is strewn with the wreckage of people being gnawed upon by this bug.