How to get number of days between two calendar instance?

60,196

Solution 1

In Java 8 and later, we could simply use the java.time classes.

hoursBetween = ChronoUnit.HOURS.between(calendarObj.toInstant(), calendarObj.toInstant());

daysBetween = ChronoUnit.DAYS.between(calendarObj.toInstant(), calendarObj.toInstant());

Solution 2

Try the following approach:

public static long daysBetween(Calendar startDate, Calendar endDate) {
    long end = endDate.getTimeInMillis();
    long start = startDate.getTimeInMillis();
    return TimeUnit.MILLISECONDS.toDays(Math.abs(end - start));
}

Solution 3

This function computes the number of days between two Calendars as the number of calendar days of the month that are between them, which is what the OP wanted. The calculation is performed by counting how many multiples of 86,400,000 milliseconds are between the calendars after both have been set to midnight of their respective days.

For example, my function will compute 1 day's difference between a Calendar on January 1, 11:59PM and January 2, 12:01AM.

import java.util.concurrent.TimeUnit;

/**
 * Compute the number of calendar days between two Calendar objects. 
 * The desired value is the number of days of the month between the
 * two Calendars, not the number of milliseconds' worth of days.
 * @param startCal The earlier calendar
 * @param endCal The later calendar
 * @return the number of calendar days of the month between startCal and endCal
 */
public static long calendarDaysBetween(Calendar startCal, Calendar endCal) {

    // Create copies so we don't update the original calendars.

    Calendar start = Calendar.getInstance();
    start.setTimeZone(startCal.getTimeZone());
    start.setTimeInMillis(startCal.getTimeInMillis());

    Calendar end = Calendar.getInstance();
    end.setTimeZone(endCal.getTimeZone());
    end.setTimeInMillis(endCal.getTimeInMillis());

    // Set the copies to be at midnight, but keep the day information.

    start.set(Calendar.HOUR_OF_DAY, 0);
    start.set(Calendar.MINUTE, 0);
    start.set(Calendar.SECOND, 0);
    start.set(Calendar.MILLISECOND, 0);

    end.set(Calendar.HOUR_OF_DAY, 0);
    end.set(Calendar.MINUTE, 0);
    end.set(Calendar.SECOND, 0);
    end.set(Calendar.MILLISECOND, 0);

    // At this point, each calendar is set to midnight on 
    // their respective days. Now use TimeUnit.MILLISECONDS to
    // compute the number of full days between the two of them.

    return TimeUnit.MILLISECONDS.toDays(
            Math.abs(end.getTimeInMillis() - start.getTimeInMillis()));
}

Solution 4

Extension to @JK1 great answer :

public static long daysBetween(Calendar startDate, Calendar endDate) {

    //Make sure we don't change the parameter passed
    Calendar newStart = Calendar.getInstance();
    newStart.setTimeInMillis(startDate.getTimeInMillis());
    newStart.set(Calendar.HOUR_OF_DAY, 0);
    newStart.set(Calendar.MINUTE, 0);
    newStart.set(Calendar.SECOND, 0);
    newStart.set(Calendar.MILLISECOND, 0);

    Calendar newEnd = Calendar.getInstance();
    newEnd.setTimeInMillis(endDate.getTimeInMillis());
    newEnd.set(Calendar.HOUR_OF_DAY, 0);
    newEnd.set(Calendar.MINUTE, 0);
    newEnd.set(Calendar.SECOND, 0);
    newEnd.set(Calendar.MILLISECOND, 0);

    long end = newEnd.getTimeInMillis();
    long start = newStart.getTimeInMillis();
    return TimeUnit.MILLISECONDS.toDays(Math.abs(end - start));
}

Solution 5

UPDATE The Joda-Time project, now in maintenance mode, advises migration to the java.time classes. See the Answer by Anees A for the calculation of elapsed hours, and see my new Answer for using java.time to calculate elapsed days with respect for the calendar.

Joda-Time

The old java.util.Date/.Calendar classes are notoriously troublesome and should be avoided.

Instead use the Joda-Time library. Unless you have Java 8 technology in which case use its successor, the built-in java.time framework (not in Android as of 2015).

Since you only care about "days" defined as dates (not 24-hour periods), let's focus on dates. Joda-Time offers the class LocalDate to represent a date-only value without time-of-day nor time zone.

While lacking a time zone, note that time zone is crucial in determining a date such as "today". A new day dawns earlier to the east than to the west. So the date is not the same around the world at one moment, the date depends on your time zone.

DateTimeZone zone = DateTimeZone.forID ( "America/Montreal" );
LocalDate today = LocalDate.now ( zone );

Let's count the number of days until next week, which should of course be seven.

LocalDate weekLater = today.plusWeeks ( 1 );
int elapsed = Days.daysBetween ( today , weekLater ).getDays ();

The getDays on the end extracts a plain int number from the Days object returned by daysBetween.

Dump to console.

System.out.println ( "today: " + today + " to weekLater: " + weekLater + " is days: " + days );

today: 2015-12-22 to weekLater: 2015-12-29 is days: 7

You have Calendar objects. We need to convert them to Joda-Time objects. Internally the Calendar objects have a long integer tracking the number of milliseconds since the epoch of first moment of 1970 in UTC. We can extract that number, and feed it to Joda-Time. We also need to assign the desired time zone by which we intend to determine a date.

long startMillis = myStartCalendar.getTimeInMillis();
DateTime startDateTime = new DateTime( startMillis , zone );

long stopMillis = myStopCalendar.getTimeInMillis();
DateTime stopDateTime = new DateTime( stopMillis , zone );

Convert from DateTime objects to LocalDate.

LocalDate start = startDateTime.toLocalDate();
LocalDate stop = stopDateTime.toLocalDate();

Now do the same elapsed calculation we saw earlier.

int elapsed = Days.daysBetween ( start , stop ).getDays ();
Share:
60,196
Akram
Author by

Akram

An Android enthusiast.

Updated on July 09, 2022

Comments

  • Akram
    Akram almost 2 years

    I want to find the difference between two Calendar objects in number of days if there is date change like If clock ticked from 23:59-0:00 there should be a day difference.

    i wrote this

    public static int daysBetween(Calendar startDate, Calendar endDate) {  
        return Math.abs(startDate.get(Calendar.DAY_OF_MONTH)-endDate.get(Calendar.DAY_OF_MONTH));  
    } 
    

    but its not working as it only gives difference between days if there is month difference its worthless.

  • CoDe
    CoDe over 9 years
    it might increment by 1.
  • stackoverflowuser2010
    stackoverflowuser2010 almost 9 years
    This is not the correct answer for the original question. This answer is correct if a day's difference is defined to be 86,400,000 milliseconds (the number of millis in 24 hours). However, the original question asked for if there is date change like If clock ticked from 23:59-0:00 there should be a day difference. So the question defines a 1 day difference to be when the calendar day differs by 1.
  • Basil Bourque
    Basil Bourque about 7 years
    Can also be used before Java 8… Much of the java.time functionality is back-ported to a Java 6 and Java 7 in the ThreeTen-Backport project. Further adapted for Android in the ThreeTenABP project.
  • Александр Бабич
    Александр Бабич about 5 years
    How about setting hours and minutes to 0 before difference calculation
  • Basil Bourque
    Basil Bourque about 5 years
    Your days code is counting days based on UTC. The days elapsed may be a different count if considered with the time zone of the original Calendar objects. Better approach would convert using GregorianCalendar to ZonedDateTime, extract LocalDate, and calculate Period.
  • Jay
    Jay about 5 years
    I don't think this will work if one date is during daylight savings time and the other is not.
  • Basil Bourque
    Basil Bourque about 5 years
    There is nothing good about the old Calendar class. Sun, Oracle, and the JCP community all agreed in that, adopting JSR 310 years ago to supplant the terrible legacy date-time classes such as Date, Calendar, and SimpleDateFormat. Suggesting these legacy classes in 2019 is poor advice.
  • Jay
    Jay about 5 years
    @BasilBourque The question used the Calendar class so I tried to give an answer consistent with the question. Sure, it would be better to use the newer LocalDate et al. If someone asked, "What supplies should I bring when hiking the Appalachian Trail?", I wouldn't answer, "You can get where you're going much more quickly by driving a car." :-)
  • Alex Vazquez Fente
    Alex Vazquez Fente over 3 years
    Doesn't this also have the problem of counting days as "periods of 24 hours" and not as the actual calendar days?