Javaでの日付の比較

1. 前書き

このチュートリアルでは、https://www.baeldung.com/java-8-date-time-intro [Java 8 Date / Time API]を使用して日付を比較する方法に焦点を当てます。 2つの日付が等しいかどうか、および日付を比較する方法を確認するために、さまざまな方法に飛び込みます。

2. 日付の比較

Javaで日付を表現する基本的な方法は、_LocalDate_です。 2019年8月10日と2019年7月1日を表す2つの_LocalDate_オブジェクトインスタンスを考えてみましょう。
LocalDate firstDate = LocalDate.of(2019, 8, 10);
LocalDate secondDate = LocalDate.of(2019, 7, 1);
  • isAfter()、_ isBefore()、および_isEqual()メソッド、および_equals()_および_compareTo() *を使用して、2つの_LocalDate_オブジェクトを比較します。

    _isAfter()_メソッドを使用して、日付インスタンスが他の指定された日付の後かどうかを確認します。 したがって、次のJUnitアサーションは合格します。
assertThat(firstDate.isAfter(secondDate), is(true));
同様に、メソッド_isBefore()_は、日付インスタンスが他の指定された日付より前かどうかを確認します。
assertThat(firstDate.isBefore(secondDate), is(false));
メソッド_isEqual()_は、日付がローカルタイムライン上の他の指定された日付と同じポイントを表すかどうかを確認します。
assertThat(firstDate.isEqual(firstDate), is(true));
assertThat(firstDate.isEqual(secondDate), is(false));

2.1. _Comparable_インターフェイスを使用した日付の比較

_equals()_メソッドは、_isEqual()_と同じ結果を返しますが、渡された引数が同じタイプ(この場合は_LocalDate_)である場合のみです。
assertThat(firstDate.equals(secondDate), is(false));
代わりに_isEqual()_メソッドを使用して、_JapaneseDate _、_ ThaiBuddhistDate_などの異なるタイプのオブジェクトと比較できます。
_Comparable_インターフェイスで定義されている_compareTo()_メソッドを使用して、2つの日付インスタンスを比較できます。
assertThat(firstDate.compareTo(secondDate), is(1));
assertThat(secondDate.compareTo(firstDate), is(-1));

3. 時間コンポーネントを含む日付インスタンスの比較

このセクションでは、2つの_LocalDateTime_インスタンスを比較する方法について説明します。 _LocalDateTime_インスタンスには、日付と時刻コンポーネントが含まれます。
  • LocalDate_と同様に、2つの_LocalDateTime_インスタンスをメソッド_isAfter()、_ isBefore()および_isEqual() *と比較しています。 加えて、_equals()_と_compareTo()_は、_LocalDate._で説明したのと同様の方法で使用できます。

    同様に、2つの_ZonedDateTime_インスタンスを比較するために同じメソッドを使用できます。 同じ日、ニューヨークの現地時間8:00とベルリンの現地時間14:00を比較してみましょう。
ZonedDateTime timeInNewYork =
  ZonedDateTime.of(2019, 8, 10, 8, 0, 0, 0, ZoneId.of("America/New_York"));
ZonedDateTime timeInBerlin =
  ZonedDateTime.of(2019, 8, 10, 14, 0, 0, 0, ZoneId.of("Europe/Berlin"));

assertThat(timeInNewYork.isAfter(timeInBerlin), is(false));
assertThat(timeInNewYork.isBefore(timeInBerlin), is(false));
assertThat(timeInNewYork.isEqual(timeInBerlin), is(true));
両方の_ZonedDateTime_インスタンスは同じ瞬間を表しますが、同等のJavaオブジェクトを表すわけではありません。 内部に異なる_LocalDateTime_および_ZoneId_フィールドがあります。
assertThat(timeInNewYork.equals(timeInBerlin), is(false));
assertThat(timeInNewYork.compareTo(timeInBerlin), is(-1));

4. 追加の比較

少し複雑な比較のために、単純なユーティリティクラスを作成しましょう。
最初に、_LocalDateTime_と_LocalDate_のインスタンスが同じ日になっているかどうかを確認します。
public static boolean isSameDay(LocalDateTime timestamp,
  LocalDate localDateToCompare) {
    return timestamp.toLocalDate().isEqual(localDateToCompare);
}
次に、_LocalDateTime_の2つのインスタンスが同じ日になっているかどうかを確認します。
public static boolean isSameDay(LocalDateTime timestamp,
  LocalDateTime timestampToCompare) {
    return timestamp.truncatedTo(DAYS)
      .isEqual(timestampToCompare.truncatedTo(DAYS));
}
  • _truncatedTo(TemporalUnit)_メソッドは、指定されたレベル*(この例では1日)で日付を切り捨てます。

    第三に、1時間のレベルで比較を実装できます。
public static boolean isSameHour(LocalDateTime timestamp,
  LocalDateTime timestampToCompare) {
    return timestamp.truncatedTo(HOURS)
      .isEqual(timestampToCompare.truncatedTo(HOURS));
}
最後に、同様の方法で、同じ時間内に2つの_ZonedDateTime_インスタンスが発生するかどうかを確認できます。
public static boolean isSameHour(ZonedDateTime zonedTimestamp,
  ZonedDateTime zonedTimestampToCompare) {
    return zonedTimestamp.truncatedTo(HOURS)
      .isEqual(zonedTimestampToCompare.truncatedTo(HOURS));
}
2つの_ZonedDateTime_オブジェクトは、現地時間が異なっていても(それぞれ8:30と14:00)実際には同じ時間内に発生していることがわかります。
ZonedDateTime zonedTimestamp =
  ZonedDateTime.of(2019, 8, 10, 8, 30, 0, 0, ZoneId.of("America/New_York"));
ZonedDateTime zonedTimestampToCompare =
  ZonedDateTime.of(2019, 8, 10, 14, 0, 0, 0, ZoneId.of("Europe/Berlin"));

assertThat(DateTimeComparisonUtils.
  isSameHour(zonedTimestamp, zonedTimestampToCompare), is(true));

5. Old Java Date APIの比較

Java 8より前は、_java.util.Date_および_java.util.Calendar_クラスを使用して日付/時刻情報を操作する必要がありました。 古いJava Date APIの設計には、複雑でスレッドセーフではないなど、多くの欠点があります。 _java.util.Date_インスタンスは、実際の日付ではなく、「時間のインスタント」を表します。
ソリューションの1つは、https://www.baeldung.com/joda-time [Joda Time]ライブラリを使用することでした。 Java 8のリリース以降、https://www.baeldung.com/migrating-to-java-8-date-time-api [Java 8 Date / Time APIへの移行]をお勧めします。
  • LocalDate_および_LocalDateTime_と同様に、_java.util.Date_および_java.util.Calendar_オブジェクトの両方に、2つの日付インスタンスを比較するための_after()、_ before() compareTo()_および_equals()_メソッドがあります*。 日付は、ミリ秒のレベルで時刻として比較されます。

Date firstDate = toDate(LocalDateTime.of(2019, 8, 10, 0, 00, 00));
Date secondDate = toDate(LocalDateTime.of(2019, 8, 15, 0, 00, 00));

assertThat(firstDate.after(secondDate), is(false));
assertThat(firstDate.before(secondDate), is(true));
assertThat(firstDate.compareTo(secondDate), is(-1));
assertThat(firstDate.equals(secondDate), is(false));
より複雑な比較については、https://search.maven.org/search?q = g:org.apache.commons%20AND%20a:commons-lang3 [Apache Commons Lang]ライブラリの_DateUtils_を使用できます。 このクラスには、_Date_および_Calendar_オブジェクトを処理するための多くの便利なメソッドが含まれています。
public static boolean isSameDay(Date date, Date dateToCompare) {
    return DateUtils.isSameDay(date, dateToCompare);
}

public static boolean isSameHour(Date date, Date dateToCompare) {
    return DateUtils.truncatedEquals(date, dateToCompare, Calendar.HOUR);
}
*異なるAPIから生成された日付オブジェクトを比較するには、最初に適切な変換を行ってから比較を適用する必要があります。*詳細はlink:/java-date-to-localdate -および-localdatetime [日付をLocalDateまたはLocalDateTimeに変換して戻る]チュートリアル。

6. 結論

この記事では、Javaで日付インスタンスを比較するさまざまな方法を検討しました。
Java 8のDate / Timeクラスには、時間とタイムゾーンの有無にかかわらず、日付を比較するための豊富なAPIがあります。 また、日、時間、分などの粒度で日付を比較する方法も見てきました。
追加の例を含む、記事に記載されているすべてのコードスニペットは、https://github.com/eugenp/tutorials/tree/master/java-dates-2 [GitHub上]で入手できます。