2016-12-19 15 views
0

java.util.Dateにタイムゾーンがなく、なぜそうであるのかはっきりしています。ローカルのdateTimeオブジェクトをUTCのjava.util.Dateに変換する方法

ユーザーがTimeZoneを設定したアプリケーションがあり、DateTimeピッカーでDateを選択すると、コンポーネントはDateオブジェクトを返します。 それから、データベースにUTC相当品を保存するように日付を変更する必要があります。

それはorg.joda.timeとローカルタイムゾーンのためのUTCの日付を表すDateオブジェクトを取得するにはかなり簡単です:

public static final Date getTimeZoneDependantDate(Date pDateUtc, String pUserTimezoneValue) { 
    // Build the DateTime Object 
    DateTime originalDate = new DateTime(pDateUtc.getTime(), DateTimeZone.forID(PREF_TIMEZONE_DEF_VALUE)); 
    // Convert the Date 
    DateTime convertedDate = originalDate.withZone(DateTimeZone.forID(pUserTimezoneValue)); 
    // Return the localTime associated with the timeZone 
    return convertedDate.toLocalDateTime().toDate(); 
} 

しかし、私は反対のことを行う方法についてこだわっている、が選んだ日付を変更(タイムゾーンの観点から)ユーザーをUTCに変更します。 LocalDateTimeはローカルDateを瞬時に取得するため、パラメータとして使用します。

Stringを解析するよりもクリーンな方法はありますか?

+1

'java.util.Date'にタイムゾーンがないことを理解しているとは思えません。それは瞬間/瞬間のように扱われなければならない。したがって、コード全体は役に立たない。最初のパラメータが 'Date'で、時間操作なしで' Date'を返す(つまりモーメントを変更する)場合、これは同じ操作(単に 'return pDateUtc;')です。インスタントタイムゾーンで同じです! –

+0

私は十分にはっきりしてはいけません。私は、ユーザーがカレンダーで日付を選択し、文字列に時間を書き込むDatePickerを使用しています。 コンポーネント(ユーザーのタイムゾーンを考慮してコードを変更することはできません)は、ユーザーの選択とコントローラに一致するjava.util.Dateを返します。 それから、ユーザーが自分のタイムゾーンの視点から選択したローカル日付と一致する瞬間を計算するためにコントローラが必要です。より良い世界では、コンポーネントはタイムゾーンに注意し、正しいDateオブジェクトを返します。 – TheBakker

+0

あなたの説明によると、ユーザーはローカルカレンダーの日付とローカル時計の時刻を選択します。そして、 'DatePicker'コンポーネントは' Date'オブジェクトを生成します。つまり、このコンポーネントは少なくとも内部的にタイムゾーン変換を適用します。たぶん、代わりに 'DatePicker'コンポーネントのタイムゾーンを設定する必要があります。しかし、 'DatePicker'によって返された' java.util.Date'オブジェクトを操作するのは間違いです。 –

答えて

0

ネットワークを介して日付を送信して保存する最善の方法は、タイムスタンプ(日付はミリ秒単位)の形式です。このタイムスタンプはタイムゾーン情報を必要としません。しかし、タイムスタンプの形式で日付を取得した後、日付オブジェクトを作成します。日付をUTC形式で表示する場合は、変換する必要があります。

+0

私が書いたように、私の問題は、ユーザーが自分のタイムゾーンに応じて選択するDateオブジェクトを返すdateTimepickerオブジェクトです。私のコントローラは、ビジネスレイヤに情報をプッシュする前にこれを変更する必要があります。私が探しているのは、このローカル日付を正しいUTC日付に変換する最も簡単な方法です。 – TheBakker

+0

ビジネスレイヤにどのように送信していますか? –

+0

@TheBakker「ローカル」の「日付」はありません。算術的意味ではすでにUTCです(そのメソッド 'toString()'は狂った形で実装されています)。 –

1

tl; dr

あなたは十分な情報を提供していません。レポート:これの

  • 結果:myJavaUtilDate.toInstant().toString()
  • 入力コンポーネント
  • へのアプリの現在のデフォルトのタイムゾーン

詳細

あなたは本当に十分に与えていませんあなたの問題に関する情報GUIコンポーネントのjava.util.Dateオブジェクトを使用して、UTCで正しい日時の値を取得していますか?

America/Montrealのケベックの時間帯での利用者は2016年12月1日に9 AMに入り、java.util.Dateオブジェクトを生成しながら、あなたのコンポーネントが正しくUTCにこれらの値を調整している、あなたは何の問題もない場合。 UTCの値は、午後の午後2時(America/Montreal)はその特定の日付のUTCより5時間遅れているため、UTCの午後2時です。 java.sql.Timestampオブジェクトに変換した後、Dateオブジェクトをデータベースに渡すだけです。

FYIでは、古い日時クラスクラス(Date & Calendarなど)とJoda-Timeの両方がjava.timeクラスに置き換えられました。次に、コンポーネントがうまく使用している動作の種類を示すjava.timeのコード例をいくつか示します。

LocalDate ld = LocalDate.of (2016 , Month.DECEMBER , 1); 
LocalTime lt = LocalTime.of (9 , 0); 
ZoneId z = ZoneId.of ("America/Montreal"); 
ZonedDateTime zdt = ZonedDateTime.of (ld , lt , z); 
Instant instant = zdt.toInstant(); // UTC 

System.out.println ("zdt.toString(): " + zdt); 
System.out.println ("instant.toString(): " + instant); 

zdt.toString():2016-12-01T09:00〜05:00 [アメリカ/モントリオール]

インスタント。toString():2016-12-01T14:00:00Z

文字列の最後にZZuluの略であり、UTCを意味します。文字列を生成しながら、現在のデフォルトのタイムゾーンを適用するjava.util.Date::toStringの不幸な行動を考えると

は、私はあなたがその価値の明確な読書を得ることができるので、あなたのDateInstantに変換示唆しています。

Instant instantConvertedFromDateOfComponent = myJavaUtilDate.toInstant(); 

このステップの後に、あなたが実際に午後に2 PMを見なければ、すべてが順調ですし、あなたのコンポーネントがうまく行っています。

タイムゾーンの問題を無視して、ユーザーが自分のゾーンとしてUTCを意図しているかのようにユーザーの入力を報告すると、コンポーネントがうまく動作しない場合、2016-12-01T09:00:00Zが表示されます。それは問題です。回避策は、自分でタイムゾーンを調整することです。 「ローカル」(ゾーンレス)値を抽出し、意図したタイムゾーンを適用します。

"ローカル"の日付と時刻を取得するには、まずOffsetDateTimeオブジェクトに変換します。

OffsetDateTime odt = instantConvertedFromDateOfComponent.atOffset(ZoneOffset.UTC); 
LocalDateTime ldt = odt.toLocalDateTime(); // 2016-12-01T09:00:00Z 
ZonedDateTime zdt = ldt.atZone(z); // 2016-12-01T09:00-05:00[America/Montreal] 

JDBCドライバがJDBC 4.2以降に準拠している場合、これらのjava.time型を直接渡すことができます。そうでない場合は、古いクラスに追加された新しいメソッドを使用してjava.sql型に変換します。スタックオーバーフローで何度も議論されているので、より多くの情報を検索してください。

サーバーの現在の既定のタイムゾーンは、プログラミングとは関係ありません。暗黙的にデフォルトに依存するのではなく、オプションの引数で常に希望の/期待されるタイムゾーンを明示的に指定します。 java.timeについて


java.timeフレームワークは、Java 8に組み込まれており、後にされています。これらのクラスは、java.util.DateCalendar、& SimpleDateFormatなど、面倒な古いlegacy日時クラスに取って代わります。

maintenance modeにあるJoda-Timeプロジェクトは、java.timeクラスへの移行を推奨しています。

詳しくはOracle Tutorialをご覧ください。そして、多くの例と説明のためにStack Overflowを検索してください。仕様はJSR 310です。

ここで、java.timeクラスを取得するには?

  • Java SE 8SE 9以降
    • 内蔵しています。
    • バンドルされた実装の標準Java APIの一部です。
    • Java 9には、いくつかのマイナーな機能と修正が加えられています。
  • Java SE 6とJavaの多く
  • Android
    • ThreeTenABPプロジェクトはThreeTen-バックポート具体的にAndroidのため(上記)を適応させます。
    • How to use…を参照してください。

ThreeTen-Extraプロジェクトでは、追加のクラスでjava.timeを拡張します。このプロジェクトは、将来のjava.timeへの追加の可能性を証明する土台です。ここでは、IntervalYearWeekYearQuartermoreなどの便利なクラスがあります。

関連する問題