2012-08-27 10 views
5

私はHOUR_OF_DAYフィールドを設定し、GregorianCalendar日付オブジェクトのタイムゾーンを変更しようとしています。Java GregorianCalendar change TimeZone

GregorianCalendar date = new GregorianCalendar(TimeZone.getTimeZone("GMT+10")); 
System.out.println("HOUR: " + date.get(Calendar.HOUR_OF_DAY)); 
date.set(Calendar.HOUR_OF_DAY, 23); 
//date.get(Calendar.HOUR_OF_DAY); 
date.setTimeZone(TimeZone.getTimeZone("GMT")); 
System.out.println("HOUR: " + date.get(Calendar.HOUR_OF_DAY)); 

出力:

HOUR: 16 
HOUR: 23 

HOUR_OF_DAYの値が異なるタイムゾーンを設定した後に変更されませんいくつかの理由。これが可能であるどのように

HOUR: 16 
HOUR: 13 

:私はHOUR_OF_DAYためdate.getのコメントを解除した場合でも、すべてがアウトプットそれが

GregorianCalendar date = new GregorianCalendar(TimeZone.getTimeZone("GMT+10")); 
System.out.println("HOUR: " + date.get(Calendar.HOUR_OF_DAY)); 
date.set(Calendar.HOUR_OF_DAY, 23); 
date.get(Calendar.HOUR_OF_DAY); // uncommenting this line will is changing the output 
date.setTimeZone(TimeZone.getTimeZone("GMT")); 
System.out.println("HOUR: " + date.get(Calendar.HOUR_OF_DAY)); 

必要として正確に動作しますか?なぜ、getメソッドがオブジェクトの動作を変更しているのですか?

答えて

8

GregorianCalendarクラスには、次の副作用有するCalendarからそのget方法、継承:厳密モードで

を、すべてのカレンダフィールドが正規化されます。

これはgetCalendarオブジェクトで呼び出されたときtime値とすべてのフィールドが再計算されていることを意味します。これは、特にsetTimeZoneと組み合わせたときに、いくつかの予期しない振る舞いを引き起こす可能性があります。それには、ある程度の数のdocumented buggy behaviorがあります。

0

TL; DR

OffsetDateTime.now(ZoneOffset.ofHours(10) ).withHour(23) 

避けレガシー日時クラス

レガシーGregorianCalendarを含む日付時刻クラスが混乱しています。ぎこちない、あまりにもデザインの混乱。それらを避けてください。今度はjava.timeクラスに置き換えられました。具体的には、GregorianCalendarZonedDateTimeに置き換えられます。

オフセット-から-UTC

あなたは明らかに先駆けUTCoffset-from-UTC 10の時間と瞬間をしたいです。希望のオフセットを定義します。

ZoneOffset offset = ZoneOffset.ofHours(10) ; 

offset.toString():+10:00

そのオフセットとOffsetDateTimeとして現在の瞬間を取得します。

OffsetDateTime odt = OffsetDateTime.now(offset) ; 

odt.toString():2018-02-15T16:44:44.216642 + 10:00

あなたが23する時間を上書きしたいです。

OffsetDateTime odt23 = odt.withHour(23) ; 

odt23.toString():2018-02-15T23:44:44。216642 + 10:00

タイムゾーン

私はHOUR_OF_DAYフィールドを設定し、GregorianCalendarの日付オブジェクトのタイムゾーンを変更しようとしています。

いいえ、あなたはtime zoneではなくoffset-from-UTCを変更しています。

特定ののゾーンを知っている場合は、単なるオフセットではなく、むしろタイムゾーンを使用する方が良いでしょう。タイムゾーンは、特定の地域の人々が使用したオフセットの過去、現在、および将来の変更の履歴です。タイムゾーンを使用すると、オフセットはいつでも決めることができますが、その逆はできません。

は、America/MontrealAfrica/Casablanca、又はPacific/Aucklandとして、continent/regionの形式でproper time zone nameを指定します。 ESTまたはISTのような3〜4文字の略語は、ではなく、のように、標準化されておらず、ユニークではない(!)と使用しないでください。

ZoneId z = ZoneId.of("Australia/Brisbane") ; 

現在の瞬間を、そのゾーンの人々が見た壁時計の時間内にキャプチャします。

ZonedDateTime zdt = ZonedDateTime.now(z) ; 

時間をオーバーライドします。

ZonedDateTime zdt23 = zdt.withHour(23) ; 

について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.sql。*クラスは必要ありません。

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

  • Java SE 8Java SE 9、以降
    • 内蔵しています。
    • バンドルされた実装の標準Java APIの一部です。
    • Java 9には、いくつかのマイナーな機能と修正が加えられています。
  • Java SE 6Java SE 7
    • java.time機能の多くはThreeTen-BackportのJava 6 & 7に戻って、移植されます。
  • Android
    • java.timeクラスのAndroidのバンドル実装以降のバージョン。
    • 以前のAndroidの場合、ThreeTenABPプロジェクトはThreeTen-Backport(上記)に適合しています。 How to use ThreeTenABP…を参照してください。

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