Java 8には、日付と時刻の完全に新しいAPIがあります。このAPIで最も有用なクラスの1つは、LocalDateTime
タイムゾーンに依存しない日時付きの値を保持するためのクラスです。
java.util.Date
この目的でレガシークラスを使用しているコードはおそらく数百万行あります。そのため、古いコードと新しいコードをインターフェイスする場合、2つのコード間で変換する必要があります。これを達成するための直接的な方法はないように思われるので、どのようにそれを行うことができますか?
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の開始の真夜中)からのミリ秒数です。
java.util.Date
JSR-310と同等のクラスはですInstant
。したがって、前後の変換を提供する便利なメソッドがあります。
Date input = new Date();
Instant instant = input.toInstant();
Date output = Date.from(instant);
java.util.Date
インスタンスは、タイムゾーンの概念がありません。を呼び出すtoString()
とjava.util.Date
、これはtoString
タイムゾーンに関連しているため、これは奇妙に思えるかもしれません。ただし、このメソッドは実際にはオンザフライでJavaのデフォルトのタイムゾーンを使用して文字列を提供します。タイムゾーンはの実際の状態の一部ではありません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回発生するローカルタイムラインに重複があります。春にはギャップがあり、時間は消えます。atZone(ZoneId)
変換によって何が行われるかの詳細については、Javadocを参照してください。
要約するjava.util.Date
と、a LocalDateTime
とa を往復するjava.util.Date
場合、夏時間のために別の瞬間になる可能性があります。
追加情報:非常に古い日付に影響する別の違いがあります。java.util.Date
1582年10月15日に変更されるカレンダーを使用し、その前の日付はグレゴリオ暦ではなくユリウス暦を使用します。対照的にjava.time.*
、ISOカレンダーシステム(グレゴリオ暦に相当)を常に使用します。ほとんどのユースケースでは、ISOカレンダーシステムが必要ですが、1582年より前の日付を比較すると、奇妙な効果が見られる場合があります。
LocalDateTime.ofInstant(date.toInstant()...
本来の動作とは異なります。たとえば、このアプローチを使用new Date(1111-1900,11-1,11,0,0,0);
するようになり1111-11-17 23:53:28
ます。java.sql.Timestamp#toLocalDateTime()
結果1111-11-11 00:00:00
が前の例にある必要があるかどうかの実装を見てください。
java.sql.Date#toInstant
スローすることにも注意する価値がありUnsupportedOperationException
ます。したがってtoInstant
、のRowMapper では使用しないでくださいjava.sql.ResultSet#getDate
。
これが私が思いついたものです(そしてすべての日付時間の難問と同様に、それはおそらくいくつかの奇妙なタイムゾーン-うるう年-日光の調整に基づいて反証されるでしょう: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
Instant.ofEpochMilli(date.getTime())
DOdate.toInstant()
toInstant()
は見栄えがいいですが、arggggh で失敗しますjava.sql.Date
!ですから、ついに使いやすくなりますInstant.ofEpochMilli(date.getTime())
。
デフォルトのタイムゾーンが必要だと確信している場合は、はるかに便利な方法です。
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でない場合は、時刻を変更します。
LocalDateTime
-> の最速の方法Date
は:
Date.from(ldt.toInstant(ZoneOffset.UTC))
これが最も簡単な方法であるか、最良の方法であるか、または落とし穴があるかどうかはわかりませんが、機能します。
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();
}
LocalDateTime
にはDate
。夏時間の移行時に、a LocalDateTime
が存在しないか、2回発生する可能性があります。それぞれのケースで何が起こりたいかを考え出す必要があります。
GregorianCalendar
新しいjava.time
APIが置き換えることを目指している古い厄介なAPI に属しています
Androidを使用していて、threetenbpを使用している場合は、DateTimeUtils
代わりに使用できます。
例:
Date date = DateTimeUtils.toDate(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
Date.from
API 26以降でのみサポートされているため、使用できません