Java8から java.time
が標準APIに入ったが、それ以前に書かれたソースだったり、ライブラリとの兼ね合いで、まだまだ java.util.Date
を扱う機会がある。
両方扱うときに困るのが変換方法で、だいたい検索すると LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
みたいなのが出てくる。
もうちょっと簡単に変換できる方法があるのでメモ。
- 環境
- java.util.Dateからjava.time.LocalDateTimeなどへの変換
- java.time.LocalDateTimeなどからjava.util.Dateへの変換
- 振り返り
- 余談
環境
Java8以降
java.util.Dateからjava.time.LocalDateTimeなどへの変換
java.util.Date
から直接 java.time.LocalDateTime
などへは変換できないが、 java.sql
パッケージの Date
, Time
, Timestamp
には、それぞれ対応する java.time
パッケージのクラスへの変換処理が、Java8の時点で用意されている。
なので、いったん java.util.Date#getTime()
をもとに java.sql
パッケージのクラスに変換するなどし、再度 java.time
パッケージのクラスへの変換処理を呼んでやればいい。
java.util.Date
からの変換であれば LocalDateTime
にすることが多いと思うが、 LocalDateTime
には日付部分を返す toLocalDate()
と時刻部分を返す toLocalTime()
があるので、とりあえず Timestamp
を経由しておくのが簡単。
java.util.Date date = ...; LocalDateTime localDateTime = new Timestamp(date.getTime()).toLocalDateTime(); LocalDate localDate = localDateTime.toLocalDate(); LocalTime localTime = localDateTime.toLocalTime();
Date#toInstant()
や ZoneId#systemDefault()
を覚えるよりは、こちらのほうが楽だと思う。
java.time.LocalDateTimeなどからjava.util.Dateへの変換
java.time
のクラスから java.util.Date
への変換の場合、これまた java.sql
パッケージの3クラスに、それぞれ対応する java.time
パッケージのクラスを引数に取る valueOf
メソッドが用意されている。
これらを使って java.sql
パッケージのクラスに変換してやれば、いずれも java.util.Date
を継承しているので、 java.util.Date
として扱える。
正確に java.util.Date
のインスタンスである必要がある場合は、 getTime()
した値でコンストラクタを読んでやればいい。
LocalDateTime localDateTime = ...; Timestamp timestamp = Timestamp.valueOf(localDateTime); java.sql.Date sqlDate = java.sql.Date.valueOf(localDateTime.toLocalDate()); Time time = Time.valueOf(localDateTime.toLocalTime()); java.util.Date utilDate = new java.util.Date(timestamp.getTime());
これを覚えておくと、任意の日時の java.util.Date
の作成が簡単にできるので、ユニットテストが捗る。
LocalDateTime testLocalDateTime = LocalDateTime.of(2021, 12, 19, 17, 30, 00); Timestamp testTimestamp = Timestamp.valueOf(testLocalDateTime ); java.util.Date testDate = new java.util.Date(testTimestamp.getTime());
振り返り
いずれも、 java.sql
パッケージのクラスと、 java.time
パッケージのクラスの対応関係だけ覚えておけばいいので、いろんな変換方法を覚えておくよりは簡単かなと思う。
変換処理の検索結果上位に乗ってこないのは、 java.sql
パッケージのクラスがあまり使われていないからだろうか?
余談
Groovy v2.5以降だと org.apache.groovy.datetime.extensions.DateTimeExtensions で、変換メソッドが拡張されている。
java.util.Date#toLocalDateTime() および LocalDateTime#toDate() など、相互変換が可能。
java.util.Calendar
にも toLocalDateTime()
などが拡張されている。