_Java.util.Date
_クラスには、Date
インスタンスを_Java.time.Instant
_に変換するtoInstant()
というメソッドがあります。
_Java.sql.Date
_クラスは_Java.util.Date
_クラスを拡張しますが、_Java.sql.Date
_でtoInstant()
を呼び出そうとすると、UnsupportedOperationException
を受け取ります。
なぜtoInstant()
は_Java.sql.Date
_でサポートされていない操作ですか?
_Java.sql.Date
_を_Java.time.Instant
_に変換する「正しい」方法は何ですか?
JavaDoc を確認してください
sql.Date
には時間コンポーネントがないため、それをtime.Instant
に変換する可能性はありません
このメソッドは常にUnsupportedOperationExceptionをスローします。SQLDate値には時刻コンポーネントがないため、使用しないでください。
Java.sql.Date
とJava.time
間の正しいマッピングはLocalDate
です:
LocalDate date = sqlDate.toLocalDate();
本当に必要な場合を使用すると、Instant
を導出できますが、追加情報(時間)は任意です。例えば:
Instant i = date.atStartOfDay(ZoneOffset.UTC).toInstant();
Java.sql.Dateには、日付コンポーネント(日付、月、および年)のみが含まれます。日付と時刻の両方のコンポーネントはありません。 toInstantはDate/Timeコンポーネントの両方を必要とするため、Java.sql.DateインスタンスのtoInstantはUnsupportedOperationException例外をスローします。
Java.util.Date OR Java.sql.Timestampには両方の日付/時刻コンポーネントがあるため、toInstant()が機能します!
このようにすることができます:
// Time is 00:00:00.000
new Java.util.Date(sqlDate.getTime()).toInstant()
更新:
Instant.ofEpochMilli(sqlDate.getTime());
// OR
new Java.util.Date(sqlDate.getTime()).toInstant();
ToInstant()がInstant.ofEpochMilli(getTime())を内部的に呼び出すため、同じ結果が返されます。
public Instant toInstant() {
return Instant.ofEpochMilli(getTime());
}
これまでの回答は、_Java.sql.Date
_に時間情報がないという詳細に集中しています。それは正しいですが、このタイプがInstant
への直接変換を提供できない本当の理由または十分な理由ではありません。残念ながら Java-8のドキュメント は同じ間違いをして、ユーザーに問題が時間情報が欠けているだけだと思わせるようにします。
概念的には、タイプ_Java.sql.Date
_はローカルタイプを表します。世界中のどの地域でも異なるカレンダー日付をモデル化しています。しかし、Instant
は世界中の地球上で同じです。 ユーザーは変換を行うためにタイムゾーンまたはタイムゾーンオフセットが必要です。
悲劇的なことに、タイプ_Java.sql.Date
_は、グローバル型(インスタントのような)である_Java.util.Date
_を継承します。ただし、この継承は実際には実装の継承を示しており、型の継承を示しているわけではありません。これらの古いJDBCクラスの設計が壊れていると考えるもう1つの理由。したがって、ハックを使用して、メソッドgetTime()
を介して_Java.sql.Date
_のインスタンス内で_Java.util.Date
_をラップし、最終的にインスタントへの直接変換を可能にすることができます。ただし、この変換では、システムのデフォルトのタイムゾーンが暗黙的に使用されます。
それでは、どのように正しく学問的な方法で変換するのでしょうか?ここで正しい方向を指している Java-8のドキュメント について考えてみましょう。
_Java.sql.Date sqlDate = ...;
LocalDate calendarDate = sqlDate.toLocalDate();
ZonedDateTime zdt = calendarDate.atStartOfDay(ZoneId.of("Europe/Paris"));
Instant instant = zdt.toInstant();
_