1. 개요

이 빠른 사용방법(예제)에서는 Java에서 두 날짜 간의 차이를 계산하는 여러 가능성을 탐색합니다.

2. 코어 자바

2.1. java.util.Date사용하여  일의 차이 찾기

핵심 Java API를 사용하여 계산을 수행하고 두 날짜 사이의 일 수를 결정하는 것으로 시작하겠습니다.

@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(6, diff);
}

 

2.2. java.time.temporal.ChronoUnit사용 하여 차이점 찾기

Java 8의 Time API는 TemporalUnit  인터페이스를 사용하여 날짜-시간 단위(예: 초 또는 일)를 나타  냅니다.

각 단위는 특정 단위를 기준으로 두 시간 객체 사이의 시간을 계산하기 위해 사이명명된 메서드에 대한 구현을 제공합니다 .

예를 들어 두 LocalDateTime 사이의 초를 계산하려면 다음을 수행합니다 .

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

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

    assertEquals(10, diff);
}

ChronoUnit TemporalUnit 인터페이스를 구현하여 구체적인 시간 단위 세트를 제공합니다. 가독성을 높이 려면 ChronoUnit 열거형 값을 정적으로 가져오는 것이 좋습니다 .

import static java.time.temporal.ChronoUnit.SECONDS;

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

또한 두 개의 호환 가능한 시간 객체를 사이  메서드에 전달할 수 있습니다(  심지어  ZonedDateTime ) .

무엇에 대한 위대한  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(6, diff);
}

2.3. 사용 ) (때까지 임시 #을

어떠한 시간적 같은 객체 LOCALDATE 또는 ZonedDateTime는 , 을 제공 할 때까지 다른까지 시간 계산 방법 시공간 지정된 단위 환산 :

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

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

    assertEquals(10, diff);
}

까지 시간적 #사이 TemporalUnit #  동일한 기능을위한 두 가지의 API이다.

2.4. 사용 java.time.Duration  및  java.time.Period을

Java 8에서 Time API는 DurationPeriod 라는 두 가지 새로운 클래스를 도입했습니다 .

시간 기반(시간, 분 또는 초) 시간에서 두 날짜-시간의 차이를 계산하려면 Duration  클래스를 사용할 수 있습니다 .

@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(6, diff);
}

그러나 Period 클래스를 사용하여 두 날짜 간의 차이를 나타내 려고 하면 함정에 주의해야 합니다 .

예를 들어 이 함정을 빠르게 설명할 수 있습니다.

Period 클래스를 사용하여 두 날짜 사이의 일수를 계산해 보겠습니다 .

@Test
public void givenTwoDatesInJava8_whenUsingPeriodGetDays_thenWorks()  {
    LocalDate aDate = LocalDate.of(2020, 9, 11);
    LocalDate sixDaysBehind = aDate.minusDays(6);

    Period period = Period.between(aDate, sixDaysBehind);
    int diff = Math.abs(period.getDays());

    assertEquals(6, diff);
}

위의 테스트를 실행하면 통과합니다. Period 클래스가 문제를 해결하는 데 편리 하다고 생각할 수 있습니다. 여태까지는 그런대로 잘됐다.

이 방법이 6일의 차이로 작동한다면 60일 동안도 작동할 것이라는 데 의심의 여지가 없습니다.

따라서 위의 테스트 에서 660으로 변경하고  어떤 일이 발생하는지 봅시다 .

@Test
public void givenTwoDatesInJava8_whenUsingPeriodGetDays_thenDoesNotWork() {
    LocalDate aDate = LocalDate.of(2020, 9, 11);
    LocalDate sixtyDaysBehind = aDate.minusDays(60);

    Period period = Period.between(aDate, sixtyDaysBehind);
    int diff = Math.abs(period.getDays());

    assertEquals(60, diff);
}

이제 테스트를 다시 실행하면 다음이 표시됩니다.

java.lang.AssertionError: 
Expected :60
Actual   :29

앗! 기간 클래스가 차이를 29 일로 보고한 이유는 무엇 입니까?

이는 Period 클래스가 "x년, y개월, z일" 형식으로 날짜 기반 시간을 나타내기 때문  입니다. getDays()  메서드를 호출 하면 "z일" 부분만 반환합니다.

따라서 위 테스트 기간  개체는 "0년 1개월 29일" 값을 보유합니다.

@Test
public void givenTwoDatesInJava8_whenUsingPeriod_thenWeGet0Year1Month29Days() {
    LocalDate aDate = LocalDate.of(2020, 9, 11);
    LocalDate sixtyDaysBehind = aDate.minusDays(60);
    Period period = Period.between(aDate, sixtyDaysBehind);
    int years = Math.abs(period.getYears());
    int months = Math.abs(period.getMonths());
    int days = Math.abs(period.getDays());
    assertArrayEquals(new int[] { 0, 1, 29 }, new int[] { years, months, days });
}

Java 8의 Time API를 사용하여 일수 차이를 계산하려면 ChronoUnit.DAYS.between()  메서드가 가장 간단한 방법입니다.

3. 외부 라이브러리

3.1. 조다타임

JodaTime을 사용 하여 비교적 간단하게 구현할 수도 있습니다 .

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

Maven Central에서 최신 버전의 Joda-time얻을 수 있습니다 .

LocalDate 케이스:

@Test
public void givenTwoDatesInJodaTime_whenDifferentiating_thenWeGetSix() {
    org.joda.time.LocalDate now = org.joda.time.LocalDate.now();
    org.joda.time.LocalDate sixDaysBehind = now.minusDays(6);

    long diff = Math.abs(Days.daysBetween(now, sixDaysBehind).getDays());
    assertEquals(6, diff);
}

마찬가지로 LocalDateTime 사용 :

@Test
public void givenTwoDateTimesInJodaTime_whenDifferentiating_thenWeGetSix() {
    org.joda.time.LocalDateTime now = org.joda.time.LocalDateTime.now();
    org.joda.time.LocalDateTime sixMinutesBehind = now.minusMinutes(6);

    long diff = Math.abs(Minutes.minutesBetween(now, sixMinutesBehind).getMinutes());
    assertEquals(6, diff);
}

3.2. 데이트4J

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(6, diff);
}

4. 결론

이 기사에서는 일반 Java와 외부 라이브러리를 사용하여 날짜(시간이 있는 것과 없는 것) 간의 차이를 계산하는 몇 가지 방법을 설명했습니다.

기사의 전체 소스 코드는 GitHub에서 사용할 수 있습니다 .
Junit footer banner