programing

Java에서 두 날짜 사이의 일 차이?

nasanasas 2020. 10. 6. 08:16
반응형

Java에서 두 날짜 사이의 일 차이?


두 날짜 사이의 날짜 수 를 찾아야합니다 . 하나는 보고서에서 가져오고 다른 하나는 현재 날짜입니다. 내 스 니펫 :

  int age=calculateDifference(agingDate, today);

여기에 calculateDifference개인 방법이다, agingDate하고 today있는 Date당신의 명확한 설명, 객체. Java 포럼의 두 기사 인 Thread 1 / Thread 2를 따랐습니다 .

독립 실행 형 프로그램에서 잘 작동하지만 보고서에서 읽을 논리에 이것을 포함하면 값에서 비정상적인 차이가 발생합니다.

왜 발생하며 어떻게 해결할 수 있습니까?

편집하다 :

실제 일수에 비해 더 많은 일수를 얻고 있습니다.

public static int calculateDifference(Date a, Date b)
{
    int tempDifference = 0;
    int difference = 0;
    Calendar earlier = Calendar.getInstance();
    Calendar later = Calendar.getInstance();

    if (a.compareTo(b) < 0)
    {
        earlier.setTime(a);
        later.setTime(b);
    }
    else
    {
        earlier.setTime(b);
        later.setTime(a);
    }

    while (earlier.get(Calendar.YEAR) != later.get(Calendar.YEAR))
    {
        tempDifference = 365 * (later.get(Calendar.YEAR) - earlier.get(Calendar.YEAR));
        difference += tempDifference;

        earlier.add(Calendar.DAY_OF_YEAR, tempDifference);
    }

    if (earlier.get(Calendar.DAY_OF_YEAR) != later.get(Calendar.DAY_OF_YEAR))
    {
        tempDifference = later.get(Calendar.DAY_OF_YEAR) - earlier.get(Calendar.DAY_OF_YEAR);
        difference += tempDifference;

        earlier.add(Calendar.DAY_OF_YEAR, tempDifference);
    }

    return difference;
}

노트 :

안타깝게도 어떤 답변도 문제 해결에 도움이되지 않았습니다. 내가 이룬 이 문제 의 도움으로 Joda 타임 라이브러리를.


결함이있는 java.util.Date 및 친구들 대신 우수한 Joda Time 라이브러리 를 사용하는 것이 좋습니다 . 당신은 단순히 쓸 수 있습니다

import java.util.Date;
import org.joda.time.DateTime;
import org.joda.time.Days;

Date past = new Date(110, 5, 20); // June 20th, 2010
Date today = new Date(110, 6, 24); // July 24th 
int days = Days.daysBetween(new DateTime(past), new DateTime(today)).getDays(); // => 34

게임에 참여하기에는 너무 늦었을 수도 있지만 대체 뭐야? :)

이것이 스레딩 문제라고 생각하십니까? 예를 들어이 방법의 출력을 어떻게 사용하고 있습니까? 또는

다음과 같이 간단한 작업을 수행하도록 코드를 변경할 수 있습니까?

Calendar calendar1 = Calendar.getInstance();
    Calendar calendar2 = Calendar.getInstance();
    calendar1.set(<your earlier date>);
    calendar2.set(<your current date>);
    long milliseconds1 = calendar1.getTimeInMillis();
    long milliseconds2 = calendar2.getTimeInMillis();
    long diff = milliseconds2 - milliseconds1;
    long diffSeconds = diff / 1000;
    long diffMinutes = diff / (60 * 1000);
    long diffHours = diff / (60 * 60 * 1000);
    long diffDays = diff / (24 * 60 * 60 * 1000);
    System.out.println("\nThe Date Different Example");
    System.out.println("Time in milliseconds: " + diff
 + " milliseconds.");
    System.out.println("Time in seconds: " + diffSeconds
 + " seconds.");
    System.out.println("Time in minutes: " + diffMinutes 
+ " minutes.");
    System.out.println("Time in hours: " + diffHours 
+ " hours.");
    System.out.println("Time in days: " + diffDays 
+ " days.");
  }

diff / (24 * etc)는 시간대를 고려하지 않으므로 기본 시간대에 DST가있는 경우 계산이 중단 될 수 있습니다.

링크 는 멋진 작은 구현을 가지고 있습니다.

링크가 다운 된 경우 위 링크의 소스는 다음과 같습니다.

/** Using Calendar - THE CORRECT WAY**/  
public static long daysBetween(Calendar startDate, Calendar endDate) {  
  //assert: startDate must be before endDate  
  Calendar date = (Calendar) startDate.clone();  
  long daysBetween = 0;  
  while (date.before(endDate)) {  
    date.add(Calendar.DAY_OF_MONTH, 1);  
    daysBetween++;  
  }  
  return daysBetween;  
}  

/** Using Calendar - THE CORRECT (& Faster) WAY**/  
public static long daysBetween(final Calendar startDate, final Calendar endDate)
{
  //assert: startDate must be before endDate  
  int MILLIS_IN_DAY = 1000 * 60 * 60 * 24;  
  long endInstant = endDate.getTimeInMillis();  
  int presumedDays = 
    (int) ((endInstant - startDate.getTimeInMillis()) / MILLIS_IN_DAY);  
  Calendar cursor = (Calendar) startDate.clone();  
  cursor.add(Calendar.DAY_OF_YEAR, presumedDays);  
  long instant = cursor.getTimeInMillis();  
  if (instant == endInstant)  
    return presumedDays;

  final int step = instant < endInstant ? 1 : -1;  
  do {  
    cursor.add(Calendar.DAY_OF_MONTH, step);  
    presumedDays += step;  
  } while (cursor.getTimeInMillis() != endInstant);  
  return presumedDays;  
}

java.time

Java 8 이상에서는 java.time 프레임 워크 ( Tutorial )를 사용하십시오 .

Duration

Duration클래스는 시간 범위를 초 수에 분수 초를 더한 값으로 나타냅니다. 일, 시간, 분 및 초를 계산할 수 있습니다.

ZonedDateTime now = ZonedDateTime.now();
ZonedDateTime oldDate = now.minusDays(1).minusMinutes(10);
Duration duration = Duration.between(oldDate, now);
System.out.println(duration.toDays());

ChronoUnit

필요한 것이 일수뿐이라면 또는 enum을 사용할 수 있습니다 . 계산 방법 .ChronoUnit longint

long days = ChronoUnit.DAYS.between( then, now );

차이로 정의한 내용에 따라 다릅니다. 자정에 두 날짜를 비교하려면 할 수 있습니다.

long day1 = ...; // in milliseconds.
long day2 = ...; // in milliseconds.
long days = (day2 - day1) / 86400000;

import java.util.Calendar;
import java.util.Date;

public class Main {
    public static long calculateDays(String startDate, String endDate)
    {
        Date sDate = new Date(startDate);
        Date eDate = new Date(endDate);
        Calendar cal3 = Calendar.getInstance();
        cal3.setTime(sDate);
        Calendar cal4 = Calendar.getInstance();
        cal4.setTime(eDate);
        return daysBetween(cal3, cal4);
    }

    public static void main(String[] args) {
        System.out.println(calculateDays("2012/03/31", "2012/06/17"));

    }

    /** Using Calendar - THE CORRECT WAY**/
    public static long daysBetween(Calendar startDate, Calendar endDate) {
        Calendar date = (Calendar) startDate.clone();
        long daysBetween = 0;
        while (date.before(endDate)) {
            date.add(Calendar.DAY_OF_MONTH, 1);
            daysBetween++;
        }
        return daysBetween;
    }
}

DST 날짜에 대한 올바른 반올림과 함께 밀리 초 시간의 차이를 사용하는 솔루션 :

public static long daysDiff(Date from, Date to) {
    return daysDiff(from.getTime(), to.getTime());
}

public static long daysDiff(long from, long to) {
    return Math.round( (to - from) / 86400000D ); // 1000 * 60 * 60 * 24
}

한 가지 참고 : 물론 날짜는 일부 시간대 여야합니다.

중요한 코드 :

Math.round( (to - from) / 86400000D )

라운드를 원하지 않으면 UTC 날짜를 사용할 수 있습니다.


문제 설명 : (내 코드는 몇 주 내에 델타를 계산하지만 며칠 안에 델타에 동일한 문제가 적용됨)

다음은 매우 합리적으로 보이는 구현입니다.

public static final long MILLIS_PER_WEEK = 7L * 24L * 60L * 60L * 1000L;

static public int getDeltaInWeeks(Date latterDate, Date earlierDate) {
    long deltaInMillis = latterDate.getTime() - earlierDate.getTime();
    int deltaInWeeks = (int)(deltaInMillis / MILLIS_PER_WEEK);
    return deltaInWeeks; 
}

그러나이 테스트는 실패합니다.

public void testGetDeltaInWeeks() {
    delta = AggregatedData.getDeltaInWeeks(dateMar09, dateFeb23);
    assertEquals("weeks between Feb23 and Mar09", 2, delta);
}

그 이유는:

Mon Mar 09 00:00:00 EDT 2009 = 1,236,571,200,000
Mon Feb 23 00:00:00 EST 2009 = 1,235,365,200,000
MillisPerWeek = 604,800,000
따라서
(Mar09-Feb23) / MillisPerWeek =
1,206,000,000 / 604,800,000 = 1.994 ...

그러나 달력을 보는 사람은 답이 2라는 데 동의 할 것입니다.


이 기능을 사용합니다.

DATEDIFF("31/01/2016", "01/03/2016") // me return 30 days

내 기능 :

import java.util.Date;

public long DATEDIFF(String date1, String date2) {
        long MILLISECS_PER_DAY = 24 * 60 * 60 * 1000;
        long days = 0l;
        SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy"); // "dd/MM/yyyy HH:mm:ss");

        Date dateIni = null;
        Date dateFin = null;        
        try {       
            dateIni = (Date) format.parse(date1);
            dateFin = (Date) format.parse(date2);
            days = (dateFin.getTime() - dateIni.getTime())/MILLISECS_PER_DAY;                        
        } catch (Exception e) {  e.printStackTrace();  }   

        return days; 
     }

이 apache commons-lang 클래스 getFragmentInDays 메소드를 살펴보십시오 DateUtils.


@Mad_Troll의 답변을 바탕으로이 방법을 개발했습니다.

나는 그것에 대해 약 30 개의 테스트 케이스를 실행했으며, 서브 데이 타임 조각을 올바르게 처리하는 유일한 방법입니다.

예 : 지금 & 지금 + 1 밀리 초를 지나면 여전히 같은 날입니다. 수행 1-1-13 23:59:59.0981-1-13 23:59:59.099제대로 0일 반환; 여기에 게시 된 다른 방법의 할당은이를 올바르게 수행하지 않습니다.

어떤 방식으로 넣는 지 상관하지 않습니다. 종료일이 시작일 이전이면 거꾸로 계산됩니다.

/**
 * This is not quick but if only doing a few days backwards/forwards then it is very accurate.
 *
 * @param startDate from
 * @param endDate   to
 * @return day count between the two dates, this can be negative if startDate is after endDate
 */
public static long daysBetween(@NotNull final Calendar startDate, @NotNull final Calendar endDate) {

    //Forwards or backwards?
    final boolean forward = startDate.before(endDate);
    // Which direction are we going
    final int multiplier = forward ? 1 : -1;

    // The date we are going to move.
    final Calendar date = (Calendar) startDate.clone();

    // Result
    long daysBetween = 0;

    // Start at millis (then bump up until we go back a day)
    int fieldAccuracy = 4;
    int field;
    int dayBefore, dayAfter;
    while (forward && date.before(endDate) || !forward && endDate.before(date)) {
        // We start moving slowly if no change then we decrease accuracy.
        switch (fieldAccuracy) {
            case 4:
                field = Calendar.MILLISECOND;
                break;
            case 3:
                field = Calendar.SECOND;
                break;
            case 2:
                field = Calendar.MINUTE;
                break;
            case 1:
                field = Calendar.HOUR_OF_DAY;
                break;
            default:
            case 0:
                field = Calendar.DAY_OF_MONTH;
                break;
        }
        // Get the day before we move the time, Change, then get the day after.
        dayBefore = date.get(Calendar.DAY_OF_MONTH);
        date.add(field, multiplier);
        dayAfter = date.get(Calendar.DAY_OF_MONTH);

        // This shifts lining up the dates, one field at a time.
        if (dayBefore == dayAfter && date.get(field) == endDate.get(field))
            fieldAccuracy--;
        // If day has changed after moving at any accuracy level we bump the day counter.
        if (dayBefore != dayAfter) {
            daysBetween += multiplier;
        }
    }
    return daysBetween;
}

@NotNull주석을 제거 할 수 있습니다 . 이러한 주석은 Intellij에서 즉시 코드 분석을 수행하는 데 사용됩니다.


"독립 실행 형 프로그램에서 잘 작동한다"고 말하지만 "보고서에서 읽을 논리에 이것을 포함"하면 "비정상적인 차이 값"을 얻게됩니다. 이는 보고서에 올바르게 작동하지 않는 일부 값이 있고 독립 실행 형 프로그램에 해당 값이 없음을 나타냅니다. 독립형 프로그램 대신 테스트 케이스를 제안합니다. JUnit의 TestCase 클래스에서 서브 클래 싱하여 독립형 프로그램처럼 테스트 케이스를 작성하십시오. 이제 당신은 당신이 기대하는 가치를 알면서 매우 구체적인 예제를 실행할 수 있습니다 (오늘은 시간이 지남에 따라 변하기 때문에 오늘은 테스트 값으로 제공하지 마십시오). 독립형 프로그램에서 사용한 값을 입력하면 테스트가 통과 될 것입니다. 훌륭합니다. 이러한 케이스가 계속 작동하기를 원합니다. 이제 보고서에서 제대로 작동하지 않는 값을 추가하십시오. 새 테스트는 실패 할 것입니다. 실패한 이유를 파악하고 수정 한 후 녹색으로 전환합니다 (모든 테스트 통과). 보고서를 실행하십시오. 여전히 고장난 부분을 확인하십시오. 테스트를 작성하십시오. 통과하십시오. 곧 보고서가 작동한다는 것을 알게 될 것입니다.


이 기본 기능을위한 수백 줄의 코드 ???

간단한 방법 :

protected static int calculateDayDifference(Date dateAfter, Date dateBefore){
    return (int)(dateAfter.getTime()-dateBefore.getTime())/(1000 * 60 * 60 * 24); 
    // MILLIS_IN_DAY = 1000 * 60 * 60 * 24;
}

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;
}

ThreeTen-Extra

Vitalii Fedorenko답변 은 정확하며 Java 8 이상에 내장 된 java.time 클래스 ( Duration& ChronoUnit) 를 사용하여 현대적인 방식으로이 계산을 수행하는 방법을 설명합니다 (그리고 Java 6 & 7Android 로 백 포트 됨 ).

Days

코드에서 일상적으로 며칠을 사용하는 경우 단순한 정수를 클래스 사용으로 바꿀 수 있습니다. Days클래스는 java.time 의 확장 인 ThreeTen -Extra 프로젝트 에서 찾을 수 있으며 java.time에 대한 향후 추가 가능성을 입증하는 근거가됩니다. Days클래스는 애플리케이션에서 일 수를 나타내는 형식이 안전한 방법을 제공합니다. 클래스에는 ZERO및에 대한 편리한 상수가 포함되어 있습니다 ONE.

java.util.Date질문에서 오래된 오래된 개체를 고려하여 먼저 현대 java.time.Instant개체 로 변환하십시오 . 이전 날짜-시간 클래스에는 java.time으로의 변환을 용이하게하기 위해 java.util.Date::toInstant.

Instant start = utilDateStart.toInstant(); // Inclusive.
Instant stop = utilDateStop.toInstant();  // Exclusive.

Instant개체를 모두 org.threeten.extra.Days.

현재 구현 (2016-06)에서는를 호출하는 래퍼 입니다. 자세한 내용 java.time.temporal.ChronoUnit.DAYS.betweenChronoUnit클래스 문서를 참조하세요. 명확하게 말하면 DAYS, 모든 대문자 는 열거 형에 ChronoUnit있고 initial-cap Days은 ThreeTen-Extra의 클래스입니다.

Days days = Days.between( start , stop );

이러한 Days개체를 자신의 코드로 전달할 수 있습니다 . 를 호출 하여 표준 ISO 8601 형식 의 문자열로 직렬화 할 수 있습니다 toString. 이 형식 PnD은 a P사용 하여 시작을 표시하고 그 D사이에 일 수가있는 "일"을 의미합니다. java.time 클래스와 ThreeTen-Extra는 모두 날짜-시간 값을 나타내는 문자열을 생성하고 구문 분석 할 때 기본적으로 이러한 표준 형식을 사용합니다.

String output = days.toString();

P3D

Days days = Days.parse( "P3D" );  

이 코드는 두 날짜 문자열 사이의 일을 계산합니다.

    static final long MILLI_SECONDS_IN_A_DAY = 1000 * 60 * 60 * 24;
    static final String DATE_FORMAT = "dd-MM-yyyy";
    public long daysBetween(String fromDateStr, String toDateStr) throws ParseException {
    SimpleDateFormat format = new SimpleDateFormat(DATE_FORMAT);
    Date fromDate;
    Date toDate;
    fromDate = format.parse(fromDateStr);
    toDate = format.parse(toDateStr);
    return (toDate.getTime() - fromDate.getTime()) / MILLI_SECONDS_IN_A_DAY;
}

If you're looking for a solution that returns proper number or days between e.g. 11/30/2014 23:59 and 12/01/2014 00:01 here's solution using Joda Time.

private int getDayDifference(long past, long current) {
    DateTime currentDate = new DateTime(current);
    DateTime pastDate = new DateTime(past);
    return currentDate.getDayOfYear() - pastDate.getDayOfYear();
} 

This implementation will return 1 as a difference in days. Most of the solutions posted here calculate difference in milliseconds between two dates. It means that 0 would be returned because there's only 2 minutes difference between these two dates.


I've already written about it. This is a repost from Calculating the difference between two Java date instances.

public int getDiffernceInDays(long timeAfter, long timeBefore) {
    Calendar calendarAfter = Calendar.getInstance();
    calendarAfter.setTime(new Date(timeAfter));

    Calendar calendarNewAfter = Calendar.getInstance();
    calendarNewAfter.set(calendarAfter.get(Calendar.YEAR), calendarAfter.get(Calendar.MONTH), calendarAfter.get(Calendar.DAY_OF_MONTH));

    Calendar calendarBefore = Calendar.getInstance();
    calendarBefore.setTime(new Date(timeBefore));

    Calendar calendarNewBefore = Calendar.getInstance();
    calendarNewBefore.set(calendarBefore.get(Calendar.YEAR), calendarBefore.get(Calendar.MONTH), calendarBefore.get(Calendar.DAY_OF_MONTH));

    return (int) ((calendarNewAfter.getTime().getTime() - calendarNewBefore.getTime().getTime()) / (24 * 60 * 60 * 1000));
}

You should use Joda Time library because Java Util Date returns wrong values sometimes.

Joda vs Java Util Date

For example days between yesterday (dd-mm-yyyy, 12-07-2016) and first day of year in 1957 (dd-mm-yyyy, 01-01-1957):

public class Main {

public static void main(String[] args) {
    SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");

    Date date = null;
    try {
        date = format.parse("12-07-2016");
    } catch (ParseException e) {
        e.printStackTrace();
    }

    //Try with Joda - prints 21742
    System.out.println("This is correct: " + getDaysBetweenDatesWithJodaFromYear1957(date));
    //Try with Java util - prints 21741
    System.out.println("This is not correct: " + getDaysBetweenDatesWithJavaUtilFromYear1957(date));    
}


private static int getDaysBetweenDatesWithJodaFromYear1957(Date date) {
    DateTime jodaDateTime = new DateTime(date);
    DateTimeFormatter formatter = DateTimeFormat.forPattern("dd-MM-yyyy");
    DateTime y1957 = formatter.parseDateTime("01-01-1957");

    return Days.daysBetween(y1957 , jodaDateTime).getDays();
}

private static long getDaysBetweenDatesWithJavaUtilFromYear1957(Date date) {
    SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy");

    Date y1957 = null;
    try {
        y1957 = format.parse("01-01-1957");
    } catch (ParseException e) {
        e.printStackTrace();
    }

    return TimeUnit.DAYS.convert(date.getTime() - y1957.getTime(), TimeUnit.MILLISECONDS);
}

So I really advice you to use Joda Time library.


I did it this way. it's easy :)

Date d1 = jDateChooserFrom.getDate();
Date d2 = jDateChooserTo.getDate();

Calendar day1 = Calendar.getInstance();
day1.setTime(d1);

Calendar day2 = Calendar.getInstance();
day2.setTime(d2);

int from = day1.get(Calendar.DAY_OF_YEAR);
int to = day2.get(Calendar.DAY_OF_YEAR);

int difference = to-from;

참고URL : https://stackoverflow.com/questions/3299972/difference-in-days-between-two-dates-in-java

반응형