18

I need to get the number of minutes between two dates. I know Joda is the best to use, but this is for an Android project, so I prefer to use a little external libraries as possible, and the app I'm building doesn't require the calculation to be surgically precise.

However, the code I'm using doesn't seem to be working. I'm trying to get the number of minutes between "11/21/2011 7:00:00 AM" and "11/21/2011 1:00:00 PM" (which should be 360 minutes), but the code I'm using returns 0:

int diff = minutesDiff(GetItemDate("11/21/2011 7:00:00 AM"), GetItemDate("11/21/2011 1:00:00 PM"));

public static Date GetItemDate(final String date)
{
    final Calendar cal = Calendar.getInstance(TimeZone.getDefault());
    final SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss a");
    format.setCalendar(cal);

    try {
        return format.parse(date);
    } catch (ParseException e) {
        return null;
    }
}

public static int minutesDiff(Date earlierDate, Date laterDate)
{
    if( earlierDate == null || laterDate == null ) return 0;

    return (int)((laterDate.getTime()/60000) - (earlierDate.getTime()/60000));
}
Kris B
  • 3,436
  • 9
  • 64
  • 106
  • It does? It doesn't for me. Also, why are you doing the division twice? – Dave Newton Nov 21 '11 at 18:08
  • 2
    It works perfectly fine for me. The output is -360. – Tyler Nov 21 '11 at 18:17
  • I don't know why you're getting zero, but your format string is wrong. HH is the format for hour between 0 and 23, but since you also have the a format character, I'm assuming you want the hour to be between 1 and 12, and you should be using hh. Currently, your 1:00:00 PM is getting parsed as 1:00:00 AM. – Brigham Nov 21 '11 at 18:25
  • Wouldn't `-1` make more sense as the return value in case one date is `null`? Or throwing an `IllegalArgumentException`? If you return `0`, it seems that the two dates represent the same point in time, but one may not even be a valid object reference. – Giulio Piancastelli Nov 21 '11 at 18:43
  • See my answer for the reason why you're getting the 0 and why this is not working. This might be a locale issue too. – Jarno Argillander Nov 21 '11 at 18:50
  • 1
    Thank Jarno, that was the issue. I was getting an exception when I was formatting the dates. Also, removed the two divisions. :) – Kris B Nov 21 '11 at 18:57

2 Answers2

15

If your GetItemDate is failing for either date, you will get zero. On the catch statement, place a println or debug to output the issue and see if that tells you something.

Also, just as a matter of practice, I'd change:

return (int)((laterDate.getTime()/60000) - (earlierDate.getTime()/60000));

to:

long result = ((laterDate.getTime()/60000) - (earlierDate.getTime()/60000));
return (int) result;

This gives you the opportunity to view the result of the math in an IDE.

Thom
  • 14,013
  • 25
  • 105
  • 185
  • 4
    Many (most?) IDEs have the ability to watch function return values, so creating a local *just* for that purpose shouldn't be necessary. I still wouldn't do the division twice. – Dave Newton Nov 21 '11 at 18:34
  • Good call on the not doing division twice. I didn't even notice. – Thom Nov 21 '11 at 18:36
  • You're probably better of rounding then casting to `int` but that depends on your intention of course. 2 minutes 59 seconds and 4 minutes 0 seconds is 59 seconds closer to 1 minute difference than 2. – Tom Jan 16 '13 at 06:43
  • After reading comments: `return Math.round((laterDate.getTime() - earlierDate.getTime())/60000);` Note: Casting to `int` is not necessary. `Math.round` returns `int`. – ADTC Oct 09 '17 at 18:42
5

I debugged through your code: there is ParseException in GetItemDate() for both of the date strings like:

Unparseable date: 11/21/2011 07:00:00 AM

The problem is that parsing AM/PM hours only works with "hh" (small caps!) or "KK". At least that is the case in my phone (it seems some of us didn't see this issue at all). I tested it also works with a single "h" too.

hh = 1-12
KK = 0-11
HH = 0-23
kk = 1-24

Change your SimpleDateFormat line to this:

final SimpleDateFormat format = new SimpleDateFormat("MM/dd/yyyy hh:mm:ss a", Locale.US);


This post explains the "a" and Locale: Unable to parse DateTime-string with AM/PM marker

PS. I'm from Finland so I must use the "Locale.US" part for this to work. US residents may test the code without it, I think.

Community
  • 1
  • 1
Jarno Argillander
  • 5,885
  • 2
  • 31
  • 33