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
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());
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));
}
I have the similar (not exact same) approach given above by https://stackoverflow.com/a/31800947/3845798.
And have written test cases around the api, for me it failed if I passed 8th march 2017 - as the start date and 8th apr 2017 as the end date.
There are few dates where you will see the difference by 1day. Therefore, I have kind of made some small changes to my api and my current api now looks something like this
public long getDays(long currentTime, long endDateTime) {
Calendar endDateCalendar;
Calendar currentDayCalendar;
//expiration day
endDateCalendar = Calendar.getInstance(TimeZone.getTimeZone("EST"));
endDateCalendar.setTimeInMillis(endDateTime);
endDateCalendar.set(Calendar.MILLISECOND, 0);
endDateCalendar.set(Calendar.MINUTE, 0);
endDateCalendar.set(Calendar.HOUR, 0);
endDateCalendar.set(Calendar.HOUR_OF_DAY, 0);
//current day
currentDayCalendar = Calendar.getInstance(TimeZone.getTimeZone("EST"));
currentDayCalendar.setTimeInMillis(currentTime);
currentDayCalendar.set(Calendar.MILLISECOND, 0);
currentDayCalendar.set(Calendar.MINUTE, 0);
currentDayCalendar.set(Calendar.HOUR,0);
currentDayCalendar.set(Calendar.HOUR_OF_DAY, 0);
long remainingDays = (long)Math.ceil((float) (endDateCalendar.getTimeInMillis() - currentDayCalendar.getTimeInMillis()) / (24 * 60 * 60 * 1000));
return remainingDays;}
I am not using TimeUnit.MILLISECONDS.toDays that were causing me some issues.
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.
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 ();
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));
}