java.util.Date.compareTo(java.sql.Timestamp time)は危ない。
System.out.println(new java.util.Date(10000).before(new java.sql.Timestamp(20000))); System.out.println(new java.util.Date(10000).before(new java.sql.Timestamp(10999)));
上記1行目では"true"を返す。基準時から10000ミリ秒経過後の時間は基準時から20000ミリ秒経過後の時間よりも前なので、この挙動は正しい。
でも、2行目では"false"を返す、微妙な挙動がある。ってかバグだわ、こりゃ。そういうのを含めて、仕様だそうです。
なんで?
java.util.Date(long time)では、timeをミリ秒単位として解釈し、その全ての値をthis.fastTime に格納する。一方でjava.sql.Timestamp(long time)では、秒単位以上の値をsuper.fastTimeに格納し、秒の小数点以下の値をthis.nanosに格納する。このとき、Date.compareTo(Date ahotherDate)を使って比較すると、Dateオブジェクトの内部ではTimestamp.nanosを無視され、Date.fastTimeのみを比較するのでTimestampクラスの秒の小数点以下の値は無視されてしまう。
public Date(long date) { fastTime = date; } //中略 public int compareTo(Date anotherDate) { long thisTime = getMillisOf(this); long anotherTime = getMillisOf(anotherDate); return (thisTime<anotherTime ? -1 : (thisTime==anotherTime ? 0 : 1)); }
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); } }
どうしても比較する場合は、
java.sql.Timestamp側から比較するしかない。
System.out.println(new java.sql.Timestamp(10000).before(new java.util.Date(20000))); System.out.println(new java.sql.Timestamp(10000).before(new java.util.Date(10999)));
nanosにはミリ秒未満を格納させればよかったのに、ね。
バグじゃない、仕様だってさ。
上記のような Timestamp クラスと java.util.Date クラスの違いのため、Timestamp 値は java.util.Date のインスタンスとして考えないでください。Timestamp と java.util.Date の継承関係は、型の継承ではなく、実装の継承を示します。
Oracle Technology Network for Java Developers | Oracle Technology Network | Oracle
まさか、この定型文の出番だとは思わなかったwww
こういうのが駄目な継承って言われるんだろうなぁ。