50

I want to compare two dates for my Android application, but I got a really weird issue.

For example:

If I set the back in the past date to 127 days ago:

this.dateEvent = System.currentTimeMillis() - (127 * 24 * 3600 * 1000)

And then compare it to the current date (Days between)

    Calendar sDate = getDatePart(new Date(this.dateEvent));
    Calendar eDate = getDatePart(new Date(System.currentTimeMillis()));

    int daysBetween = 0;
    while (sDate.before(eDate))
    {
        sDate.add(Calendar.DAY_OF_MONTH, 1);
        daysBetween ++;
    }

    while (sDate.after(eDate))
    {
        eDate.add(Calendar.DAY_OF_MONTH, 1);
        daysBetween ++;
    }

    return daysBetween;

It will return 22 which is not at all what was expected.

Did I make something wrong or is that an issue with the Calendar class ?

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
Manitoba
  • 8,522
  • 11
  • 60
  • 122
  • What does the declaration of `dateEvent` look like? – keyser Apr 27 '14 at 13:09
  • You're always adding **DAY_OF_MONTH** (so, after 31 or 30 or 28 or 29 it will **restart counting** from 1) instead of **DAY**. And, in the first case I'd add a **NEGATIVE** number (-1) – Phantômaxx Apr 27 '14 at 13:11
  • Hello, `dateEvent` is declared with `private long dateEvent = 0L;`. I've also tried to replace `DAY_OF_MONTH` by `DAY_OF_YEAR`, but that didn't solve the issue. – Manitoba Apr 27 '14 at 13:57
  • 1
    I recommend you use java.time, the modern Java date and time API, for your date work. The `Calendar` class is poorly designed and long outdated, so don’t use that. java.time is not only a lot nicer to work with, opposite `Calendar` it specifically has direct support for finding the number of days between two dates. – Ole V.V. Apr 06 '20 at 11:46
  • i gave super easy solution here https://stackoverflow.com/a/65551309/10390808 – Abhinav Chauhan Jan 04 '21 at 01:58

19 Answers19

134

Here's a two line solution:

long msDiff = Calendar.getInstance().getTimeInMillis() - testCalendar.getTimeInMillis();
long daysDiff = TimeUnit.MILLISECONDS.toDays(msDiff);

In this example it gets the number of days between date "testCalendar" and the current date.

The Berga
  • 3,744
  • 2
  • 31
  • 34
22

Please refer this code, this may help you.

public String getCountOfDays(String createdDateString, String expireDateString) {
    SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy", Locale.getDefault());

    Date createdConvertedDate = null, expireCovertedDate = null, todayWithZeroTime = null;
    try {
        createdConvertedDate = dateFormat.parse(createdDateString);
        expireCovertedDate = dateFormat.parse(expireDateString);

        Date today = new Date();

        todayWithZeroTime = dateFormat.parse(dateFormat.format(today));
    } catch (ParseException e) {
        e.printStackTrace();
    }

    int cYear = 0, cMonth = 0, cDay = 0;

    if (createdConvertedDate.after(todayWithZeroTime)) {
        Calendar cCal = Calendar.getInstance();
        cCal.setTime(createdConvertedDate);
        cYear = cCal.get(Calendar.YEAR);
        cMonth = cCal.get(Calendar.MONTH);
        cDay = cCal.get(Calendar.DAY_OF_MONTH);

    } else {
        Calendar cCal = Calendar.getInstance();
        cCal.setTime(todayWithZeroTime);
        cYear = cCal.get(Calendar.YEAR);
        cMonth = cCal.get(Calendar.MONTH);
        cDay = cCal.get(Calendar.DAY_OF_MONTH);
    }


    /*Calendar todayCal = Calendar.getInstance();
    int todayYear = todayCal.get(Calendar.YEAR);
    int today = todayCal.get(Calendar.MONTH);
    int todayDay = todayCal.get(Calendar.DAY_OF_MONTH);
    */

    Calendar eCal = Calendar.getInstance();
    eCal.setTime(expireCovertedDate);

    int eYear = eCal.get(Calendar.YEAR);
    int eMonth = eCal.get(Calendar.MONTH);
    int eDay = eCal.get(Calendar.DAY_OF_MONTH);

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

    date1.clear();
    date1.set(cYear, cMonth, cDay);
    date2.clear();
    date2.set(eYear, eMonth, eDay);

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

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

    return ("" + (int) dayCount + " Days");
}
Khalid Taha
  • 3,183
  • 5
  • 27
  • 43
Amarjit
  • 4,327
  • 2
  • 34
  • 51
9

I've finally found the easiest way to deal with that. Here is my code:

public int getTimeRemaining()
{
    Calendar sDate = toCalendar(this.dateEvent);
    Calendar eDate = toCalendar(System.currentTimeMillis());

    // Get the represented date in milliseconds
    long milis1 = sDate.getTimeInMillis();
    long milis2 = eDate.getTimeInMillis();

    // Calculate difference in milliseconds
    long diff = Math.abs(milis2 - milis1);

    return (int)(diff / (24 * 60 * 60 * 1000));
}

private Calendar toCalendar(long timestamp)
{
    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(timestamp);
    calendar.set(Calendar.HOUR_OF_DAY, 0);
    calendar.set(Calendar.MINUTE, 0);
    calendar.set(Calendar.SECOND, 0);
    calendar.set(Calendar.MILLISECOND, 0);
    return calendar;
}

Hope it helps.

hector6872
  • 1,336
  • 14
  • 18
Manitoba
  • 8,522
  • 11
  • 60
  • 122
9

You should never use formula such 24 * 60 * 60 * 1000! Why? Because there is day saving time, and not all days have 24 hours, also what about leap year, that has +1 day. That's why there is a calendar class. If you do not want to put any external library to your project like Jodatime, you could use pure Calendar class with very efficient function:

public static int numDaysBetween(final Calendar c, final long fromTime, final long toTime) {
    int result = 0;
    if (toTime <= fromTime) return result;

    c.setTimeInMillis(toTime);
    final int toYear = c.get(Calendar.YEAR);
    result += c.get(Calendar.DAY_OF_YEAR);

    c.setTimeInMillis(fromTime);
    result -= c.get(Calendar.DAY_OF_YEAR);

    while (c.get(Calendar.YEAR) < toYear) {
        result += c.getActualMaximum(Calendar.DAY_OF_YEAR);
        c.add(Calendar.YEAR, 1);
    }

    return result;
}
Oleksandr Albul
  • 1,611
  • 1
  • 23
  • 31
7
public long Daybetween(String date1,String date2,String pattern)
{
    SimpleDateFormat sdf = new SimpleDateFormat(pattern,Locale.ENGLISH);
    Date Date1 = null,Date2 = null;
    try{
        Date1 = sdf.parse(date1);
        Date2 = sdf.parse(date2);
    }catch(Exception e)
    {
        e.printStackTrace();
    }
    return (Date2.getTime() - Date1.getTime())/(24*60*60*1000);
}
indrajeet
  • 341
  • 5
  • 9
7
    Date userDob = new SimpleDateFormat("yyyy-MM-dd").parse(dob);
    Date today = new Date();
    long diff =  today.getTime() - userDob.getTime();
    int numOfYear = (int) ((diff / (1000 * 60 * 60 * 24))/365);
    int numOfDays = (int) (diff / (1000 * 60 * 60 * 24));
    int hours = (int) (diff / (1000 * 60 * 60));
    int minutes = (int) (diff / (1000 * 60));
    int seconds = (int) (diff / (1000));
Nilesh Savaliya
  • 666
  • 9
  • 9
3

I had the same need, I finally ended up using Joda Time, it is very convenient and offers lots of additional functions including the one you are looking for.

You can download the files from here.

Once you included the jar file into your project, you can easily do for example the following:

int daysBetween = Days.daysBetween(new DateTime(sDate), new DateTime(eDate)).getDays();
Yoann Hercouet
  • 17,894
  • 5
  • 58
  • 85
  • 2
    Joda time library will add 4744 methods to your project. Choose wisely if you want to avoid the 65K methods limit. – Lior Iluz Dec 22 '15 at 15:56
  • Adding jars is really unwise, just for a simple calculation. Be wary of methods limit as @LiorIluz mentioned. – sud007 Jan 13 '16 at 12:24
2

the best way :-

        long fromCalender = Calender.getInstance();
        fromCalender.set...// set the from dates
        long toCalender = Calender.getInstance();
        fromCalender.set...// set the to dates

        long diffmili = fromCalender - toCalender;

        long hours = TimeUnit.MILLISECONDS.toHours(diffmili);
        long days = TimeUnit.MILLISECONDS.toDays(diffmili);
        long min = TimeUnit.MILLISECONDS.toMinutes(diffmili);
        long sec = TimeUnit.MILLISECONDS.toSeconds(diffmili);
Akshay Paliwal
  • 3,718
  • 2
  • 39
  • 43
  • You should test your solution before posting it, there is a copy/past error and a typo in Calendar – Bogy Sep 10 '19 at 08:21
2

Do like this it supports all Api Levels

    Calendar cal = Calendar.getInstance();
    SimpleDateFormat sdf = new SimpleDateFormat("MMM dd yyyy HH:mm:ss", 
    Locale.ENGLISH);
    try {
        String datestart="June 14 2018 16:02:37";
        cal.setTime(sdf.parse(datestart));// all done
         Calendar cal1=Calendar.getInstance();
        String formatted = sdf.format(cal1.getTime());//formatted date as i want
        cal1.setTime(sdf.parse(formatted));// all done

        long msDiff = cal1.getTimeInMillis() - cal.getTimeInMillis();
        long daysDiff = TimeUnit.MILLISECONDS.toDays(msDiff);
        Toast.makeText(this, "days="+daysDiff, Toast.LENGTH_SHORT).show();
    } catch (ParseException e) {
        e.printStackTrace();
    }
Syed Danish Haider
  • 1,334
  • 11
  • 15
2
fun TimeZone.daysBetween(from: Date, to: Date): Int {
    val offset = rawOffset + dstSavings
    return ((to.time + offset) / 86400000).toInt() - ((from.time + offset) / 86400000).toInt()
}

Have a try:

    val f = SimpleDateFormat("yyyy-MM-dd HH:mm:ss").apply {
        timeZone = TimeZone.getTimeZone("GMT")
    }
    val df = f.parse("2019-02-28 22:59:59")
    val dt = f.parse("2019-02-28 23:00:00")

    TimeZone.getTimeZone("GMT").daysBetween(df, dt)  // 0
    TimeZone.getTimeZone("GMT+1").daysBetween(df, dt) // 1
2

java.time and ThreeTenABP

I should like to contribute the modern answer: Use java.time, the modern Java date and time API for your date work. If developing for Android API level 25 or lower, then through the backport for Android, ThreeTenABP (link at the bottom).

    LocalDate eDate = LocalDate.now(ZoneId.of("Europe/Paris"));
    LocalDate sDate = eDate.minusDays(127);

    long daysBetween = ChronoUnit.DAYS.between(sDate, eDate);
    System.out.println(daysBetween);

When I ran this code today, the output was the expected:

127

Notice that the code is not only shorter, just one line for finding the difference; it is also clearer and more natural to read. The classes Date and Calendar that you used are poorly designed and long outdated. I recommend you don’t use them.

What went wrong in your code?

You’ve got an int overflow in your conversion of 127 days to milliseconds. In mathematics 127 * 24 * 3600 * 1000 equals 10 972 800 000. Since the numbers you multiply are ints, Java performs the multiplication in int, and the largest number an int can hold is 2 147 483 647, far from enough for your expected result. In this situation it would have been nice if Java would have thrown an exception or in some other way have made us aware of the error. It doesn’t. It tacitly throws away the high order bits, giving us a result of -1 912 101 888. Subtracting this negative number from the current time is equivalent to adding 22 days and a few hours. This explains why you got 22. Funny that 13 answers have been posted and it seems that no one has spotted this …

Even when doing the multiplication using the long type, it still doesn’t calculate 127 days correctly, though. If the 127 days cross a transition to or from summer time (DST), which in France is the case during 254 of the 365 days of a year, the day of the transition is not 24 hours, but either 23 or 25. Which causes an incorrect number of milliseconds.

You should always leave date math to proven library methods. Never hand code it yourself. It’s more complicated than most of us think, so the risk of doing it incorrectly is high.

Question: Doesn’t java.time require Android API level 26?

java.time works nicely on both older and newer Android devices. It just requires at least Java 6.

  • In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in.
  • In non-Android Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
  • On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.

Links

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • 1
    Update, java.time is now available native for API <26 without ThreeTehnABP. You just need to use Android 4.0 and add in some simple config: developer.android.com/studio/preview/features#j8-desugar – 7200rpm Apr 22 '20 at 03:21
1

The best solution that worked for me is :

private static int findDaysDiff(long unixStartTime,long unixEndTime)
    {
        Calendar calendar1 = Calendar.getInstance();
        calendar1.setTimeInMillis(unixStartTime);
        calendar1.set(Calendar.HOUR_OF_DAY, 0);
        calendar1.set(Calendar.MINUTE, 0);
        calendar1.set(Calendar.SECOND, 0);
        calendar1.set(Calendar.MILLISECOND, 0);

        Calendar calendar2 = Calendar.getInstance();
        calendar2.setTimeInMillis(unixEndTime);
        calendar2.set(Calendar.HOUR_OF_DAY, 0);
        calendar2.set(Calendar.MINUTE, 0);
        calendar2.set(Calendar.SECOND, 0);
        calendar2.set(Calendar.MILLISECOND, 0);

        return (int) ((calendar2.getTimeInMillis()-calendar1.getTimeInMillis())/(24 * 60 * 60 * 1000));

    }

Since it first converts Hour , Minute, Second and Millisecond to 0 and now the difference will be only in days.

Pradeep Kumar Kushwaha
  • 2,231
  • 3
  • 23
  • 34
1

the answer is not correct in some dates like "2019/02/18" , "2019/02/19" but i edit and resolve bug

this is best method :

 public int getCountOfDays(String createdDateString, String expireDateString) {

        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");

        Date createdConvertedDate = null;
        Date expireCovertedDate = null;
        try {
            createdConvertedDate = dateFormat.parse(createdDateString);
            expireCovertedDate = dateFormat.parse(expireDateString);
        } catch (ParseException e) {
            e.printStackTrace();
        }


        Calendar start = new GregorianCalendar();
        start.setTime(createdConvertedDate);

        Calendar end = new GregorianCalendar();
        end.setTime(expireCovertedDate);

        long diff = end.getTimeInMillis() - start.getTimeInMillis();

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


        return (int) (dayCount);
    }

Enjoy and if was helpefull +vote to this answer ;)

Erfan
  • 3,059
  • 3
  • 22
  • 49
1

Kotlin Extension:

fun Date?.getDaysBetween(dest: Date?): Int {

    if(this == null || dest == null) return 0

    val diff = abs(this.time - dest.time)
    val dayCount = diff.toFloat() / (24 * 60 * 60 * 1000)
    return dayCount.toInt()
}
Amir Hossein Ghasemi
  • 20,623
  • 10
  • 57
  • 53
0

I am count the days between last submission date and current date if it is less than zero then student cannot give submission. I am working with kotlin. The below code helps you.

 var calendar=Calendar.getInstance().time
 var dateFormat= SimpleDateFormat("dd/M/yyyy")
 var d2=dateFormat.parse(data.get("date").toString())
 var cd=dateFormat.format(calendar)
 var d1=dateFormat.parse(cd)
 var diff=d2.time-d1.time
 var ddd= TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS)
0

This is the Java 8 java.time version which works perfectly for me. You might want to make sure that startDate and endDate are set to the same time, otherwise days might vary by +-1! These are the Kotlin versions I just copy/pasted.

private fun getDawnOfDay(instant: Instant): Temporal =
        LocalDate.from(instant.atZone(ZoneOffset.UTC)).atStartOfDay()

fun getNumberOfDaysInBetween(startDate: Date, endDate: Date) =
        Duration.between(getDawnOfDay(startDate.toInstant()), getDawnOfDay(endDate.toInstant()))
            .toDays()
postfixNotation
  • 181
  • 1
  • 5
  • Using java.time is a good idea (as I also recommend in my answer). Your way of doing it won’t always be accurate, though. `Duration` assumes that a day is always 24 hours. A day is not always 24 hours. The typical counter-example is the spring forward, where a day is only 23 hours. If your interval is across this spring forward, you will be counting one day too few even when `startDate` and `endDate` have the same time of day. – Ole V.V. Jun 17 '20 at 16:28
  • Hi and thanks a lot for your helpful comment! I just edited my answer, setting both values to a UTC-zoned value. Do you think this might solve the issue, I mean setting both to UTC to simply get the correct number of days in between? Thx! – postfixNotation Jun 19 '20 at 05:53
  • Sorry, it’s not OK . I have set my time zone to Europe/Berlin. I have two `Date`  objects, Sun Mar 29 01:30:00 CET 2020 and Mon Mar 30 01:30:00 CEST 2020. You see that the time of day is the same. Expected number of days between: 1. Days between according to your method: 0. – Ole V.V. Jun 19 '20 at 14:19
  • You may use `ChronoUnit.DAYS.between(startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate(), endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate())`. Feel free to publish in your answer, and I will upvote. You may of course wrap the conversion from `Date` to `LocalDate` into an auxiliary method in the same manner as you already do. – Ole V.V. Jun 19 '20 at 14:28
  • Thanks for your helpful comments! I tried the following: `val zoneId = ZoneId.systemDefault()`, `val date1 = LocalDateTime.of(2020, Month.MARCH, 29, 1, 30, 0, 0)`, `val date2 = LocalDateTime.of(2020, Month.MARCH, 30, 1, 30, 0, 0)`, `val zonedDate1 = ZonedDateTime.of(date1, zoneId)`, `val zonedDate2 = ZonedDateTime.of(date2, zoneId)` which leas to 0 days in between since I'm in Berlin: `Duration.between(zonedDate1, zonedDate2).toDays()` – postfixNotation Jun 22 '20 at 09:53
  • But if I do the same with `ZoneId.of("UTC")` as zoneId I get the correct result of 1 day. In the above method of my answer the `instant.atZone(ZoneOffset.UTC)` is actually meant as a constant (always UTC). So I was not intending to have this as a variable. – postfixNotation Jun 22 '20 at 09:55
  • 1
    As far as I know a `Date` object doesn't store the time zone at all, it's basically a point in time, completely time zone agnostic. I might be wrong, or I simply don't understand the issue you are describing. – postfixNotation Jun 22 '20 at 09:58
  • 1
    You are correct, a `Date` is a point in time independent of time zone. – Ole V.V. Jun 22 '20 at 11:18
0

I have just modified a little bit most popular answer. Here is my solution: daysBetween() - Return days count between two dates.

public static long daysBetween(Date date1, Date date2) {
        long msDiff = resetTimeToDateStart(date1).getTime() - resetTimeToDateStart(date2).getTime();
        return TimeUnit.MILLISECONDS.toDays(msDiff);
    }
private static Date resetTimeToDateStart(Date dDate){
        if (Utils.isNull(dDate)){
            return null;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(dDate);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }
Vitaly
  • 334
  • 4
  • 14
  • 1
    I am probably repeating myself. (1) the classes `Calendar` and `Date` are poorly designed and long outdated, I recommend that you don’t use them. (2) Your calculation assumes there are always 24 hours in a day. A day can be occasionally shorter, e.g., 23 hours, so your code will count 1 day too few sometimes. – Ole V.V. Dec 18 '20 at 19:49
0
int difference in days=(present_year - oldyear) * 365 + (present_month - oldmonth)*30 + (present_date-olddate);
Gabriele Mariotti
  • 320,139
  • 94
  • 887
  • 841
0

All above answers calculating millis_diff / (24 * 60 * 60 * 1000) is simply wrong if you consider 23:59:59 ~ 00:00:00 as two different days and expect offset day count as 1, instead of 0.

A kotlin version gives you count 1, based on @oleksandr-albul answer above.

 fun getDayCountBetween(to: Long, from: Long): Int {
    if (to <= from) return 0
    val calendar = Calendar.getInstance()
    var count = 0

    // get day count between 'to' and Jan 1st.
    calendar.timeInMillis = to
    val year = calendar.get(Calendar.YEAR)
    count += calendar.get(Calendar.DAY_OF_YEAR)

    // minus day count between 'from' and Jan 1st.
    calendar.timeInMillis = from
    count -= calendar.get(Calendar.DAY_OF_YEAR)

    // plus day count of all the gap years.
    while (calendar.get(Calendar.YEAR) < year) {
        count += calendar.getActualMaximum(Calendar.DAY_OF_YEAR)
        calendar.add(Calendar.YEAR, 1)
    }

    return count
}
ZhouX
  • 1,866
  • 18
  • 22