2012-10-30 26 views
5

バグの後、私は、ミリ秒かかるコンストラクタを使用してjava.util.Dateからjava.sql.Timestampを作成すると、Dateインスタンスは常にタイムスタンプ(after)です。これは、(a)before()の契約が厳密な比較を指定し、(b)等しくない場合、タイムスタンプはナノ秒を持つため、日付自体を日付の後に置く可能性があるため、困惑しています。しかし、結果は反対で反復可能です(JDK 1.6と1.7、JVMのタイムゾーンが違う)。 2つの日付の比較は正しく動作しますが、Dateでbefore()またはafter()を呼び出してTimestamp引数を指定すると予期しない結果が生じます。java.util.Dateから作成されたjava.sql.Timestampは、常にbefore()ですか?

以下のサンプルコードでは、2つのDateインスタンスと1つの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? 
    } 
} 

出力例:

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 

最後の行は好奇心旺盛です。

ありがとうございます。

+0

デバッガを使用してその点を指摘します。 [Timestamp API](http://docs.oracle.com/javase/6/docs/api/java/sql/Timestamp.html)* "[...]では、タイムスタンプ値を表示しないようにすることをお勧めしますjava.util.Dateのインスタンスとして一般的に使用されます。」* – Kai

+1

'd1.compareTo(ts);'結果 '1'は、1ナノの違いなどがあることを示します。 ___私はそれがバグだと信じています、はい。いい仕事が見つかりました! – XenoRo

答えて

6

あなたが内部表現を見て、どのようなafter()方法で比較されて、あなたは例えば

millis = 1351607849957 

のためにあなたが

fastTime = 1351607849957 

TimestampDateを取得することを確認した場合
fastTime = 1351607849000 
nanos = 957000000 

比較されるのはfastTimeの部分だけです。あなたの観察された動作が得られます。 @ user714965は上記のように、TimestampDateとして扱うことは想定されていません。

+0

ああ、これです。ありがとうございました。 –

4

java.sql.TimestampのAPIドキュメントは言う:

注:このタイプはjava.util.Dateの複合および個別のナノ秒値です。積分秒のみがjava.util.Dateコンポーネントに格納されます。分数秒 - ナノ秒 - は別々です。

(それはケッピルの答えに同意します)。

また言う:

起因Timestampクラス及び上記java.util.Dateクラスの違いのために、コードがjava.util.Dateのインスタンスとして総称Timestamp値を表示しないことをお勧めします。 Timestampjava.util.Dateの間の継承関係は、実際に継承を表すのではなく、継承の継承を示します。あなたはそのメソッドが期待する(java.util.Date.after()にそれを渡した場合、あなたがやっていることであるjava.util.Date、としてTimestamp扱うべきではありません意味

java.util.Date - あなたはそれがだかのように扱い、Timestampに渡していますjava.util.Date、このコメントはあなたがしてはいけないと言います)。

これは標準的なJavaライブラリの悪い設計です。日付と時間を扱う必要がある場合は、はるかに優れた設計と強力なライブラリであるJoda Timeを使用してください。

+0

はい、私はこれらの違い(と非互換性、特にequals())とJodaについて認識していますが、私はこの奇妙な動作の説明を探しています。 –

+0

'java.sql.Timestamp'のようなクラスのソースコードを掘り下げれば、JDKのインストールディレクトリにある' src.zip'ファイルで見つけることができます。 – Jesper

関連する問題