2011-04-30 10 views
6

たjava.sql.Timestampのコンストラクタは次のように行く:たjava.sql.Timestampの方法は

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); 
    } 
} 

それは基本的には、ミリ秒の時間を受け入れ、その後、最後の3桁の数字を抽出し、それがナノスます。だから、1304135631 のミリ秒値のために、私は 4.21億としてTimestamp.getnanos()を取得しています。これは単純な計算です(最後に6つのゼロを追加する)...最適ではないようです。

より良い方法は、ナノ秒単位で時間を受け取り、それからナノ秒の値を計算するタイムスタンプコンストラクタでした。

以下のプログラムを実行すると、実際のナノ秒と、ナノ秒を計算するTimestampの方法で返されたものとの違いがわかります。

long a = System.currentTimeMillis(); 
    for(;;){ 
     long b = System.currentTimeMillis(); 
     Timestamp tm = new Timestamp(System.currentTimeMillis()); 
     System.out.println(tm.getTime()); 
     System.out.println(tm.getNanos()); 
     System.out.println("This is actual nanos" + System.nanoTime()%1000000000); 
     System.out.println("--------------------------"); 
     if(b-a >= 1) 
      break; 
    } 

だから、ナノ秒までの時間を保存すると言うタイムスタンプに関するすべての議論は、とても正確であるように思われません...ではないですか?

答えて

6

ミリ秒単位の時間はナノ秒で表されません。もっと正確に言えば、それは単純にできません。あなたはTimestamp#setNanos()を使って実際のナノ秒を設定することになっています。

long timeInMillis = System.currentTimeMillis(); 
long timeInNanos = System.nanoTime(); 

Timestamp timestamp = new Timestamp(timeInMillis); 
timestamp.setNanos((int) (timeInNanos % 1000000000)); 

// ... 
+1

はい。これは間違いなく機能します。だから、Timestampに実際にナノを保存させるには、それは2つのステップのプロセスでなければなりません。 1970年1月1日よりnanosを受け入れるコンストラクタは、より良い解決策でした。 – Vicky

+1

これは安全ではありません!それはラップする!問題は、 'currentTimeMillis'と' nanoTime'がより大きい解像度で一致しないかもしれないということです。例えば'nanoTime'は、12:06:30.9999,12:06:** 31 ** .1111の値を返しますが、' currentTimeMillis'は12:06:30.666 12:06:** 30 ** ** 777を返します。タイムスタンプを初期化すると、タイムスタンプが12:06:30.9999,12:06:** 30 * .1111になります。これとは別に、@ Vickyさんのコメントを、1970年以前にタイムスタンプをどのように初期化しますか? – Luciano

+0

ナノ秒の設定は別に設定する必要がありますが、このように 'System#nanoTime()'を使用することは間違っています。 「System#nanoTime()」のAPIドキュメントには次のように書かれています。「このメソッドは、経過時間を測定するためにのみ使用でき、システムや壁時計の時間の他の概念には関係しません。返される値は固定されているが任意の時刻以降のナノ秒を表します(将来的には値が負になる可能性もあります)。 "(http://download.oracle.com/javase/6/docs/api/java/lang/Systemを参照) .html#nanoTime%28%29) –

0

それは古い記事ですが、私は、タイムスタンプのドキュメントは、それが「nanaosecondsの精度に 小数秒の仕様を可能にすることにより、小数点以下の秒を保持している」と述べているんので追加したいと思います。混乱する部分は「ホールド」です。これは最初は混乱しているようですが、正しく理解されていれば実際にはナナセ秒の値を保持しているとは言いません。それは分数値を「保持」し、ナノ秒の「精度」を可能にします。精度は、合計桁数の表現 によって理解する必要があります。したがって、本質的に、パーツは実際には分数(ミリ秒単位)ですが、1000000で乗算されてナノ秒単位で表されます。

受け入れられた回答(これまで有用なBaluCによって)はそれをうまくまとめています。

0

私はOpenJPAの実装がTimestampHelperののが好きです。静的初期化子を使用して、タイムスタンプを作成するための呼び出しの間に経過したナノ秒を追跡します。

1

java.time.*の導入以来、java.sql.Timestampに新しいファクトリメソッドがあります。Timestamp.from(Instant.now())は(ナノ秒精度で)ジョブを実行します。また、それ以外の方法で変換するにはTimestamp.toInstant()があります。

+0

Java 8は、['LocalDateTime.now()'](https://docs.oracle.com/javase/8/docs/api/java/time/LocalDateTime.html#now)を提供しています。 - )...または<8の場合は、現在のタイムスタンプを取得するために 'System.nanoTime()'を使用します。 – KarelG

関連する問題