1概要

この簡単な記事では、Javaで2つの日付の差を計算する複数の可能性を探ります。


2コアJava


2.1.

java.util.Date

を使用して日数の差を調べる

まず、コアJava APIを使用して計算を行い、2つの日付の間の日数を調べます。

@Test
public void givenTwoDatesBeforeJava8__whenDifferentiating__thenWeGetSix()
  throws ParseException {

    SimpleDateFormat sdf = new SimpleDateFormat("MM/dd/yyyy", Locale.ENGLISH);
    Date firstDate = sdf.parse("06/24/2017");
    Date secondDate = sdf.parse("06/30/2017");

    long diffInMillies = Math.abs(secondDate.getTime() - firstDate.getTime());
    long diff = TimeUnit.DAYS.convert(diffInMillies, TimeUnit.MILLISECONDS);

    assertEquals(diff, 6);
}

** 2.2.

java.time

を使用する – Java 8以降


LocalDate、LocalDateTime

を使用して2つの日付(時間の有無にかかわらず)を

Period

および__Durationと組み合わせて表すと、差の計算がより直感的になります。


LocalDate

の違い:

@Test
public void givenTwoDatesInJava8__whenDifferentiating__thenWeGetSix() {
    LocalDate now = LocalDate.now();
    LocalDate sixDaysBehind = now.minusDays(6);

    Period period = Period.between(now, sixDaysBehind);
    int diff = period.getDays();

    assertEquals(diff, 6);
}


LocalDateTime

の場合

@Test
public void givenTwoDateTimesInJava8__whenDifferentiating__thenWeGetSix() {
    LocalDateTime now = LocalDateTime.now();
    LocalDateTime sixMinutesBehind = now.minusMinutes(6);

    Duration duration = Duration.between(now, sixMinutesBehind);
    long diff = Math.abs(duration.toMinutes());

    assertEquals(diff, 6);
}


ここ

このAPIのもう少し詳細です。

** 2.3.

java.time.temporal.ChronoUnit

を使用して秒数の差を求める

Java 8のTime APIは日時の単位を表します。秒数または日数。

  • 各ユニットはhttps://docs.oracle.com/javase/8/docs/api/java/time/temporal/TemporalUnit.html#between-java.time.temporal.Temporal-javaという名前のメソッドの実装を提供します。 time.temporal.Temporal – [

    between

    ] – 特定の単位** に関して、2つの時間オブジェクト間の時間を計算します。

たとえば、2つの

__LocalDateTime

__の間の秒数を計算するには、次のようにします。

@Test
public void givenTwoDateTimesInJava8__whenDifferentiatingInSeconds__thenWeGetTen() {
    LocalDateTime now = LocalDateTime.now();
    LocalDateTime tenSecondsLater = now.plusSeconds(10);

    long diff = ChronoUnit.SECONDS.between(now, tenSecondsLater);

    assertEquals(diff, 10);
}



ChronoUnit


は、

TemporalUnit

インタフェースを実装することによって一連の具体的な時間単位を提供します。

読みやすくするために、

ChronoUnit

列挙値を静的にインポートすることを強くお勧めします。

import static java.time.temporal.ChronoUnit.SECONDS;
//omitted
long diff = SECONDS.between(now, tenSecondsLater);

また、

ZonedDateTimeでも、互換性のある2つのテンポラルオブジェクトを


between

__メソッドに渡すことができます。


ZonedDateTime

の素晴らしいところは、計算が異なるタイムゾーンに設定されていても機能することです。

@Test
public void givenTwoZonedDateTimesInJava8__whenDifferentiating__thenWeGetSix() {
    LocalDateTime ldt = LocalDateTime.now();
    ZonedDateTime now = ldt.atZone(ZoneId.of("America/Montreal"));
    ZonedDateTime sixMinutesBehind = now
      .withZoneSameInstant(ZoneId.of("Asia/Singapore"))
      .minusMinutes(6);

    long diff = ChronoUnit.MINUTES.between(sixMinutesBehind, now);

    assertEquals(diff, 6);
}


2.4.

java.time.temporal.Temporal


until()


を使用する



Temporal


オブジェクト。


_LocalDateまたはZonedDateTime。 .temporal.TemporalUnit – 指定された単位で別の時間までの時間を計算するための[

until_

]メソッド:

@Test
public void givenTwoDateTimesInJava8__whenDifferentiatingInSecondsUsingUntil__thenWeGetTen() {
    LocalDateTime now = LocalDateTime.now();
    LocalDateTime tenSecondsLater = now.plusSeconds(10);

    long diff = now.until(tenSecondsLater, ChronoUnit.SECONDS);

    assertEquals(diff, 10);
}


__の間の

Temporal#until



__TemporalUnit#は、同じ機能に対する2つの異なるAPIです。

** 3外部ライブラリ


3.1.

JodaTime



JodaTime

を使って比較的簡単な実装を行うこともできます。

<dependency>
    <groupId>joda-time</groupId>
    <artifactId>joda-time</artifactId>
    <version>2.9.9</version>
</dependency>

最新バージョンのhttps://search.maven.org/classic/#search%7Cga%7C1%7Ca%3A%22joda-time%22[Joda-time]はMaven Centralから入手できます。


ローカル日付

ケース:

@Test
public void givenTwoDatesInJodaTime__whenDifferentiating__thenWeGetSix() {
    LocalDate now = LocalDate.now();
    LocalDate sixDaysBehind = now.minusDays(6);

    Period period = new Period(now, sixDaysBehind);
    long diff = Math.abs(period.getDays());

    assertEquals(diff, 6);
}

同様に、

LocalDateTime

では次のようになります。

@Test
public void givenTwoDateTimesInJodaTime__whenDifferentiating__thenWeGetSix() {
    LocalDateTime now = LocalDateTime.now();
    LocalDateTime sixMinutesBehind = now.minusMinutes(6);

    Period period = new Period(now, sixMinutesBehind);
    long diff = Math.abs(period.getDays());
}


3.2.

Date4J



Date4j

は、この場合、明示的に__TimeZoneを提供する必要があることに注意することなく、直接的で単純な実装も提供します。

Mavenの依存関係から始めましょう。

<dependency>
    <groupId>com.darwinsys</groupId>
    <artifactId>hirondelle-date4j</artifactId>
    <version>1.5.1</version>
</dependency>

これは標準の

DateTime

を使った簡単なテストです。

@Test
public void givenTwoDatesInDate4j__whenDifferentiating__thenWeGetSix() {
    DateTime now = DateTime.now(TimeZone.getDefault());
    DateTime sixDaysBehind = now.minusDays(6);

    long diff = Math.abs(now.numDaysFrom(sixDaysBehind));

    assertEquals(diff, 6);
}


4結論

このチュートリアルでは、単純なJavaと外部ライブラリの両方を使用して、日付間の時間差(時間のあるなしにかかわらず)を計算する方法をいくつか示しました。

この記事の完全なソースコードはhttps://github.com/eugenp/tutorials/tree/master/java-dates[GitHubで利用可能]です。