JavaでDate型の値を使用して現在日付の比較をする際に、 new Date() を現在日付として使用すると思わぬ不具合が発生します。
その理由と、対策方法を解説します。
new Date()は時間も取得する
Javaで日付を生成するときによく使われる new Date() は現在日付と時間が取得されます。
import java.util.*; public class Main { public static void main(String[] args) throws Exception { System.out.println(new Date()); // Tue Jan 26 10:28:46 UTC 2021 } }
そのため、例えば本日が「2021/1/26」だとして、「2021/1/26」が本日かどうかを判定する際に以下のように書くと期待通りの結果が返却されません。
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; public class Main { public static void main(String[] args) throws ParseException { // 比較したい日付 String inpDateStr = "2021/01/26 00:00:00"; SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss"); Date date = sdf.parse(inpDateStr); // 現在日付(2021/1/26) Date currentDate = new Date(); if (date.compareTo(currentDate) >= 0) { System.out.println("本日以降!"); } else { System.out.println("本日よりも前!"); } // 本日よりも前!が出る } }
compareToの結果は以下のようになります。
比較元 | 比較対象 | 結果 |
2021/1/26 | 2021/1/26 | 0 |
2021/1/27 | 2021/1/26 | 1 |
2021/1/25 | 2021/1/26 | -1 |
本日日付と同じ日付を想定している場合は、compareToの結果が0になって「本日以降!」が表示されることを期待します。
しかしながら、本日日付として new Date() を使用すると、前述の通り時間も現在の時間になるので、”2021/01/26 00:00:00″と”2021/01/26 20:03:12″を比較することになるため、compareToの結果は-1となり、「本日より前!」が表示されてしまいます。
現在日時かつ00時00分00の取得方法
指定の日付が本日の日付かどうかを正しく判定するには、本日の日付が”2021/01/26 00:00:00″である必要があります。
これは new Date() では取得できないので、以下の方法で取得します。
import java.text.ParseException; import java.text.SimpleDateFormat; import java.time.LocalDate; import java.time.ZoneId; import java.util.Date; public class Main { public static void main(String[] args) throws ParseException { // 比較したい日付 String inpDateStr = "2021/01/26 00:00:00"; SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd hh:mm:ss"); Date date = sdf.parse(inpDateStr); // 現在日付(2021/1/26) LocalDate localCurrentDate = LocalDate.now(); Date currentDate = Date.from(localCurrentDate.atStartOfDay(ZoneId.systemDefault()).toInstant()); if (date.compareTo(currentDate) >= 0) { System.out.println("本日以降!"); } else { System.out.println("本日よりも前!"); } // 本日以降! } }
LocalDate型のnow()を使用すると、現在日付かつ00時00分00を取得することができます。
ただし、そのままだとLocalDate型のままなので、Date型に変換する必要があります。
変換した値を使用すれば、無事に本日現在日付で正しく比較することができます。
ただし、Date型の比較はおススメできない
実はそもそもDate型で比較することはあまりおススメできません。
Date型は古い時代からある日付を扱う型ですが、使いづらいという課題を抱えていました。
2014年にリリースされた、Java SE 8 というバージョンで追加された、公式のパッケージである「time」はDate型が抱える使いづらさなどを解決しました。
そのため、現在のJavaにおいてDate型はあまり使用するべき型ではなく、「time」パッケージに含まれている「LocalDate型」や「LocalDateTime型」を使用することをおススメします。
import java.text.ParseException; import java.time.LocalDate; public class Main { public static void main(String[] args) throws ParseException { // 比較したい日付 LocalDate localDate = LocalDate.of(2021, 1, 26); // 現在日付(2021/1/26) LocalDate localCurrentDate = LocalDate.now(); if (localDate.compareTo(localCurrentDate) >= 0) { System.out.println("本日以降!"); } else { System.out.println("本日よりも前!"); } // 本日以降! } }
このように、LocalDateを使用すると非常にシンプルに記述することができますし、SimpleDateFormat のような変換を挟んだりする必要もなくなります。
Javaで日付を使用する場合は「LocalDate型」や「LocalDateTime型」を使用しましょう。
ちなみにDate型が良く使用される理由ですが、Javaは比較的歴史のある言語であるため、Javaを書く人も歴史がある人であるケースがあります。
きちんと最新情報を追いかけている人であれば問題ないですが、意外と最新情報を追いかけていない人もいます。
その様な方がDate型を使っているケースが多いです。
まとめ
Javaで現在日付をDate型で比較する場合は、現在日付の作成の仕方に注意が必要です。
new Date() で現在日付を作成した場合は、日付だけではなく時間も取得されます。(Tue Jan 26 10:28:46 UTC 2021)
その値を使用すると、時間含む時間で比較するので想定していない結果となってしまう可能性があるのでご注意ください。
【お知らせ 無料!】未経験エンジニアがJavaでWebサイトを作成できるようになるための学習ロードマップを、無料で公開しています!
実体験に基づいて作成されているので、プログラミングスクールなどで指導されるロードマップにも劣らない品質です。
こちらの「【Java】エンジニア未経験者がJavaを効率的に勉強する手順を紹介します」リンクから無料で閲覧できるので、是非ご覧ください!