web-dev-qa-db-ja.com

Java-ゾーンオフセットなしでJava.time.InstantをJava.sql.Timestampに変換

開発中のアプリケーションでは、Java.time.InstantオブジェクトをJava.sql.Timestampに変換する必要があります。 Instantオブジェクトを作成するとき、例えば

Instant now = Instant.now();

要素を検査します。 2017-03-13T14:28:59.970Zのようなものを受け取ります。次に、次のようなTimestampオブジェクトを作成しようとします。

Timestamp current = Timestamp.from(now);

そして、私が要素を検査するとき。 2017-03-13T16:28:59.970Zのようなものを受け取りますが、同じ結果ですが、2時間のオフセットが追加されています。誰もがあなたのこれが起こることを説明し、オフセットなしでこれを解決する方法の答えを私に提供できますか?.

このように作成した場合:

LocalDateTime ldt = LocalDateTime.ofInstant(Instnant.now(), ZoneOffset.UTC);
Timestamp current = Timestamp.valueOf(ldt);

すべて正常に動作します。しかし、私は変換を避けようとします。 Instantオブジェクトのみを使用してこれを行う方法はありますか?

30

実験のためにコンピューターのタイムゾーンをヨーロッパ/ブカレストに変更しました。これは、UTC +タイムゾーンの2時間です。

コードをコピーすると、次のような結果が得られます。

    Instant now = Instant.now();
    System.out.println(now); // prints 2017-03-14T06:16:32.621Z
    Timestamp current = Timestamp.from(now);
    System.out.println(current); // 2017-03-14 08:16:32.621

出力はコメントで提供されます。しかし、私は続けます:

    DateFormat df = DateFormat.getDateTimeInstance();
    df.setTimeZone(TimeZone.getTimeZone("UTC"));
    // the following prints: Timestamp in UTC: 14-03-2017 06:16:32
    System.out.println("Timestamp in UTC: " + df.format(current));

これで、Timestampが元のInstantと本当に一致していることがわかります(ミリ秒のみが表示されませんが、そこにも含まれていると確信しています)。 Timestampを印刷するときにtoStringメソッドを暗黙的に呼び出しており、このメソッドがコンピューターのタイムゾーン設定を取得し、このゾーンの時間を表示するため、すべてが正しく行われ、混乱するだけです。 。このため、表示が異なります。

LocalDateTimeを使用して試みた他のことは機能しているように見えますが、実際にはあなたが望むものを提供していません:

    LocalDateTime ldt = LocalDateTime.ofInstant(Instant.now(), ZoneOffset.UTC);
    System.out.println(ldt); // 2017-03-14T06:16:32.819
    current = Timestamp.valueOf(ldt);
    System.out.println(current); // 2017-03-14 06:16:32.819
    System.out.println("Timestamp in UTC: " + df.format(current)); // 14-03-2017 04:16:32

UTC Timestampを使用してDateFormatを印刷すると、2時間前であることがわかります。Instantが06:16:32 UTCの場合、04:16:32 UTCです。 。この方法はだまされて、機能しているように見えますが、機能していません。

これは、古いクラスを置き換えるためのJava 8日時クラスの設計につながる問題を示しています。したがって、あなたの問題に対する本当の良い解決策は、おそらくInstantオブジェクトを受け入れることができるJDBC 4.2ドライバーを入手して、Timestampへの変換を完全に回避することです。まだ利用できるかどうかはわかりませんが、そうなると確信しています。

37
Ole V.V.

現在のタイムスタンプが必要な場合は、次の関数を使用しないでください。さまざまなプロジェクトでこれを使用しており、完全に機能します。

public static Timestamp getTimeStamp()
{
    // Calendar information
    Calendar calendar       = Calendar.getInstance();
    Java.util.Date now      = calendar.getTime();
    Timestamp dbStamp       = new Timestamp(now.getTime());
    return dbStamp;
}   

例:

System.out.println( getTimeStamp() );

出力:2017-03-13 15:01:34.027

編集

Java 8 LocalDateTimeの使用:

public static Timestamp getTimeStamp()
{
    return Timestamp.valueOf(LocalDateTime.now());
}   
1
DazstaV3

レコードをSQL Server DBに保存するときに、同じ問題に直面しました。私はJava.sql.Timestamp.valueOf(String s)を使用してTimestamp in UTCを取得しました:

import Java.time.Instant; import Java.time.format.DateTimeFormatter; .... .... DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(UTC); String dateTime = dateTimeFormatter.format(Instant date); Timestamp timestamp = Timestamp.valueOf(dateTime);

わたしにはできる。

0
Taras Melnyk