Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java.sql.Timestamp created from java.util.Date, why always before() it?

Tags:

java

time

Following a bug, I've noticed that if I create a java.sql.Timestamp from a java.util.Date, using the constructor that takes the milliseconds, the Date instance is always after() the Timestamp. This is puzzling, since (a) the contract for before() specifies a strict comparison and (b) if not equal, the Timestamp, because it has nanoseconds, might itself be after() the Date. But the results are opposite and repeatable (with JDK 1.6 and 1.7, with different JVM timezones). Comparing two Dates works correctly, but calling before() or after() on a Date and giving a Timestamp argument has unexpected results.

The sample code below has two Date and one Timestamp instance, all of them with the same millisecond value. Yet comparing a Date with a Timestamp shows the Date to be after() the Timestamp.

import java.util.Date;
import java.sql.Timestamp;

public class X extends Date {

    public static void main(String[] args) {
        Date d1 = new Date();
        Date d2 = new Date(d1.getTime());
        Timestamp t = new Timestamp (d1.getTime());
        System.out.println ("date1 = " + d1 + " (" + d1.getTime() + ")" );
        System.out.println ("date2 = " + d2 + " (" + d2.getTime() + ")" );
        System.out.println ("timestamp = " + t + "  (" + t.getTime() + ")" );
        System.out.println ("d1 before d2: " + d1.before(d2));
        System.out.println ("d1 after  d2: " + d1.after(d2));
        System.out.println ("d1 before ts: " + d1.before(t));
        System.out.println ("d1 after  ts: " + d1.after(t)); //why true?
    }
}

Sample output:

C:\>\Java\jdk1.7.0_05\bin\java X
date1 = Tue Oct 30 10:15:59 EDT 2012 (1351606559812)
date2 = Tue Oct 30 10:15:59 EDT 2012 (1351606559812)
timestamp = 2012-10-30 10:15:59.812  (1351606559812)
d1 before d2: false
d1 after  d2: false
d1 before ts: false
d1 after  ts: true

The last line is the curious one.

Thank you.

like image 459
After Sandy Avatar asked Oct 30 '12 14:10

After Sandy


1 Answers

If you look at the internal representation and what is compared in the after() method, you see that for example for

millis = 1351607849957

you get a Date with

fastTime = 1351607849957

and a Timestamp with

fastTime = 1351607849000
nanos = 957000000

Since all that is compared is the fastTime part, you get your observed behaviour. As @user714965 points out above, you aren't supposed to treat a Timestamp as a Date.

like image 197
Keppil Avatar answered Sep 27 '22 20:09

Keppil