5

In java, I want to get the number of days between two dates, excluding those two dates.

For example:

If first date = 11 November 2011 and the second date = 13 November 2011 then it should be 1.

This is the code I am using but doesn't work (secondDate and firstDate are Calendar objects):

long diff=secondDate.getTimeInMillis()-firstDate.getTimeInMillis();
float day_count=(float)diff / (24 * 60 * 60 * 1000);
daysCount.setText((int)day_count+"");                    

I even tried rounding the results but that didn't help.

How do I get the number of days between dates in java excluding the days themselves?

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
Hiral Vadodaria
  • 19,158
  • 5
  • 39
  • 56
  • Did you normalize your dates before calculation? I mean you have to clear fields HOUR_OF_DAY, MINUTE, SECOND, and MILLISEC. – slkorolev Nov 02 '11 at 07:42
  • @slkorolev: Oh...I really didn't know that.Let me try again. – Hiral Vadodaria Nov 02 '11 at 07:46
  • 2
    possible duplicate of [Difference in days between two dates in Java?](http://stackoverflow.com/questions/3299972/difference-in-days-between-two-dates-in-java) – marcolopes Apr 19 '14 at 05:50
  • Modern comment: avoid using `Calendar`, `GregorianCalendar` and other date and time classes from Java 1.0 and 1.1. Use the modern `LocalDate` for a date. – Ole V.V. Dec 02 '22 at 18:50

6 Answers6

12

I've just tested on SDK 8 (Android 2.2) the following code snippet:

Calendar date1 = Calendar.getInstance();
Calendar date2 = Calendar.getInstance();

date1.clear();
date1.set(
   datePicker1.getYear(),
   datePicker1.getMonth(),
   datePicker1.getDayOfMonth());
date2.clear();
date2.set(
   datePicker2.getYear(),
   datePicker2.getMonth(),
   datePicker2.getDayOfMonth());

long diff = date2.getTimeInMillis() - date1.getTimeInMillis();

float dayCount = (float) diff / (24 * 60 * 60 * 1000);

textView.setText(Long.toString(diff) + " " + (int) dayCount);

it works perfectly and in both cases (Nov 10,2011 - Nov 8,2011) and (Nov 13,2011 - Nov 11,2011) gives dayCount = 2.0

Aubin
  • 14,617
  • 9
  • 61
  • 84
slkorolev
  • 5,883
  • 1
  • 29
  • 32
  • 2
    Two notes: 1. Don't use float to turn milliseconds into days. 2. To exclude both days from the calculation, substract 1 from `dayCount`. – Aaron Digulla Nov 02 '11 at 09:09
  • 1
    @Aaron: Thanks for the comment, I agree. I think the cause of the original problem is not within calculation but Calendar initialization. – slkorolev Nov 02 '11 at 09:19
  • What is datePicker1 there?? and how can i use my calendar objects with this code?? – Hiral Vadodaria Nov 02 '11 at 09:23
  • @Hiral: dattePicker1 and 2 are just compound components in my test app. They store year, month, and day of dates entered. Actually the main point of the snippet is to first clear all the date fields and then set only year, month, and day: ` date1.clear(); date1.set(year, month, dayOfMonth);` – slkorolev Nov 02 '11 at 09:37
  • 3
    This fails when the time zone considers Daylight Saving Time, for example "10 March 2013" against "12 March 2013" on Central Time. – Luiggi Mendoza Apr 25 '13 at 00:42
  • 1
    NO! This answer is incorrect. If `day2` is in Daylight Saving Time but `day1` is in non-daylight time, the answer will be off by one day. – Dawood ibn Kareem Jun 09 '13 at 22:03
7

Get Days between java.util.Dates, ignoring daylight savings time

Quick and dirty hack:

public int get_days_between_dates(Date date1, Date date2)
{       
    //if date2 is more in the future than date1 then the result will be negative
    //if date1 is more in the future than date2 then the result will be positive.

    return (int)((date2.getTime() - date1.getTime()) / (1000*60*60*24l));
}

This function will work 99.99% of the time, except when it surprises you later on in the edge cases during leap-seconds, daylight savings, timezone changes leap years and the like. If you are OK with the calculation being off by 1 (or 2) hours once in a while, this will suffice.

Get Days between Dates taking into account leapseconds, daylight savings, timezones, etc

If you are asking this question you need to slap yourself. What does it mean for two dates to be at least 1 day apart? It's very confusing. What if one Date is midnight in one timezone, and the other date is 1AM in another timezone? Depending on how you interpret it, the answer is both 1 and 0.

You think you can just force the dates you pass into the above function as Universal time format; that will fix some of your problems. But then you just relocate the problem into how you convert your local time to a universal time. The logical conversion from your timezone to universal time may not be what is intuitive. In some cases you will get a day difference when the dates passed in are obviously two days apart.

And you think you can deal with that? There are some simplistic calendar systems in the world which are constantly changing depending on the harvest season and installed political rulers. If you want to convert their time to UTC, java.util.Date is going to fail you at the worst moment.

If you need to calculate the days between dates and it is critical that everything come out right, you need to get an external library called Joda Time: (They have taken care of all the details for you, so you can stay blissfully unaware of them): http://joda-time.sourceforge.net/index.html

Jeff Schaller
  • 2,352
  • 5
  • 23
  • 38
Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
  • 1
    +1 for suggesting Joda Time, which ideally could have been the first sentence of your answer. Note that your "quick and dirty hack" will be out by a whole DAY, not just 1 or 2 hours, in about 25% of cases; that is those cases when `day2` occurs during daylight savings time and `day1` does not. So it will NOT "work 99.99% of the time" as you claim. – Dawood ibn Kareem Jun 09 '13 at 22:11
  • 1
    Add a Math.abs(diff) in there if you never want negatives values. – Philippe Carriere Jul 04 '13 at 19:35
  • I would also add a Math.round(diff) to make sure you don't floor the value. – Philippe Carriere Jul 04 '13 at 19:46
  • I know it's old, but, Java's Calendar class can't take care of it? – emiliopedrollo Jul 21 '15 at 20:49
2

java.time

The java.time API, released with Java-8 in March 2014, supplanted the error-prone legacy date-time API. Since then, using this modern date-time API has been strongly recommended.

Solution using modern date-time API

Using Calendar#toInstant, convert your java.util.Calendar instances into java.time.Instant and then into java.time.ZonedDateTime instances and then use ChronoUnit.DAYS.between to get the number of days between them.

Demo:

import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;

public class Main {

    public static void main(String[] args) {
        // Sample start and end dates as java.util.Date
        Calendar startCal = Calendar.getInstance();
        startCal.set(2011, 10, 11); // 11 November 2011

        Calendar endCal = Calendar.getInstance();
        endCal.set(2011, 10, 13); // 13 November 2011

        // Convert the java.util.Calendar into java.time.ZonedDateTime
        // Replace ZoneId.systemDefault() with the applicable ZoneId
        ZonedDateTime startDateTime = startCal.toInstant().atZone(ZoneId.systemDefault());
        ZonedDateTime endDateTime = endCal.toInstant().atZone(ZoneId.systemDefault());

        // The end date is excluded by default. Subtract 1 to exclude the start date
        long days = ChronoUnit.DAYS.between(startDateTime, endDateTime) - 1;
        System.out.println(days);
    }
}

Output:

1

Learn more about the modern Date-Time API from Trail: Date Time.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
0

I have two suggestions:

  1. Make sure your float day_count is calculated correctly

    float day_count = ((float)diff) / (24f * 60f * 60f * 1000f);

  2. If it's rounding error, try using floor method

    daysCount.setText("" + (int)Math.floor(day_count));

Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
Vladimir
  • 9,683
  • 6
  • 36
  • 57
0
  1. Don't use floats for integer calculations.

  2. Are you sure your dates are days? The precision of the Date type is milliseconds. So the first thing you need to do is round the date to something which doesn't have hours. Example: It's just one hour from 23:30 2011-11-01 to 00:30 2011-11-02 but the two dates are on different days.

Aaron Digulla
  • 321,842
  • 108
  • 597
  • 820
  • I set 0 to the fields HOUR_OF_DAY, MINUTE, SECOND, and MILLISEC of both the dates before calculating the days count.is it fine or anything else would cause problem? – Hiral Vadodaria Nov 02 '11 at 09:35
  • That should do the trick. If this doesn't work, you should see fractions in your `dayCount`. – Aaron Digulla Nov 02 '11 at 09:40
0

If you are only going to be dealing with dates between the years 1900 and 2100, there is a simple calculation which will give you the number of days since 1900:

public static int daysSince1900(Date date) {
    Calendar c = new GregorianCalendar();
    c.setTime(date);

    int year = c.get(Calendar.YEAR);
    if (year < 1900 || year > 2099) {
        throw new IllegalArgumentException("daysSince1900 - Date must be between 1900 and 2099");
    }
    year -= 1900;
    int month = c.get(Calendar.MONTH) + 1;
    int days = c.get(Calendar.DAY_OF_MONTH);

    if (month < 3) {
        month += 12;
        year--;
    }
    int yearDays = (int) (year * 365.25);
    int monthDays = (int) ((month + 1) * 30.61);

    return (yearDays + monthDays + days - 63);
}

Thus, to get the difference in days between two dates, you calculate their days since 1900 and calc the difference. Our daysBetween method looks like this:

public static Integer getDaysBetween(Date date1, Date date2) {
    if (date1 == null || date2 == null) {
        return null;
    }

    int days1 = daysSince1900(date1);
    int days2 = daysSince1900(date2);

    if (days1 < days2) {
        return days2 - days1;
    } else {
        return days1 - days2;
    }
}

In your case you would need to subtract an extra day (if the days are not equal).

And don't ask me where this calculation came from because we've used it since the early '90s.

DuncanKinnear
  • 4,563
  • 2
  • 34
  • 65