0

I am trying to calculate the time difference in java by input time format in 12 hours it works well when i input start time 11:58:10 pm and end time 12:02:15 am. But as i enter 12:00:00 am and 12:00:00 pm it give difference 0 minutes. don't know why. Below is my code please let me know where i am wrong.

Scanner input = new Scanner(System.in);
System.out.print("Enter start time (HH:mm:ss aa): ");
String starttime = input.nextLine();

System.out.print("Enter end time (HH:mm:ss aa): ");
String endtime = input.nextLine();

//HH converts hour in 24 hours format (0-23), day calculation
SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss aa");

Date d1 = null;
Date d2 = null;

try {
    d1 = format.parse(starttime);
    d2 = format.parse(endtime);

    //in milliseconds
    long diff = d2.getTime() - d1.getTime();

    long diffSeconds = diff / 1000 % 60;
    long diffMinutes = diff / (60 * 1000) % 60;

    System.out.print(diffMinutes + " minutes and "+diffSeconds + " seconds.");
} catch (Exception e) {
    System.out.println("Invalid fromat");
}
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
Azeem Hafeez
  • 250
  • 4
  • 14
  • 1
    HH expects the hour in 24 format, not 12. – Phaelax z Mar 03 '20 at 17:40
  • 4
    `HH` is for 24 hour clock, use `hh` instead. And it's better not to use the old classes like `Date` and `SimpleDateFormat` for this. For one, they are not designed to represent wall clock times. Use `LocalTime` and `DateTimeFormatter` – RealSkeptic Mar 03 '20 at 17:40
  • i used hh format but still same – Azeem Hafeez Mar 03 '20 at 17:48
  • 1
    Does this have to be `Date` and `SimpleDateFormat`? These are regarded as obsolete, new code should use `LocalTime`, `DateTimeFormatter` and `Duration` for this calculation. – greg-449 Mar 03 '20 at 18:07
  • can give me any example of it – Azeem Hafeez Mar 03 '20 at 18:10
  • [Java 8: Calculate difference between two LocalDateTime](https://stackoverflow.com/questions/25747499/java-8-calculate-difference-between-two-localdatetime) – Abra Mar 03 '20 at 18:27
  • 1
    Please use `java.time`. – MC Emperor Mar 03 '20 at 20:20
  • I (too) recommend you don’t use `SimpleDateFormat` and `Date`. Those classes are poorly designed and long outdated, the former in particular notoriously troublesome. Instead use `LocalTime`, `DateTimeFormatter` and also `Duration`, all from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). – Ole V.V. Mar 04 '20 at 19:00

2 Answers2

4

The new java.time methods LocalTime, DateTimeFormatter and Duration provide much better methods for handling this. For example:

DateTimeFormatter format = DateTimeFormatter.ofPattern("h:m:s a");

LocalTime time1 = LocalTime.parse("12:00:00 am", format);
LocalTime time2 = LocalTime.parse("2:00:20 pm", format);

Duration dur = Duration.between(time1, time2);

System.out.println(dur.toMinutes() + " minutes " + dur.toSecondsPart() + " seconds");

Note: Duration.toSecondsPart requires Java 9 or later, the rest of this code requires Java 8 or later.

greg-449
  • 109,219
  • 232
  • 102
  • 145
  • The class isn't deprecated, and while I don't *disagree* that this is better, sometimes you *have* to use `Date`. – Makoto Mar 03 '20 at 20:10
  • @Makoto Like when you’ve got an evil boss who says so? I can think of very, very few situations. – Ole V.V. Mar 04 '20 at 19:57
  • 1
    @OleV.V.: To my understanding, there are some gotchas with Hibernate which exist; there may be no incentive to change from `Date` to `LocalDate` or `LocalDateTime` because that could break contracts in code that is being maintained; etc. It doesn't always have to be someone or something evil in the mix. – Makoto Mar 04 '20 at 22:10
  • Frankly, @Makoto, what are you talking about? The question is about having two strings and calculating the minutes and seconds between them, there’s no persistence involved from what we know. (Besides my Hibernate 5 has been working flawlessly with java.time until now.) – Ole V.V. Mar 04 '20 at 22:15
  • Fair...I think my head was in a different space @OleV.V.. However, I don't see the value in using a different class just because of a typo (as we established, should be lower-case `hh` as opposed to upper-case). Again, sometimes you just *have* to use it. – Makoto Mar 04 '20 at 22:16
1

The problem is with the following line:

SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss aa");

It should be:

SimpleDateFormat format = new SimpleDateFormat("hh:mm:ss aa");

The symbol, H is used for a time in 24-hour format while h is used for that in 12-hour format.

Your calculation of diffMinutes is also wrong.

Do it as follows:

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("Enter start time (hh:mm:ss aa): ");
        String starttime = input.nextLine();

        System.out.print("Enter end time (hh:mm:ss aa): ");
        String endtime = input.nextLine();

        SimpleDateFormat format = new SimpleDateFormat("hh:mm:ss aa");

        Date d1 = null;
        Date d2 = null;

        try {
            d1 = format.parse(starttime);
            d2 = format.parse(endtime);

            // in milliseconds
            long diff = Math.abs(d2.getTime() - d1.getTime());

            long diffSeconds = (diff / 1000) % 60;
            long diffMinutes = (diff / (60 * 1000));

            System.out.print(diffMinutes + " minutes and " + diffSeconds + " seconds.");
        } catch (Exception e) {
            System.out.println("Invalid fromat");
        }
    }
}

A sample run:

Enter start time (hh:mm:ss aa): 10:20:30 am
Enter end time (hh:mm:ss aa): 10:20:13 pm
719 minutes and 43 seconds.

Notes:

  1. As @greg-449 has mentioned, you should strive to use modern date-time API.
  2. The difference between two quantities is an absolute value which is always positive i.e. the difference between 2 and 5 = difference between 5 and 2 = 3. Math.abs gives you the absolute value of a number which suites best for finding the difference between two quantities.
  3. You need to understand that without telling about the date, the difference between two times is always considered for the same date i.e. the difference between 12:02:15 am and 11:58:10 pm = difference between 11:58:10 pm and 12:02:15 am = 1435 minutes and 55 seconds. The difference between 11:58:10 pm on one date and 12:02:15 am on the next date is 4 minutes 5 seconds. However, your input is only for times and does not have date element and therefore the difference has been considered for the same date. Given below is the program to consider a date with time.

Program considering a date with time:

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        System.out.print("Enter start time (dd.MM.yyyy at hh:mm:ss aa): ");
        String starttime = input.nextLine();

        System.out.print("Enter end time (dd.MM.yyyy at hh:mm:ss aa): ");
        String endtime = input.nextLine();

        SimpleDateFormat format = new SimpleDateFormat("dd.MM.yyyy 'at' hh:mm:ss aa");

        Date d1 = null;
        Date d2 = null;

        try {
            d1 = format.parse(starttime);
            d2 = format.parse(endtime);

            // in milliseconds
            long diff = Math.abs(d2.getTime() - d1.getTime());

            long diffSeconds = (diff / 1000) % 60;
            long diffMinutes = (diff / (60 * 1000));

            System.out.print(diffMinutes + " minutes and " + diffSeconds + " seconds.");
        } catch (Exception e) {
            System.out.println("Invalid fromat");
        }
    }
}

A sample run:

Enter start time (dd.MM.yyyy at hh:mm:ss aa): 03.03.2020 at 11:58:10 pm
Enter end time (dd.MM.yyyy at hh:mm:ss aa): 04.03.2020 at 12:02:15 am
4 minutes and 5 seconds.
Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110