Java 8 には、日付と時刻用のまったく新しい API があります。この API で最も便利なクラスの 1 つはLocalDateTime
、タイムゾーンに依存しない日付と時刻の値を保持するための です。
java.util.Date
この目的でレガシー クラスを使用するコードは、おそらく何百万行にもなります。そのため、古いコードと新しいコードを接続する場合、2 つのコードを変換する必要があります。これを達成するための直接的な方法はないようですが、どのように行うことができますか?
簡潔な答え:
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
、「日付」ではなく、タイムライン上の瞬間を表します。オブジェクト内に格納されている実際のデータは、long
1970-01-01T00:00Z (1970 GMT/UTC 開始時の午前 0 時) からのミリ秒数です。
java.util.Date
JSR-310の と同等のクラスは ですInstant
。したがって、前後の変換を提供する便利なメソッドがあります。
Date input = new Date();
Instant instant = input.toInstant();
Date output = Date.from(instant);
java.util.Date
インスタンスにはタイムゾーンの概念がありません。はタイムゾーンに関連しているため、を呼び出すと奇妙に思えるかもしれませんtoString()
。ただし、そのメソッドは実際にはJavaのデフォルトのタイムゾーンをオンザフライで使用して文字列を提供します。タイムゾーンは の実際の状態の一部ではありません。java.util.Date
toString
java.util.Date
には、タイムゾーンに関する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時間がなくなる隙間があります。atZone(ZoneId)
変換が行うことの定義の詳細については、の Javadoc を参照してください。
要約すると、aとjava.util.Date
a を往復すると、夏時間のために別の瞬間になる可能性があります。LocalDateTime
java.util.Date
追加情報: 非常に古い日付に影響する別の違いがあります。java.util.Date
1582 年 10 月 15 日に変更されるカレンダーを使用し、それより前の日付はグレゴリオ暦ではなくユリウス暦を使用します。対照的に、java.time.*
は常に ISO 暦体系 (グレゴリオ暦に相当) を使用します。ほとんどの場合、ISO 暦体系が必要ですが、1582 年より前の日付を比較すると、奇妙な結果が生じる場合があります。
これが私が思いついたものです(そして、すべての日時の難問と同様に、奇妙なタイムゾーン-うるう年-夏時間の調整に基づいておそらく反証されるでしょう:D )
Date
<<->>LocalDateTime
与えられた:Date date = [some date]
(1) LocalDateTime
<< Instant
<<Date
Instant instant = Instant.ofEpochMilli(date.getTime());
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
(2) Date
<< Instant
<<LocalDateTime
Instant instant = ldt.toInstant(ZoneOffset.UTC);
Date date = Date.from(instant);
例:
Date date = new Date();
System.out.println(date + " long: " + date.getTime());
LocalDateTime
<< Instant
<< Date
:Instant
から作成Date
:
Instant instant = Instant.ofEpochMilli(date.getTime());
System.out.println("Instant from Date:\n" + instant);
以下から作成Date
しますInstant
(必須ではありませんが、説明のため):
date = Date.from(instant);
System.out.println("Date from Instant:\n" + date + " long: " + date.getTime());
LocalDateTime
から作成Instant
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
System.out.println("LocalDateTime from Instant:\n" + ldt);
Date
<< Instant
<<LocalDateTime
Instant
から作成LocalDateTime
:
instant = ldt.toInstant(ZoneOffset.UTC);
System.out.println("Instant from LocalDateTime:\n" + instant);
Date
から作成Instant
:
date = Date.from(instant);
System.out.println("Date from Instant:\n" + date + " long: " + date.getTime());
Fri Nov 01 07:13:04 PDT 2013 long: 1383315184574
Instant from Date:
2013-11-01T14:13:04.574Z
Date from Instant:
Fri Nov 01 07:13:04 PDT 2013 long: 1383315184574
LocalDateTime from Instant:
2013-11-01T14:13:04.574
Instant from LocalDateTime:
2013-11-01T14:13:04.574Z
Date from Instant:
Fri Nov 01 07:13:04 PDT 2013 long: 1383315184574
デフォルトのタイムゾーンが必要であることが確実な場合は、はるかに便利な方法:
Date d = java.sql.Timestamp.valueOf( myLocalDateTime );
すべてがここにあります: http://blog.progs.be/542/date-to-Java-time
「往復」の答えは正確ではありません。
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);
システムのタイムゾーンが UTC/GMT でない場合は、時刻を変更してください。
これが最も簡単な方法か最善の方法か、または落とし穴があるかどうかはわかりませんが、機能します。
static public LocalDateTime toLdt(Date date) {
GregorianCalendar cal = new GregorianCalendar();
cal.setTime(date);
ZonedDateTime zdt = cal.toZonedDateTime();
return zdt.toLocalDateTime();
}
static public Date fromLdt(LocalDateTime ldt) {
ZonedDateTime zdt = ZonedDateTime.of(ldt, ZoneId.systemDefault());
GregorianCalendar cal = GregorianCalendar.from(zdt);
return cal.getTime();
}