Monday, November 14, 2005

Timestamp bugs..

I hit upon two JDK 1.5 bugs today both related to Timestamp.

  1. Till JDK 1.4.x, Timestamp.compareTo(Date) worked. With JDK1.5, it results into ClasscastException. Since Timestamp extends Date, the caller can always call date1.compareTo(date2) where date1 and date2 can be date or any of its subclass. Now with JDK1.5, if date1 is Timestamp and date2 is Date, it will result into ClassCastException. The code should have always been backward compatible. Try the code below

    Date date1 = new Date ();
    Date date2 = new Timestamp(System.currentTimeMillis());
    int result = date2.compareTo(date1);

  2. In some special cases, two different dates differing only in millisecond values are treated to be equal. You don't believe it?
    Lets take the code sample below, where you create date1 using the value only till second, and compare that with a timestamp date2 that was created with the entire value. Since date1 does not contain millisecond part, timestamp should be greater than date here but date.compareTo() treats them equal.

    long millis = System.currentTimeMillis();
    Date date1 = new Date(millis/1000*1000);
    Timestamp date2 = new Timestamp(millis);
    int i = date1.compareTo(date2);

    This used to work till JDK1.4. It got broken in JDK 1.5 because date now uses getMillis() to compare the time instead of comparing getTime() values. This change must have been made with good intention as getMillis() didn't need any computation and they would have thought that it will become faster. However Timestamp played spilsport here. When you create Timestamp object passing long millisecond value, it breaks it up in two parts - 'millis' in which it stores values till second and 'nanos' in which it stores everything after second. The Timestamp constructior looks like

    public Timestamp(long time) {
    super((time/1000)*1000);
    nanos = (int)((time%1000) * 1000000);
    if (nanos < 0) {
    nanos = 1000000000 + nanos;
    super.setTime(((time/1000)-1)*1000);
    }
    }

    Thus the millis value in this object will be only till second. hence the comparison of the two dates above will make them equal.

The lesson is that don't use compareTo() with dates. Write your own comparator for it in which you compare using date.getTime() :)

2 comments:

Anonymous said...

salute!
I bookmark your site, best greetings.
We enjoyed visiting your website very much. We enjoyed visiting your website very much.

Another links here:

http://ativan.butkel1.org/ ativan

Buy!

Ahamad said...

Good Catch

-ahamad
Software Testing Blog
CFPDF Blog