4

hi i'm asking myself if there is an easier way to get the number of days between two dates.

I want only the days, without looking at the hours or minutes.

Therefore if today is monday, and the date wich i want to compare is on wednesday, the days between are 2 (the time does not matter)

Therefore i use this code:

        Calendar c = Calendar.getInstance();
        // Only the day:
        c.set(Calendar.HOUR, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        c.set(Calendar.MILLISECOND, 0);

        Calendar to = Calendar.getInstance();
        to.setTime(date);
        to.set(Calendar.HOUR, 0);
        to.set(Calendar.MINUTE, 0);
        to.set(Calendar.SECOND, 0);
        to.set(Calendar.MILLISECOND, 0);
        date = to.getTime();

        long millsPerDay = 1000 * 60 * 60 * 24;

        long dayDiff = ( date.getTime() - dateToday.getTime() ) / millsPerDay;

after this code i have the days in a long called dayDiff. but is it really necessarily to make a calendar of the date, set the time to 00:00:00:00 and save to.getTime() in date?

Edit: After using joda-time: Is it also possible with joda-time to get information about the days, like: difference==1 ==> Tomorrow, or difference == -1 ==> yesterday or do I have to do that manually?

eav
  • 2,123
  • 7
  • 25
  • 34

5 Answers5

7

You can use the JodaTime API as shown here.

Community
  • 1
  • 1
npinti
  • 51,780
  • 5
  • 72
  • 96
7

For specified task I always use this convenient way: (no lib, just Java 5 API)

import java.util.concurrent.TimeUnit;

Date d1 = ...
Date d2 = ...

long daysBetween = TimeUnit.MILLISECONDS.toDays(d2.getTime() - d1.getTime());

Enjoy!

user and
  • 550
  • 4
  • 9
3
public long dayDiff(Date d1, Date d2) {
    final long DAY_MILLIS = 1000 * 60 * 60 * 24;
    long day1 = d1.getTime() / DAY_MILLIS;
    long day2 = d2.getTime() / DAY_MILLIS;
    return (day1 - day2);
}

Sorry for my carelessness

J.S. Taylor
  • 771
  • 4
  • 7
  • 2
    Why do you use `double` and a `float` constant? If you used `long` you wouldn't need to cast or call `floor` – Peter Lawrey Apr 27 '11 at 09:38
  • 1
    Yeah, I'd use a `long` and have it as a constant. Be careful about dividing by an inline multiplication like you had originally since it'd be interpreted as an `int`. It works fine for a day interval, however if you divided by `1000 * 60 * 60 * 24 * 30` for a month it'd overflow the `int` and you wouldn't get expected result. – WhiteFang34 Apr 27 '11 at 09:46
  • Thank you guys, I guess some day I'll win a Stupid Nobel Prize. :) fixing my code now – J.S. Taylor Apr 27 '11 at 09:51
1

Here is an analytical daydiff method not based on hazardous millisecond-conversions :

public static int dayDiff(Calendar to, Calendar from){
    int result = 0;
    int years;


    // global year difference from 1.jan to 1.jan
    years = to.get(Calendar.YEAR) - from.get(Calendar.YEAR);
    result = years * 365; 

    // adding days for simple leap years ( divisible by 4 ). This an approximation that will be corrected by the negative leap years formula.
    result += (to.get(Calendar.YEAR)-1)/4 - (from.get(Calendar.YEAR)-1)/4;

    // removing days for negative leap years ( divisible by 100 ). This is still an approximation that will be corrected by the big leap years formula.
    result -= (to.get(Calendar.YEAR)-1)/100 - (from.get(Calendar.YEAR)-1)/100;

    // adding days for big leap years ( divisible by 400 ). After this formula, the days count from 1.jan.<from> to 1.jan.<to> is correct.
    result += (to.get(Calendar.YEAR)-1)/400 - (from.get(Calendar.YEAR)-1)/400;

    // adding month of to-year
    for(int m=0; m<to.get(Calendar.MONTH ); m++){
        result += daysInMonth(m, to.get(Calendar.YEAR));
    }

    // substracting month of from-year
    for(int m=0; m<from.get(Calendar.MONTH ); m++){
        result -= daysInMonth(m, from.get(Calendar.YEAR));
    }

    // adding days of to-year
    result += to.get(Calendar.DAY_OF_MONTH ); 


    // substracting days of from-year
    result -= from.get(Calendar.DAY_OF_MONTH ); 

    return result;

}

private static int daysInMonth(int m, int y){
    if(m==3 || m==5 || m==8 || m==10) return 30;
    if(m==1)
        if(isLeapYear(y)) return 29;
        else return 28;
    return 31;
}


private static boolean isLeapYear(int y){
    return (isSimpleLeapYear(y) && !isNegativeLeapYear(y)) || isBigLeapYear(y);
}

private static boolean isSimpleLeapYear(int y){
    return y%4 == 0;
}

private static boolean isNegativeLeapYear(int y){
    return y%100 == 0;
}

private static boolean isBigLeapYear(int y){
    return y%400 == 0;
}

}

toggeli
  • 11
  • 1
  • Personally I prefer using existing date libraries over rolling my own. Dates handling has a lot of nuances that are easy to overlook. – Leigh Jun 14 '12 at 07:58
1

Instead of setting all not relavant values to 0, you can use commons lang DateUtils.truncate

Anyway, the dayDiff (start-end)/milliesPerDay will not work correct, because of Day Light Save changes.

Ralph
  • 118,862
  • 56
  • 287
  • 383