[java] 두 Java 날짜 인스턴스의 차이 계산

java.util.DateScala에서 Java 클래스를 사용 하고 있으며 Date객체와 현재 시간 을 비교하고 싶습니다 . getTime ()을 사용하여 델타를 계산할 수 있다는 것을 알고 있습니다.

(new java.util.Date()).getTime() - oldDate.getTime()

그러나 이것은 단지 long밀리 초를 나타냅니다. 시간 델타를 얻는 더 간단하고 좋은 방법이 있습니까?



답변

JDK DateAPI는 불행히도 크게 망가졌습니다. Joda Time 라이브러리를 사용하는 것이 좋습니다 .

Joda Time에는 시간 간격 개념이 있습니다 .

Interval interval = new Interval(oldTime, new Instant());

편집 : 그런데, Joda는 두 Interval시간 순간 사이의 시간 간격을 나타내는 개념 (8am과 10am 사이 Duration의 시간을 나타냄 )과 실제 시간 경계가없는 시간을 나타내는 것 (예 : 2 시간을 나타냄)이라는 두 가지 개념을 가지고 있습니다.

시간 비교에만 관심이 있다면 대부분의 Date구현 (JDK 포함) Comparable은 사용자가 사용할 수있는 인터페이스를 구현 합니다.Comparable.compareTo()


답변

간단한 diff (lib없이)

/**
 * Get a diff between two dates
 * @param date1 the oldest date
 * @param date2 the newest date
 * @param timeUnit the unit in which you want the diff
 * @return the diff value, in the provided unit
 */
public static long getDateDiff(Date date1, Date date2, TimeUnit timeUnit) {
    long diffInMillies = date2.getTime() - date1.getTime();
    return timeUnit.convert(diffInMillies,TimeUnit.MILLISECONDS);
}

그리고 당신은 전화 할 수 있습니다 :

getDateDiff(date1,date2,TimeUnit.MINUTES);

두 날짜의 차이를 분 단위로 가져옵니다.

TimeUnitjava.util.concurrent.TimeUnit나노에서 며칠로가는 표준 Java 열거 형입니다.


사람이 읽을 수있는 diff (lib없이)

public static Map<TimeUnit,Long> computeDiff(Date date1, Date date2) {

    long diffInMillies = date2.getTime() - date1.getTime();

    //create the list
    List<TimeUnit> units = new ArrayList<TimeUnit>(EnumSet.allOf(TimeUnit.class));
    Collections.reverse(units);

    //create the result map of TimeUnit and difference
    Map<TimeUnit,Long> result = new LinkedHashMap<TimeUnit,Long>();
    long milliesRest = diffInMillies;

    for ( TimeUnit unit : units ) {

        //calculate difference in millisecond 
        long diff = unit.convert(milliesRest,TimeUnit.MILLISECONDS);
        long diffInMilliesForUnit = unit.toMillis(diff);
        milliesRest = milliesRest - diffInMilliesForUnit;

        //put the result in the map
        result.put(unit,diff);
    }

    return result;
}

http://ideone.com/5dXeu6

출력은 Map:{DAYS=1, HOURS=3, MINUTES=46, SECONDS=40, MILLISECONDS=0, MICROSECONDS=0, NANOSECONDS=0}단위가 주문 된 것과 같습니다 .

해당 맵을 사용자 친화적 인 문자열로 변환하면됩니다.


경고

위의 코드 스 니펫은 두 순간 사이의 간단한 차이를 계산합니다. 이 게시물 에서 설명한 것처럼 일광 절약 스위치 중에 문제가 발생할 수 있습니다 . 즉, 시간이없는 날짜 사이의 차이를 계산하면 날짜 / 시간이 누락 될 수 있습니다.

내 의견으로는 날짜 차이는 주관적이며 특히 며칠입니다. 당신은 할 수있다:

  • 24 시간 경과 시간 계산 : day + 1-day = 1 day = 24h

  • 일광 절약 시간을 돌보는 경과 시간 수를 세십시오 : day + 1-day = 1 = 24h (그러나 자정 시간과 일광 절약 시간을 사용하면 0 일과 23 시간이 될 수 있습니다)

  • 수 집계 day switches(: P 일광 절약이있는 경우 또는 1H), 경과 시간은 단지 2H 경우에도, 일 오전 11 = 1 일 – + 1 일 오후 1시 수단

일의 날짜 차이 정의가 첫 번째 사례와 일치하면 내 답변이 유효합니다.

JodaTime으로

JodaTime을 사용하는 경우 다음을 사용하여 2 개의 인스턴트 (millies 백업 ReadableInstant) 날짜에 대한 차이를 얻을 수 있습니다.

Interval interval = new Interval(oldInstant, new Instant());

그러나 현지 날짜 / 시간에 대한 차이점을 얻을 수도 있습니다.

// returns 4 because of the leap year of 366 days
new Period(LocalDate.now(), LocalDate.now().plusDays(365*5), PeriodType.years()).getYears()

// this time it returns 5
new Period(LocalDate.now(), LocalDate.now().plusDays(365*5+1), PeriodType.years()).getYears()

// And you can also use these static methods
Years.yearsBetween(LocalDate.now(), LocalDate.now().plusDays(365*5)).getYears()


답변

int diffInDays = (int)( (newerDate.getTime() - olderDate.getTime())
                 / (1000 * 60 * 60 * 24) )

이것은 UTC 날짜와 함께 작동하므로 현지 날짜를 보면 차이가 날 수 있습니다. 현지 날짜와 올바르게 작동하려면 일광 절약 시간으로 인해 완전히 다른 방법이 필요합니다.


답변

Java 8 이상에 내장 된 java.time 프레임 워크 사용 :

ZonedDateTime now = ZonedDateTime.now();
ZonedDateTime oldDate = now.minusDays(1).minusMinutes(10);
Duration duration = Duration.between(oldDate, now);
System.out.println("ISO-8601: " + duration);
System.out.println("Minutes: " + duration.toMinutes());

산출:

ISO-8601 : PT24H10M

분 : 1450

자세한 내용은 Oracle TutorialISO 8601 표준을 참조하십시오 .


답변

문제를보다 명확하게 정의해야합니다. 당신은 할 수 단지 둘 사이의 밀리 초 단위로 가지고 Date예를 들어, 24 시간을 밀리 초 단위로 개체와 나누기 :하지만 …

  • 시간대를 고려하지 않습니다- Date항상 UTC
  • 일광 절약 시간을 고려하지 않습니다 (예를 들어 23 시간 밖에 걸리지 않는 날이있을 수 있음)
  • UTC 내에서도 8 월 16 일 오후 11 시부 터 8 월 18 일 오전 2 시까 지 며칠이 있습니까? 27 시간 밖에 안 남았나요? 아니면 3 개의 날짜를 다루므로 3 일이되어야합니까?

답변

tl; dr

사용하지 않는 java.util.Date개체를 대체물로 변환하십시오 java.time.Instant. 그런 다음 경과 시간을로 계산하십시오 Duration.

Duration d =
    Duration.between(                   // Calculate the span of time between two moments as a number of hours, minutes, and seconds.
        myJavaUtilDate.toInstant() ,    // Convert legacy class to modern class by calling new method added to the old class.
        Instant.now()                   // Capture the current moment in UTC. About two and a half hours later in this example.
    )
;

d.toString () : PT2H34M56S

d.toMinutes () : 154

d.toMinutesPart () : 34

ISO 8601 형식 : PnYnMnDTnHnMnS

합리적인 표준 ISO 8601 은 시간 범위의 간결한 텍스트 표현을 몇 년, 월, 일, 시간 등으로 정의합니다. 표준은 그러한 기간을 기간 이라고 부릅니다 . 형식은 PnYnMnDTnHnMnS를 Where P수단 “기간”은이 T시간 부분의 일 부분을 분리하고, 다음에 문자 숫자 사이.

예 :

  • P3Y6M4DT12H30M5S
    3 년, 6 개월, 4 일, 12 시간, 30 분 및 5 초
  • PT4H30M
    4 시간 반

java.time

Java 8 이상에 내장 된 java.time 프레임 워크는 번거로운 이전 java.util.Date/ java.util.Calendar클래스를 대체합니다 . 새로운 클래스는 개념적으로 유사하지만 재구성 된 후계자로 의도 된 매우 성공적인 Joda-Time 프레임 워크에서 영감을 얻었습니다 . JSR 310에 의해 정의됩니다 . ThreeTen-Extra 프로젝트로 확장되었습니다 . 학습서를 참조하십시오 .

순간

Instant클래스는 나노초 의 해상도 (소수점의 최대 9 자리)로 UTC 의 타임 라인에서 순간을 나타냅니다 .

Instant instant = Instant.now() ;  // Capture current moment in UTC.

Date/ 와 같은 레거시 클래스를 피하는 것이 가장 Calendar좋습니다. 그러나 아직 java.time으로 업데이트되지 않은 이전 코드와 상호 운용해야하는 경우 앞뒤로 변환하십시오. 이전 클래스에 추가 된 새 변환 메소드를 호출하십시오. 에서로 이동 java.util.Date하려면을 (를 Instant) 호출하십시오 Date::toInstant.

Instant instant = myJavaUtilDate.toInstant() ;  // Convert from legacy `java.util.Date` class to modern `java.time.Instant` class.

시간의 경간

java.time 클래스는 시간 범위를 몇 년, 월, 일, 시간, 분, 초로 나타내는이 아이디어를 두 개의 반으로 나눕니다.

  • Period 몇 년, 몇 달, 며칠 동안
  • Duration 일, 시간, 분, 초 동안

다음은 예입니다.

ZoneId zoneId = ZoneId.of ( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now ( zoneId );
ZonedDateTime future = now.plusMinutes ( 63 );
Duration duration = Duration.between ( now , future );

콘솔로 덤프하십시오.

모두 PeriodDuration사용 ISO 8601 의 가치의 String 표현을 생성하기위한 표준.

System.out.println ( "now: " + now + " to future: " + now + " = " + duration );

지금 : 2015-11-26T00 : 46 : 48.016-05 : 00 [미국 / 몬트리올]에서 미래로 : 2015-11-26T00 : 46 : 48.016-05 : 00 [미국 / 몬트리올] = PT1H3M

Java 9는 Duration일 부분, 시간 부분, 분 부분 및 초 부분을 가져 오는 메소드를 추가합니다 .

전체 지속 시간에서 총 일 수, 시간 또는 분 또는 초 또는 밀리 초 또는 나노초를 얻을 수 있습니다.

long totalHours = duration.toHours();

Java 9에서 Duration클래스는 일,시, 분, 초, 밀리 초 / 나노초의 다양한 부분을 반환 하기 위한 새로운 메소드얻습니다 . , 등 의 to…Part메소드를 호출하십시오 .toDaysPart()toHoursPart()

ChronoUnit

“일수”와 같이 더 간단한 시간 단위 만 신경 쓰는 경우 ChronoUnit열거 형을 사용하십시오 .

long daysElapsed = ChronoUnit.DAYS.between( earlier , later );

또 다른 예.

Instant now = Instant.now();
Instant later = now.plus( Duration.ofHours( 2 ) );

long minutesElapsed = ChronoUnit.MINUTES.between( now , later );

120


java.time에 대하여

java.time의 프레임 워크는 나중에 자바 8에 내장되어 있습니다. 이 클래스는 까다로운 기존에 대신 기존 과 같은 날짜 – 시간의 수업을 java.util.Date, Calendar, SimpleDateFormat.

Joda 타임 프로젝트는 현재의 유지 관리 모드 , java.time로 마이그레이션을 조언한다.

자세한 내용은 Oracle Tutorial을 참조하십시오 . 많은 예제와 설명을 보려면 스택 오버플로를 검색하십시오. 사양은 JSR 310 입니다.

java.time 클래스는 어디서 구할 수 있습니까?

ThreeTen – 추가 프로젝트 추가 클래스와 java.time를 확장합니다. 이 프로젝트는 향후 java.time에 추가 될 수있는 입증 된 근거입니다. 당신은 여기에 몇 가지 유용한 클래스와 같은 찾을 수 있습니다 Interval, YearWeek, YearQuarter, 그리고 .


조다 타임

업데이트 : Joda-Time 프로젝트는 이제 유지 관리 모드 에 있으며 팀은 java.time 으로의 마이그레이션을 조언합니다. 클래스 . 나는 역사를 위해이 섹션을 그대로 둡니다.

Joda-Time 라이브러리는 기본값으로 ISO 8601을 사용합니다. 이 Period클래스는 이러한 PnYnMnDTnHnMnS 문자열을 구문 분석하고 생성합니다.

DateTime now = DateTime.now(); // Caveat: Ignoring the important issue of time zones.
Period period = new Period( now, now.plusHours( 4 ).plusMinutes( 30));
System.out.println( "period: " + period );

렌더 :

period: PT4H30M


답변

Days d = Days.daysBetween(startDate, endDate);
int days = d.getDays();

https://www.joda.org/joda-time/faq.html#datediff