1. ホーム
  2. java

[解決済み] java.time.LocalDateTimeとjava.util.Date間の変換について

2022-03-18 15:21:19

質問

Java 8では、日付と時刻に関する全く新しいAPIが提供されています。このAPIで最も便利なクラスの1つが LocalDateTime タイムゾーンに依存しない日付と時刻の値を保持するためのものです。

おそらく何百万行ものコードがレガシークラス java.util.Date を使用します。そのため、古いコードと新しいコードをインターフェイスする際に、両者を変換する必要性があります。これを実現する直接的な方法はないようですが、どうすればいいのでしょうか?

どのように解決するのか?

簡単にお答えします。

Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());
Date out = Date.from(ldt.atZone(ZoneId.systemDefault()).toInstant());

説明する。 (ベースは この質問 について LocalDate )

その名前とは裏腹に java.util.Date は時間軸上の一瞬を表し、quot;date" ではありません。このオブジェクトに格納されている実際のデータは long 1970-01-01T00:00Z (1970年GMT/UTC開始の深夜) からのミリ秒のカウント。

と同等のクラスです。 java.util.Date は、JSR-310 では Instant そのため、変換を行うための便利なメソッドが用意されています。

Date input = new Date();
Instant instant = input.toInstant();
Date output = Date.from(instant);

A java.util.Date インスタンスにはタイムゾーンの概念がありません。これは、もしあなたが toString() の上で java.util.Date というのは toString はタイムゾーンに対する相対値です。しかし、このメソッドは実際にはJavaのデフォルトのタイムゾーンをその場で使用して文字列を提供します。タイムゾーンは、実際には java.util.Date .

An Instant は、タイムゾーンの情報も含んでいない。したがって Instant をローカルな日付時刻に変換するには、タイムゾーンを指定する必要があります。これは、デフォルトのゾーンであるかもしれません。 ZoneId.systemDefault() - あるいは、ユーザー設定のタイムゾーンなど、アプリケーションが制御するタイムゾーンを指定することもできます。 LocalDateTime には、インスタントとタイムゾーンの両方を取得する便利なファクトリーメソッドがあります。

Date in = new Date();
LocalDateTime ldt = LocalDateTime.ofInstant(in.toInstant(), ZoneId.systemDefault());

逆に LocalDateTime を呼び出すことで、タイムゾーンを指定することができます。 atZone(ZoneId) メソッドを使用します。は、その ZonedDateTime に直接変換することができます。 Instant :

LocalDateTime ldt = ...
ZonedDateTime zdt = ldt.atZone(ZoneId.systemDefault());
Date output = Date.from(zdt.toInstant());

からの変換に注意してください。 LocalDateTime から ZonedDateTime は、予期せぬ振る舞いを引き起こす可能性があります。これは、サマータイムにより、すべてのローカルな日付時刻が存在しないためである。秋には、ローカルタイムラインに重複があり、同じローカルタイムラインが2回発生する。春には、1時間が消えてしまうギャップがある。のJavadocを参照。 atZone(ZoneId) は、この変換が何を行うかの詳細な定義についてです。

要約すると、ラウンドトリップした場合 java.util.DateLocalDateTime に戻り、さらに java.util.Date の場合、夏時間の関係で異なる時刻が表示されることがあります。

追加情報です。非常に古い日付に影響するもう一つの違いがあります。 java.util.Date は1582年10月15日に変更される暦を使用しており、それ以前の日付はグレゴリオ暦ではなくユリウス暦を使用しています。それに対して java.time.* はISO暦法(グレゴリオ暦法と同等)を常に使用します。ほとんどの場合、ISO暦法が望ましいのですが、1582年以前の日付を比較すると、奇妙な効果が見られるかもしれません。