Search code examples
javadatetimedeltalocaltime

Calculating the time difference between two times in Java


    String time1 = br.readLine();
    DateFormat sdf = new SimpleDateFormat("hh:mm:ss",Locale.ENGLISH);
    Date d1 = sdf.parse(time1);
    int n = Integer.parseInt(br.readLine());
    for(int i=0;i<n;i++) {
        String time2 = br.readLine();
        Date d2 = sdf.parse(time2);
        long diffMs = d1.getTime() - d2.getTime();
        System.out.println(diffMs/(1000*60*60));

Input:

time1 = 23:05:38
time2 = 12:36:07

Output should be 10 but it’s giving 22.


Solution

  • First, I am assuming that the calculation takes place in a time zone without summer time (DST) and other anomalies, or at least on dates where there is no transition.

    I left out the reading from the BufferedReader since you already seem to be handling this fine.

        String time1 = "23:05:38";
        LocalTime t1 = LocalTime.parse(time1);
        String time2 = "12:36:07";
        LocalTime t2 = LocalTime.parse(time2);
        Duration diff = Duration.between(t2, t1);
        System.out.println(diff.toHours());
    

    This prints the expected

    10

    As you can see, I am following Deb’s suggestion in the comment: using the modern Java date and timeAPI known as JSR-310 or java.time. This automatically solves your problem since LocalTime parses your times on the 24 hour clock without any explicit formatter and therefore without the opportunity to use the wrong case in a format pattern string.

    That’s right, I agree with d.j.brown that the lowercase hh in your pattern is the culprit. Your times were interpreted as 23:05:38 AM, which is nonsense, but the outdated SimpleDateFormat just takes that to mean 11:05:38 PM, that is 23:05:38 on a 24 hour clock, that is what you had expected. IMHO it’s quite nasty to let you get away with such a bug without telling you. You were fortunate to have a time that started with “12”, for 12:36:07 AM means 0:36:07 on a 24 hour clock, so this time you got a wrong result and were made aware something was wrong. Otherwise your bug would have gone unnoticed, maybe for a long time. This long story to carry a morale: stay far away from SimpleDateFormat.

    Question: Can I use the modern API with my Java version?

    If using at least Java 6, you can.

    • In Java 8 and later the new API comes built-in.
    • In Java 6 and 7 get the ThreeTen Backport, the backport of the new classes (that’s ThreeTen for JSR-310, where the modern API was first defined).
    • On Android, use the Android edition of ThreeTen Backport. It’s called ThreeTenABP, and I think that there’s a wonderful explanation in this question: How to use ThreeTenABP in Android Project.