web-dev-qa-db-ja.com

精度を失わずにJava.sql.TimestampをJava.util.Calendarに変換する

データベースからタイムスタンプ値を取得し、カレンダーに変換し、タイムスタンプに戻すことを試みていますが、精度が失われます。

ここに問題を再現するコードがあります

import Java.sql.Timestamp;
import Java.util.Calendar;

public class Test {
    public static void main(String[] args)
    {
        Timestamp timestamp = new Timestamp(112, 10, 5, 15, 39, 11, 801000000);
        System.out.println("BEFORE "+timestamp.toString());
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(timestamp.getTime());
        timestamp = new Timestamp(calendar.getTimeInMillis());
        System.out.println("AFTER "+timestamp.toString());
    }
}

これが変換のサンプル結果です

BEFORE 2012-10-18 14:30:13.362001
AFTER 2012-10-18 14:30:13.362

その精度を失います。 10進数値をそのままにするにはどうすればよいですか?

30
William

時間をミリ秒で設定していますが、入力精度はマイクロ秒であるため、もちろんミリ秒よりも細かい精度は失われます。

カレンダーはミリ秒よりも細かい粒度をサポートしていません。回避策はありません。

30
Bohemian

Java.time

Java 8以降では、解決策があります。新しい Java.time フレームワークが組み込まれています。 JSR 31 によって定義され、インスピレーションを受けています。 Joda-Time によって、 ThreeTen-Extra プロジェクトによって拡張されます。

この新しいフレームワークには ナノ秒 の解像度があります。古いJava.util.Date値、Joda-Time値、両方とも ミリ秒 を処理するのに十分です。そして、 Postgres などの一部のデータベースで使用される microseconds を処理するだけで十分です。 H2 などの一部のデータベースはナノ秒を使用します。そのため、Java.timeはすべて、または少なくともすべての主流の状況を処理できます。唯一の例外は、ニッチな科学的または工学的な状況です。

Image

Java 8で、古いクラスはJava.timeとの間で変換するための新しいメソッドを取得しました。 Java.sql.Timestamp 新しいtoInstantを使用しますメソッドとfromInstantメソッド Instant クラスには、1970 UTCの最初の瞬間であるエポックからのナノ秒のカウントが含まれます(基本的には、詳細についてはクラスdocを参照してください)。

Instantから ZonedDateTime オブジェクトを取得できます。

Java.sql.Timestamp ts = myResultSet.getTimestamp( 1 );
Instant instant = ts.toInstant();
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( zoneId );
8
Basil Bourque