3

I am trying to calculate time diffrence between dates:

public static void main(String args[])
{
    String start = "2013-03-10 10:28:47.000000";
    String end = "2013-04-07 09:54:08.054577";

    CalculateDuration calc = new CalculateDuration();
    calc.calculateDiffrenceInMinutes(start,end);
}
public int calculateDiffrenceInMinutes(String start_time, String end_time)
{

    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  

    Date d1 = null;
    Date d2 = null;
    try {
        d1 = format.parse(start_time);
        d2 = format.parse(end_time);
    } catch (ParseException e) {
        e.printStackTrace();
    }    

    // Get msec from each, and subtract.
    int diff = (int) d2.getTime() - (int)d1.getTime();
    int diffSeconds = (int) (diff / 1000);         
    int diffMinutes = (int) (diff / (60 * 1000));         
    int diffHours = (int) (diff / (60 * 60 * 1000));                      

    return diffMinutes;
}

For some reason i cant understand the example i show give a negetive output even though the end date is after the start date.

Any ideas?

Andrea Ligios
  • 49,480
  • 26
  • 114
  • 243
Michael A
  • 5,770
  • 16
  • 75
  • 127
  • In addition to the answer below, it's generally better to make functions take the actual parameters they're interested in; your method ought to take `Date`s, not `String`s. This makes it easier to test (maybe your conversion wasn't working properly) and more flexible to use. – chrylis -cautiouslyoptimistic- Sep 02 '13 at 14:13
  • 1
    @chrylis And also, because it might lead to situations later on, where someone converts his `Date` instances to `String` so he can call this method (which then converts them back to `Date`). Which is completeley needless. – brimborium Sep 02 '13 at 14:21

3 Answers3

8

Try changing

int diff = (int) d2.getTime() - (int)d1.getTime();

to

long diff = d2.getTime() - d1.getTime();

Explicit typecasting from long to int will cause precision loss and may result in a negative value on subtraction.

long a = 90000000000000L;
long b = 10000001000000L;

a>b
(int)a-(int)b => negative value
rocketboy
  • 9,573
  • 2
  • 34
  • 36
4

As others pointed out about precision loss, you can read the details in here.

long diff = d2.getTime() - d1.getTime();
long diffSeconds = diff / 1000 % 60;  
long diffMinutes = diff / (60 * 1000) % 60;
long diffHours   = diff / (60 * 60 * 1000) % 60;

Java's date-time API has some design issues. Calendar is not thread safe. You may want to look at Joda-Time. This would make it as simple as-

Seconds.between(startDate, endDate);
Sajal Dutta
  • 18,272
  • 11
  • 52
  • 74
  • How is Java's Calendar "very much buggy"? Can you point out some unresolved bugs? That is a bold statement to put in an answer. – VGR Sep 04 '13 at 00:36
  • @VGR I don't want to write a long message. So here are some answers might help. http://stackoverflow.com/questions/12032051/differences-between-java-util-date-and-joda-time-apis – Sajal Dutta Sep 04 '13 at 08:30
  • http://stackoverflow.com/questions/12131324/is-java-util-calendar-thread-safe-or-not – Sajal Dutta Sep 04 '13 at 08:31
  • http://stackoverflow.com/questions/589870/should-i-use-java-date-and-time-classes-or-go-with-a-3rd-party-library-like-joda – Sajal Dutta Sep 04 '13 at 08:32
2

Date#getTime() returns a long and that has a reason. Because quite a few milliseconds have passed since January 1, 1970, 00:00:00 GMT. An int can't hold that huge number (and overflows, which explains why you might get negative numbers (depending on the two dates)). So you should use long to do the calculations.

I would change your code like this:

long diff = d2.getTime() - d1.getTime();
long diffSeconds = diff / (          1000);         
long diffMinutes = diff / (     60 * 1000);         
long diffHours   = diff / (60 * 60 * 1000);

Of course, you also need to change the return type of your calculateDiffrenceInMinutes method to long.

Note: In your example, you could also leave diffSeconds, diffMinutes and diffHours as int. But I wouldn't recommend that, as this would be a solution that fails if the dates are too far apart.

brimborium
  • 9,362
  • 9
  • 48
  • 76