Joda-Time에서 두 날짜 사이의 일 수


335

Joda-Time DateTime 인스턴스의 일 차이를 어떻게 알 수 있습니까? '일의 차이'를 사용하면 시작이 월요일이고 종료가 화요일이면 시작 및 종료 날짜의 시간 / 분 / 초에 관계없이 반환 값 1을 기대합니다.

Days.daysBetween(start, end).getDays() 시작이 저녁에 있고 아침에 끝나는 경우 0을 제공합니다.

나는 다른 날짜 필드와 같은 문제를 겪고 있기 때문에 덜 중요한 필드를 '무시'하는 일반적인 방법이 있기를 바랐습니다.

다시 말해, 2 월과 3 월 4 일 사이의 월도 1 일 것이고 14:45와 15:12 사이의 시간도 마찬가지입니다. 그러나 14:01과 14:55의 시간 차이는 0입니다.

답변:


393

짜증나게, withTimeAtStartOfDay 답변은 틀리지 만 가끔 만 있습니다. 당신이 원하는 :

Days.daysBetween(start.toLocalDate(), end.toLocalDate()).getDays()

"자정 / 일 시작"은 때때로 오전 1시 (일부 지역에서는 일광 절약 시간제)를 의미하며 Days.daysBetween이 제대로 처리되지 않는 것으로 나타났습니다.

// 5am on the 20th to 1pm on the 21st, October 2013, Brazil
DateTimeZone BRAZIL = DateTimeZone.forID("America/Sao_Paulo");
DateTime start = new DateTime(2013, 10, 20, 5, 0, 0, BRAZIL);
DateTime end = new DateTime(2013, 10, 21, 13, 0, 0, BRAZIL);
System.out.println(daysBetween(start.withTimeAtStartOfDay(),
                               end.withTimeAtStartOfDay()).getDays());
// prints 0
System.out.println(daysBetween(start.toLocalDate(),
                               end.toLocalDate()).getDays());
// prints 1

LocalDate전체 단계를 회피하는 것입니다.


Days.daysBetween부정확 하다고 생각되는 특정 데이터를 사용하여 사례를 제공 할 수 있습니까 ?
Basil Bourque

Instant당신이 사용한다고 말할 때 , 당신은 단지 이야기하는 것이 아닙니다 start.toInstant().
Patrick M

@PatrickM 네, 그렇습니다. 성찰 할 때, 이것이 어떤 제약을 부과 할 것인지는 확실하지 않으므로 마지막 문장을 제거하겠습니다. 감사!
Alice Purcell

@ chrispy daysBetween 문서에 따르면 전체 WHOLE 일 수가 반환 됩니다. 내 경우에는 2 일 1 시간이 3 일 반품해야합니다. 귀하의 예에서는 2 일을 반환합니다. 이것을 달성 할 수있는 방법이 있습니까?
Sujit Joshi 2016

@SujitJoshi 나는 당신의 질문을 이해하지 못합니다. 나는 전체 스택 오버플로 질문을 게시하고 나를 위해 여기에 링크를 붙여 넣는 것이 좋습니다 :)
Alice Purcell

186

Days 수업

메소드 Days와 함께 클래스를 사용하면 withTimeAtStartOfDay작동합니다.

Days.daysBetween(start.withTimeAtStartOfDay() , end.withTimeAtStartOfDay() ).getDays() 

1
감사! joda를 사용하여 android.text.format.DateUtils.getRelativeTimeSpanString ()의 동작을 달성하려고 시도했으며 실제로 유용했습니다.
gosho_ot_pochivka 2016 년

1
게시물 을 참조하여 toDateMidnight()DateTime 유형 의 메소드 는 더 이상 사용되지 않습니다.
Aniket Kulkarni

2
이제 .withTimeAtStartOfDay () 대신 .toDateMidnight ()를 사용한다
bgolson

2
end가 앞에있는 경우 start음수 일을 반환합니까?
akhy

7
@akhyar : 시도해 보지 않겠습니까?
Michael Borgwardt

86

당신은 사용할 수 있습니다 LocalDate:

Days.daysBetween(new LocalDate(start), new LocalDate(end)).getDays() 

게시물 을 참조하여 toDateMidnight()DateTime 유형 의 메소드 는 더 이상 사용되지 않습니다.
Aniket Kulkarni

new LocalDate(date)이상 사용 date.toLocalDate()?
SARose

9

tl; dr

java.time.temporal.ChronoUnit.DAYS.between( 
    earlier.toLocalDate(), 
    later.toLocalDate() 
)

…또는…

java.time.temporal.ChronoUnit.HOURS.between( 
    earlier.truncatedTo( ChronoUnit.HOURS )  , 
    later.truncatedTo( ChronoUnit.HOURS ) 
)

java.time

참고로 Joda-Time 프로젝트는 이제 유지 관리 모드 에 있으며 팀은 java.time 클래스 로의 마이그레이션을 조언합니다 .

Joda 타임의 상당 DateTime하다 ZonedDateTime.

ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime now = ZonedDateTime.now( z ) ;

분명히 날짜로 날짜를 계산하려고합니다. 즉, 시간을 무시하고 싶습니다. 예를 들어 자정 전 1 분을 시작하고 자정 후 1 분을 끝내면 하루가됩니다. 이 동작을하려면에서을 추출 LocalDate하십시오 ZonedDateTime. 이 LocalDate클래스는 시간이없고 시간대가없는 날짜 전용 값을 나타냅니다.

LocalDate localDateStart = zdtStart.toLocalDate() ;
LocalDate localDateStop = zdtStop.toLocalDate() ;

ChronoUnit열거 형을 사용하여 경과 일수 또는 다른 단위를 계산 하십시오 .

long days = ChronoUnit.DAYS.between( localDateStart , localDateStop ) ;

자르기

60 분의 시간 범위로서 완전한 시간이 아니라 시간의 시간에 따른 시간의 델타에 관심이있는 경우이 계산을 수행하는보다 일반적인 방법에 대해 문의하려면이 truncatedTo방법을 사용하십시오 .

다음은 같은 날 14:45 ~ 15:12의 예입니다.

ZoneId z = ZoneId.of( "America/Montreal" ); 
ZonedDateTime start = ZonedDateTime.of( 2017 , 1 , 17 , 14 , 45 , 0 , 0 , z );
ZonedDateTime stop = ZonedDateTime.of( 2017 , 1 , 17 , 15 , 12 , 0 , 0 , z );

long hours = ChronoUnit.HOURS.between( start.truncatedTo( ChronoUnit.HOURS ) , stop.truncatedTo( ChronoUnit.HOURS ) );

1

며칠 동안 작동하지 않습니다. 이 경우 toLocalDate ()를 사용하십시오.


java.time에 대하여

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

Joda 타임 프로젝트는 지금에 유지 관리 모드 의로 마이그레이션을 조언 java.time의 클래스.

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

java.time 객체를 데이터베이스와 직접 교환 할 수 있습니다 . JDBC 4.2 이상을 준수 하는 JDBC 드라이버를 사용하십시오 . 문자열이 필요없고 수업이 필요 없습니다 .java.sql.*

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

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

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


자르기를 사용하는 며칠 동안 TL; DR은 허용 된 답변에 설명 된 버그, 즉 시작 시간이 오전 1시에있을 때 하나씩 벗어납니다. toLocalDate를 사용하여 추가 답변을 사용하도록 업데이트했습니다.
Alice Purcell

2

허용 된 답변은 두 개의 LocalDate객체를 작성하며 많은 데이터를 읽는 경우 상당히 비쌉니다. 나는 이것을 사용한다 :

  public static int getDaysBetween(DateTime earlier, DateTime later)
  {
    return (int) TimeUnit.MILLISECONDS.toDays(later.getMillis()- earlier.getMillis());
  }

호출 getMillis()하면 이미 존재하는 변수를 사용합니다.
MILLISECONDS.toDays()그런 다음 간단한 산술 계산을 사용하고 객체를 만들지 않습니다.


1
이 답변은 시간대와 날짜를 고려하지 않고 '일'에 대한 정의가 정확히 24 시간 인 경우에만 작동합니다. 그렇다면이 방법을 사용하십시오. 그렇지 않은 경우 시간대를 해결하는 다른 답변을 살펴보십시오.
Basil Bourque 2016 년

@BasilBourque, 당신은 옳습니다. 아직도, 나는 산술 계산을 기반으로 솔루션을 찾는 대신 각 메소드 호출에 대해 고가의 객체를 만들 것입니다. 웹 페이지에서 입력을 읽는다면 그러한 계산을 위해 많은 맛이 있습니다.
괜찮을지 모르지만

1
루프가 뜨거울 경우 Java는 객체 할당을 최적화합니다. docs.oracle.com/javase/7/docs/technotes/guides/vm/…
Alice Purcell

1

java.time.Period

java.time.Period수업을 사용하여 계산 하십시오 .

Java 8을 사용하면 차이를 계산하는 것이 더 직관적 LocalDate이므로 LocalDateTime두 날짜를 나타냅니다.

    LocalDate now = LocalDate.now();
    LocalDate inputDate = LocalDate.of(2018, 11, 28);

    Period period = Period.between( inputDate, now);
    int diff = period.getDays();
    System.out.println("diff = " + diff);

0
DateTime  dt  = new DateTime(laterDate);        

DateTime newDate = dt.minus( new  DateTime ( previousDate ).getMillis());

System.out.println("No of days : " + newDate.getDayOfYear() - 1 );    

-11
public static int getDifferenceIndays(long timestamp1, long timestamp2) {
    final int SECONDS = 60;
    final int MINUTES = 60;
    final int HOURS = 24;
    final int MILLIES = 1000;
    long temp;
    if (timestamp1 < timestamp2) {
        temp = timestamp1;
        timestamp1 = timestamp2;
        timestamp2 = temp;
    }
    Calendar startDate = Calendar.getInstance(TimeZone.getDefault());
    Calendar endDate = Calendar.getInstance(TimeZone.getDefault());
    endDate.setTimeInMillis(timestamp1);
    startDate.setTimeInMillis(timestamp2);
    if ((timestamp1 - timestamp2) < 1 * HOURS * MINUTES * SECONDS * MILLIES) {
        int day1 = endDate.get(Calendar.DAY_OF_MONTH);
        int day2 = startDate.get(Calendar.DAY_OF_MONTH);
        if (day1 == day2) {
            return 0;
        } else {
            return 1;
        }
    }
    int diffDays = 0;
    startDate.add(Calendar.DAY_OF_MONTH, diffDays);
    while (startDate.before(endDate)) {
        startDate.add(Calendar.DAY_OF_MONTH, 1);
        diffDays++;
    }
    return diffDays;
}

1
문제는 구체적으로 joda-time을 찾고 있습니다.
kapad
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.