7

次のシナリオがあります。

  • Calendarオブジェクトを返すスイングコントロール
  • 重い日付/時刻操作を行うために使用する中間DateTimeオブジェクト(joda)
  • オブジェクトOraclePreparedStatementのみを取得するデータベース接続( )java.sql.Date

私の問題は、CalendarandDateTimeオブジェクトがGMT(私が望む)で日付を正しく表示していることですがjava.sql.Date、データベースに送信するためにに変換すると、日付はローカルタイムゾーンに変換されます。

例えば:

  • CalendarそしてDateTime2012-08-13T23:59:59.000Z(正しいGMT)です
  • 結果java.sql.Dateは2012-08-14です(ローカルUTC + 2の日付が正しくありません)

以下は、変換を行うために使用しているコードです。

DateTime dateGmt = new DateTime(calendarGmt.getTimeInMillis(), DateTimeZone.UTC);
java.sql.Date sqlDate = new java.sql.Date(dateGmt.getMillis());

java.sql.Date正しいタイムゾーンを維持しながらオブジェクトを作成する方法がわかりません。間違った変換を行っている可能性もあります。

4

3 に答える 3

17

時間を失う

1つの問題は、java.sql.Dateが…</p>であると想定されていることです。

インスタンスが関連付けられている特定のタイムゾーンで時間、分、秒、およびミリ秒をゼロに設定することにより、「正規化」されます。

ドキュメントによると。これは、日時の時間部分がjava.util.DateまたはJoda-TimeDateTimeオブジェクトからクリアされていることを意味します。

タイムゾーンなし

Gilbert Le Blancによる正解として、java.util.Dateとjava.sql.Dateの両方に内部的にタイムゾーンの概念がありません。Unixエポックからのミリ秒数を格納します。

これらのクラスは厄介なトリックを引き出します。それらのtoStringメソッドは、JVMのデフォルトのタイムゾーンを文字列のレンダリングに適用します。とても紛らわしい。オブジェクトにはDateタイムゾーンがありませんが、文字列として表示するとタイムゾーンが表示されます。

java.util.Dateオブジェクトにエポック(1970開始)からの1344902399000Lミリ秒の数が含まれている場合、それは2012-08-13T23:59:59.000ZUTC/GMTを意味します。ただし、JVMが夏時間(DST)が有効になっているフランスにあると信じている場合は、UTC/GMTより2時間進んでいることがわかります。2012-08-14T01:59:59.000+02:00これはそのクラスのひどい文字列形式で記述されています。同じ時刻は、異なるタイムゾーンで異なる曜日の意味(13対14)を持ち、壁の時計は真夜中を過ぎています。

ジョーダ-救助の時間

ここでは、 Joda- Time2.4ライブラリが役立ちます。java.sql.Dateまたはjava.util.DateオブジェクトをUTCタイムゾーンオブジェクトとともにDateTimeコンストラクターに渡して、苦労している値を明確に把握します。

java.util.Date date = new java.util.Date( 1390276603054L );
DateTime dateTimeUtc = new DateTime( date, DateTimeZone.UTC );
System.out.println( "dateTimeUtc: " + dateTimeUtc );

実行時…</p>

2014-01-21T03:56:43.054Z

反対方向をJoda-Timeからjava.util.Dateに変換するには…</p>

java.util.Date date = myDateTime.toDate();

反対方向をJoda-Timeからjava.sql.Dateに変換するには…</p>

java.sql.Date date = new java.sql.Date( myDateTime.getMillis() );

更新– java.time

Joda-Timeプロジェクトは現在メンテナンスモードにあり、チームはjava.timeクラスへの移行をアドバイスしています。

に相当するものはjava.util.DateですInstant。このクラスは、 UTCInstantのタイムライン上の瞬間をナノ秒の解像度(小数の最大9桁)で表します。

Instant instant = Instant.ofEpochMilli( 1390276603054L );

タイムゾーンを適用して、aとJoda-Timeに類似したZoneIdを生成します。ZonedDateTimejava.util.CalendarDateTime

ZoneId z = ZoneId.of( "Europe/Kaliningrad" );
ZonedDateTime zdt = instant.atZone( z );

次に、日付のみの値、その日付部分をZonedDateTimeとして抽出しますLocalDate。このLocalDateクラスは、時刻やタイムゾーンのない日付のみの値を表します。ふりをしLocalDateているjava.sql.Dateのは、日付のみの値です。

LocalDate localDate = zdt.toLocalDate() ;

PreparedStatement::setObjectJDBC 4.2以降では、およびを介して、準拠するドライバーでjava.time型を直接使用できますResultSet::getObject

myPreparedStatement.setObject( … , localDate );

…そして…</p>

LocalDate ld = myResultSet.getObject( … , LocalDate.class );

古い非準拠ドライバーの場合は、古いクラスに追加された新しいメソッドを使用して、aとの間でjava.sql.Dateオブジェクトに簡単に変換します。LocalDatetoLocalDatevalueOf( LocalDate )

于 2014-01-21T05:44:42.823 に答える
7

aの内部表現はjava.sql.Date、1970年1月1日00:00:00.000GMTから経過したミリ秒数です。

問題を見ていませんtoStringか?この方法toGMTString()は、減価償却されていますが、まだ存在しています。

于 2012-08-13T16:34:19.710 に答える
1

設定ファイルTIMEZONE=GMTを追加する必要があるかもしれません

Webアプリケーションでは、これはweb.xmlで定義されます

<context-param> <param-name>javax.faces.DATETIMECONVERTER_DEFAULT_TIMEZONE_IS_SYSTEM_TIMEZONE</p‌​aram-name> <param-value>true</param-value> </context-param>

よろしく

于 2012-08-13T16:20:04.850 に答える