Javaプログラミングにおいて、旧来からある java.util.Date 型を、より扱いやすく設計された java.time.LocalDate 型へ変換したいという場面が多くあります。直接 Date 型から LocalDate 型へ変換するメソッドは用意されていないため、いくつかのステップを踏む必要があります。本稿ではその手順を丁寧に解説します。
なぜ変換が必要か?
java.util.Date は長らく Java の日付型として使用されてきましたが、以下のような欠点があります:
-
時刻・タイムゾーン・ミリ秒などの扱いがあいまいでエラーの原因になりやすい
-
スレッドセーフでない操作や可読性の低いAPIが多い
-
JDK8で導入された
java.timeパッケージのモダンな日付/時刻処理に比べて機能が乏しい
一方、 java.time.LocalDate は 日付だけ(年・月・日) を扱うため、例えば「今日の日付」「誕生日」「請求日」など 時間を伴わない日付情報 を明確に扱う用途に適しています。したがって、レガシーな Date 型から LocalDate 型へ変換することで、コードの明確性・保守性・バグ防止の観点から有利になります。
変換の流れ(概要)
java.util.Date を LocalDate に変換する一般的な流れは次の通りです:
-
java.util.Dateから時刻・ミリ秒値を取得 -
java.time.Instantやjava.sql.Timestamp/java.sql.Dateへ変換 -
そこから
java.time.LocalDateTimeやjava.time.LocalDateに変換
直接的な変換メソッドは用意されていないため、いずれかの中間型を経由する方法を採ります。
サンプルコード
以下は Date 型から LocalDate 型へ変換するサンプルです。2通りの変換方法を示しています。
実行すると、現在の「年‐月‐日」形式の LocalDate 値が表示されるはずです。
補足:タイムゾーン・時刻情報について
上述の変換では、Date に含まれる「時刻・ミリ秒値」をそのまま LocalDate に反映しています。このため、実際のローカルタイムゾーン・夏時間(DST)などによっては意図しない日付ずれが起きる可能性があります。具体的には次のような点に注意してください:
-
Date.getTime()は UTC 1970-01-01 00:00 からのミリ秒数を返します。 -
Timestamp.toLocalDateTime()はシステムのデフォルトタイムゾーンを参照してLocalDateTimeを生成します。 -
その結果、たとえば日本時間(UTC+9)で深夜近くに変換した場合など、日付が1日ずれることがあります。
-
結局「日付だけを取得したい」 という目的であれば、変換前の
Dateをどのタイムゾーンで評価するかを明確にしておくと安全です。
例えば、「システムデフォルトではなく特定のタイムゾーン(例:Asia/Tokyo)で評価したい」の場合は、Instant.atZone(ZoneId.of("Asia/Tokyo")) を使って ZonedDateTime を生成する流れも考慮すべきです。
よりモダンな代替:Instantを経由する方法
上記で紹介した Timestamp や java.sql.Date を使う方法は動作しますが、JDK 8 の java.time API に則ったより明確な代替として、次のようなメソッドもあります:
この方法では、タイムゾーンを明示して Instant を LocalDate に変換できるため、「どのタイムゾーンで日付を切り捨てるか」がより明確になります。
まとめ
-
java.util.Dateは時刻・ミリ秒・タイムゾーンなどを含む旧来型で、日付だけを扱いたい場合にjava.time.LocalDateへ変換することでコードの明快化・バグ軽減につながります。 -
直接の変換メソッドは存在しないため、
Timestamp/java.sql.Date経由、もしくはInstant+ZoneIdを経由して変換します。 -
タイムゾーンの扱いが日付の結果に影響するため、扱う環境(システムデフォルト/明示ゾーン)を意識しておきましょう。
-
日付だけを扱う処理(請求日・誕生日・締め日など)では、LocalDate 型を積極的に利用することでコードの可読性・保守性が向上します。
