Java.util.Date
オブジェクト、またはJava.util.Calendar
オブジェクトがあります。 Java.time フレームワークでそれを正しい型に変換するにはどうすればよいですか?
Java.time型を使用してビジネスロジックの大部分を実行する必要があると聞いたことがあります。 Java.time用にまだ更新されていない古いコードを使用する場合、相互に変換できる必要があります。どのタイプがJava.util.Date
またはJava.util.Calendar
にマップされますか?
はい、できれば必ず Java.time フレームワークを使用する必要があります。
Java.util.Date
、 Java.util.Calendar
、およびJava.text.SimpleTextFormat
などを含む古い日時クラスは、 不十分な設計、混乱を招く、面倒です 。できる限り避けてください。ただし、これらの古いタイプと相互運用する必要がある場合は、古いものと新しいものを切り替えることができます。
多少単純化しすぎた基本的な紹介を読み、古い日時クラスと新しい日時クラスの間を行き来する方向に向けてください。
Java.time フレームワークは JSR 31 によって定義され、非常に成功した Joda-Time ライブラリに触発され、 ThreeTen-Extra プロジェクト。機能の大部分は ThreeTen-Backport プロジェクトのJava 6および7にバックポートされ、 のAndroid ThreeTenABP プロジェクト。
どのJava.time型が Java.util.Date
と一致しますか? Java.util.Date
オブジェクトは基本的に、UTCのタイムライン上の瞬間、日付と時刻の組み合わせを表します。これをJava.timeのいくつかのタイプのいずれかに変換できます。それぞれについて以下で説明します。変換を容易にするために、古い日時クラスにいくつかの新しいメソッドが追加されていることに注意してください。
Instant
Java.timeの構築ブロックは Instant
であり、 [〜#〜] utc [〜#〜] のタイムライン上の瞬間であり、解像度は nanoseconds 。
通常、UTCでビジネスロジックの多くを実行する必要があります。このような作業では、Instant
が頻繁に使用されます。 Instant
オブジェクトを渡し、ユーザーへのプレゼンテーションにのみタイムゾーンを適用します。 do オフセットまたはタイムゾーンを適用する必要がある場合は、以下でさらに説明するタイプを使用します。
Java.util.Date
からInstant
へInstant
とJava.util.Date
の両方がUTCのタイムライン上にあることを考えると、 Java.util.Date
からInstant
に簡単に移動できます。古いクラスは新しいメソッド Java.util.Date::toInstant
を取得しました。
Instant instant = myUtilDate.toInstant();
Instant
からJava.util.Date
まで、他の方向に進むことができます。ただし、秒の小数部に関する情報が失われる可能性があります。 Instant
は、2016-01-23T12:34:56.123456789Z
などの小数点以下9桁までの nanoseconds を追跡します。 Java.util.Dateと.Calendarは両方とも、2016-01-23T12:34:56.123Z
などの小数点以下3桁までの ミリ秒 に制限されています。この例でInstant
からDate
に移動すると、456789
が切り捨てられます。
Java.util.Date myUtilDate = Java.util.Date.from(instant);
Java.util.Calendar
からInstant
へJava.util.Calendar
の代わりに Java.util.Date
はどうですか? Calendar
オブジェクトの内部で、日付時刻は、UTC(1970-01-01T00:00:00.0Z
)の1970年の最初の瞬間の エポック基準日時 からの ミリ秒 のカウントとして追跡されます。したがって、この値はInstant
に簡単に変換できます。
Instant instant = myUtilCalendar.toInstant() ;
Java.util.GregorianCalendar
からZonedDateTime
へさらに良いのは、 Java.util.Calendar
オブジェクトが実際に Java.util.GregorianCalendar
である場合、 ZonedDateTime
に簡単に直接アクセスできることです。このアプローチには、埋め込まれたタイムゾーン情報を保持するという利点があります。
Calendar
の interface からGregorianCalendar
の 具象クラス への Downcast 。次に、 toZonedDateTime
および from
メソッドを呼び出して、前後に移動します。
if (myUtilCalendar instanceof GregorianCalendar) {
GregorianCalendar gregCal = (GregorianCalendar) myUtilCalendar; // Downcasting from the interface to the concrete class.
ZonedDateTime zdt = gregCal.toZonedDateTime(); // Create `ZonedDateTime` with same time zone info found in the `GregorianCalendar`
}
別の方向に行く…
Java.util.Calendar myUtilCalendar = Java.util.GregorianCalendar.from(zdt); // Produces an instant of `GregorianCalendar` which implements `Calendar` interface.
上で説明したように、1秒の端数に関する情報を失うになる可能性があることに注意してください。 Java.time型(ZonedDateTime
)の nanoseconds は、.Calendar
/.GregorianCalendar
の ミリ秒 に切り捨てられます。
OffsetDateTime
Instant
から offset-from-UTC を適用して、ある地域の wall-clock time に移動できます。オフセットは、 [〜#〜] utc [〜#〜] (東向き)またはUTCの後ろ(西向き)よりも前の時間数、場合によっては分と秒です。 ZoneOffset
クラスはこの考えを表しています。結果は OffsetDateTime
オブジェクトです。
ZoneOffset offset = ZoneOffset.of("-04:00");
OffsetDateTime odt = OffsetDateTime.ofInstant(instant, zoneOffset);
OffsetDateTime
からJava.util.Date
まで、他の方向に進むことができます。 Instant
を抽出し、上記のコードで見たように進めます。上記で説明したように、すべての ナノ秒 は ミリ秒 (データ損失)に切り捨てられます。
Java.util.Date myUtilDate = Java.util.Date.from(odt.toInstant());
ZonedDateTime
さらに良いことに、完全な タイムゾーン を適用します。タイムゾーンは、 夏時間(DST) などの異常を処理するためのオフセット plus ルールです。
ZoneId
を適用すると、 ZonedDateTime
オブジェクトが取得されます。 適切なタイムゾーン名 (大陸/地域)を使用します。 EST
やIST
など、一般的に見られる3〜4文字の略語は、標準化も一意化もされていないため使用しないでください。
ZoneId zoneId = ZoneId.of("America/Montreal");
ZonedDateTime zdt = ZonedDateTime.ofInstant(instant, zoneId);
ZonedDateTime
からJava.util.Date
まで、他の方向に進むことができます。 Instant
を抽出し、上記のコードで見たように進めます。上記で説明したように、すべての ナノ秒 は ミリ秒 (データ損失)に切り捨てられます。
Java.util.Date myUtilDate = Java.util.Date.from( zdt.toInstant() );
さらに、上記でZonedDateTime
をGregorianCalendar
に変換できることがわかりました。
LocalDate
時刻やタイムゾーンのない日付のみの値が必要な場合があります。そのためには、 Java.time.LocalDate
オブジェクトを使用します。
詳細については、この質問を参照してください。 Java.util.DateをJava.time.LocalDateに変換 、特に this Answer は、Joda-TimeとJavaの両方の発明の背後にある主人によって書かれました。時間。
重要なのは、ZonedDateTime
を経由することです(上記のコードで生成されます)。日付を決定するにはタイムゾーンが必要です。日付は世界中で異なり、東部では新しい日が早く始まります。たとえば、パリの真夜中は新しい日ですが、モントリオールでは「昨日」です。したがって、LocalDate
には contain タイムゾーンは含まれませんが、 determine LocalDate
にはタイムゾーンが必要です。
LocalDate localDate = zdt.toLocalDate();
LocalDate
から日時への逆方向への変換は、時刻を作成することを意味します。ビジネスシナリオで意味のある任意の時刻を選択できます。ほとんどの人にとって、その日の最初の瞬間は理にかなっています。その最初の瞬間を00:00:00.0
としてハードコーディングしたくなるかもしれません。一部のタイムゾーンでは、 夏時間(DST) またはその他の異常により、その時間が最初の瞬間として有効でない場合があります。そのため、Java.timeに atStartOfDay
を呼び出して正しい時間を決定させます。
ZonedDateTime zdt = localDate.atStartOfDay(zoneId);
LocalTime
まれに、日付とタイムゾーンのない時刻のみが必要な場合があります。この概念は、 LocalTime
クラスによって表されます。上記でLocalDate
で説明したように、LocalTime
オブジェクトにそのタイムゾーンが含まれていない(「覚えていない」)場合でも、LocalTime
を決定するにはタイムゾーンが必要です。したがって、再び、上記のようにZonedDateTime
から取得したInstant
オブジェクトを調べます。
LocalTime localTime = zdt.toLocalTime();
LocalDateTime
他の2つのLocal…
タイプと同様に、 LocalDateTime
にはタイムゾーンもオフセットも割り当てられていません。そのため、めったに使用しないこれ。日時の大まかなアイデアを提供しますが、タイムライン上の not ポイントです。これは、タイムゾーンに適用される一般的な日付と時刻を意味する場合に使用します。
たとえば、「今年はクリスマスが始まります」は2016-12-25T00:00:00.0
になります。 LocalDateTime
のテキスト表現にオフセットまたはタイムゾーンがないことに注意してください。クリスマスはパリのフランスよりも早くインドのデリーで始まり、その後はカナダのモントリオールで始まります。これらの各地域のタイムゾーンを適用すると、タイムライン上で異なる瞬間が得られます。
LocalDateTime ldt = zdt.toLocalDateTime();