1

I am trying to calculate the difference between two hours. Time format must be hh:mm:ss! I implement this code:

public static String timeDifference(long timeDifference1) {

    long timeDifference = timeDifference1 / 1000;
    int h = (int) (timeDifference / (3600));
    int m = (int) ((timeDifference - (h * 3600)) / 60);
    int s = (int) (timeDifference - (h * 3600) - m * 60);

    return String.format("%02d:%02d:%02d", h, m, s);
}

public static void main(String[] args) throws ParseException {
    Scanner sc = new Scanner(System.in);
    while (sc.hasNext()) {
        String timeStart = sc.next();
        String timeStop = sc.next();
        char lol[]=timeStop.toCharArray();
        if(lol[0]=='0' && lol[1]=='0'){
            lol[0]='2';
            lol[1]='4';
        }
        String tetx=String.valueOf(lol);
        timeStop=tetx;

        char kk[]=timeStart.toCharArray();
        if(kk[0]=='0' && kk[1]=='0'){
            kk[0]='2';
            kk[1]='4';
        }
        String hhh=String.valueOf(kk);
        timeStart=hhh;

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

        Date d1 = null;
        Date d2 = null;

        d1 = format.parse(timeStart);
        d2 = format.parse(timeStop);

        long diff;

        if (d1.getTime() > d2.getTime()) {
            diff = (int) (d1.getTime() - d2.getTime());

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

        System.out.println(timeDifference(diff));

    }
}

Input must be:

10:03:43 15:00:58

13:00:00 14:00:00

00:00:00 12:05:00

12:05:00 00:00:00

And output:

04:57:15

01:00:00

12:05:00

11:55:00 

But i get

04:57:15

01:00:00

00:05:00

00:05:00 

How can i fix this?

Michael
  • 41,989
  • 11
  • 82
  • 128
Ema Hoffer
  • 67
  • 1
  • 5
  • 1
    Is this something you do for school ? If not, you should consider using [structures especially made for that](https://www.tutorialspoint.com/java/java_date_time.htm) – Arthur Attout Jun 08 '18 at 08:44
  • 1
    Why reinvent the wheel? Use LocalDateTime API in Java8. Use DateTimeFormatter for parsing. – Amal Gupta Jun 08 '18 at 08:45
  • yes,it is for university.thats why i need this specific timeformat (hh:mm:ss) – Ema Hoffer Jun 08 '18 at 08:47
  • Looks like your parsing the input wrong? try HH:mm:ss You should also consider backward and forward comparisons – Jared Teng Jun 08 '18 at 08:47
  • 2
    Unrelated: look into your naming skills. Try to use names that say more than kk, date1, date2, etc. Names should tell the reader something about your intent. – GhostCat Jun 08 '18 at 08:48
  • new SimpleDateFormat("hh:mm:ss"); maybe is wrong cause you need 24h time format ? new SimpleDateFormat("HH:mm:ss");, edit: atleast i was to slow :D – Van De Wack Jun 08 '18 at 08:50
  • 1
    This has been asked answered before. Please search and find. – Ole V.V. Jun 08 '18 at 09:11
  • Using standard library classes for the task is a good idea and can be done to a much larger extent than you do. However, stay away from the long outdated and poorly designed classes `Date` and especially `SimpleDateFormat`. `java.time` is the modern Java date and time API and much nicer to work with. See the answers by [shash678](https://stackoverflow.com/a/50757107/5772882) and [Michael](https://stackoverflow.com/a/50757107/5772882). – Ole V.V. Jun 08 '18 at 09:20
  • I tend to understand that the times are on the same date except that an end time of 00:00:00 would mean midnight at the end of the day (sometimes called 24.00 where I come from). Is this correct? – Ole V.V. Jun 08 '18 at 09:22
  • 1
    @ArthurAttout I agree completely in your statement, but the page you are linking to is long outdated, using the old and poorly designed date and time classes from Java 1.0 and 1.1. Today we have so much better in [`java.time`, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). – Ole V.V. Jun 08 '18 at 09:35
  • I totally agree with you,this is not the best code,but I still learn :) Thank you for useful information . – Ema Hoffer Jun 08 '18 at 09:42
  • @Ole, sorry about that, I'm always confused with which API is used nowadays .. – Arthur Attout Jun 08 '18 at 14:01
  • On est facilement confus, @ArthurAttout. There are *so* many sites and pages still lying around showing us how to use the old date and time classes that we shouldn’t be using anymore. – Ole V.V. Jun 09 '18 at 08:04

4 Answers4

5

Don't reinvent the wheel. You can do all of this with the java.time package.

The logic becomes slightly less elegant once we have the requirement that a second value of 00:00:00 represents tomorrow. We need to use LocalDateTimes and potentially add a day:

private static String getDifference(final String first, final String second)
{
    final LocalTime firstTime = LocalTime.parse(first, DateTimeFormatter.ISO_LOCAL_TIME);
    final LocalTime secondTime = LocalTime.parse(second, DateTimeFormatter.ISO_LOCAL_TIME);

    final LocalDateTime firstDateTime = LocalDateTime.of(LocalDate.now(), firstTime);
    final LocalDateTime secondDateTime = LocalDateTime.of(
        LocalDate.now().plusDays(second.equals("00:00:00") ? 1 : 0),
        secondTime
    );

    final Duration diff = Duration.between(firstDateTime, secondDateTime).abs();

    return String.format(
        "%02d:%02d:%02d",
        diff.toDaysPart() < 1 ? diff.toHoursPart() : 24,
        diff.toMinutesPart(),
        diff.toSecondsPart()
    );
}

Call like so:

System.out.println(getDifference("12:05:00", "00:00:00"));

Sample output:

11:55:00


Please note that toMinutesPart and its sibling methods were added in JDK 9. The logic is fairly similar in JDK 8 but more verbose.

Michael
  • 41,989
  • 11
  • 82
  • 128
  • 1
    but when the start time is 12:05:00 and end time is 00:00:00 the answer is wrong.(12:05:00 ,must be 11:55:00) – Ema Hoffer Jun 08 '18 at 09:01
  • Then the problem is ambiguous. Is 00:00:00 the start of the day or the end of the day? It can't (or shouldn't) be both. – Michael Jun 08 '18 at 09:02
  • 1
    If the input is `00:00:00` and `00:00:00` is the answer zero or 24 hours? – Michael Jun 08 '18 at 09:07
  • first input is start time and the second is end time.Code must calculate difference between this two times in hours. Like: Start :12:05:00 End:00:00:00. Between this two times have 11:55:00 hours difference. – Ema Hoffer Jun 08 '18 at 09:09
  • the answer must be 24:00:00 – Ema Hoffer Jun 08 '18 at 09:09
  • @OleV.V. Hm, maybe not quite. `13:00:00` and `13:00:00` would give a duration of zero but I presume that should give an output of zero, not 24. – Michael Jun 08 '18 at 09:21
2

The answer by Michael is good (+1). Allow me to add that you don’t need to mention any formatter (though I also see the advantage of being explicit about the format) and you don’t need to invent an artificial and probably incorrect date to deal with the 24:00 issue.

        LocalTime start = LocalTime.parse(timeStart);
        LocalTime stop = LocalTime.parse(timeStop);
        if (stop.isAfter(start)) { // the normal situation
            System.out.println(formatDuration(Duration.between(start, stop)));
        } else if (stop.equals(LocalTime.MIDNIGHT)) {
            System.out.println(
                    formatDuration(Duration.between(start, stop).plusDays(1)));
        } else {
            System.out.println("End time " + timeStop + " was before start time " + timeStart);
        }

I am assuming that the times are on the same date except that an end time of 00:00:00 would mean midnight at the end of the day (sometimes called 24.00 where I come from). If you need to calculate, say from 13:00 one day to 13:00 to the next day as 24 hours, just delete the second if condition and the last else block.

Feeding your example input gives the output you asked for:

04:57:15
01:00:00
12:05:00
11:55:00

As Michael mentions, the toMinutesPart and toSecondsPart methods were introduced in Java 9. For how to format the duration in earlier Java versions see my answer here.

What went wrong in your code?

To parse times on a 24 hour clock correctly (12:05:00, 13:00:00, 14:00:00, 15:00:58) you need to use uppercase HH for hour of day. Lowercase hh is for hour within AM or PM from 01 to 12 inclusive. When you don’t specify AM or PM, AM is used as default. So 10:03:43 is parsed as you expected. Funnily 15:00:58 is too even though there is no 15:00:58 AM. SimpleDateFormat just extrapolates. The trouble comes with 12:05:00 since 12:05:00 AM means 00:05:00. On my computer I got 23:55:00 (not 00:05:00, as you said you got). This is because you had first altered the start time into 24:00:00 and next calculated the time from 00:05:00 to 24:00:00, which is 23:55:00. Since you know which time is the start time and which is the end time, you probably shouldn’t swap them in the case where they seem to be in the wrong order. In your last example I got 23:55:00 too. What happens is the same except the times aren’t swapped since 00:05:00 is already before 24:00:00.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
0

Please change hh to HH in SimpleDateFormat. This will give you result in 24 hour format. https://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html

SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");
Ashish Patil
  • 4,428
  • 1
  • 15
  • 36
  • I know,but it must be in hh:mm:ss.So the task is set. – Ema Hoffer Jun 08 '18 at 08:56
  • What is meant by hh:mm:ss? I mean, either it just means that the hours should be two digits before the first colon, and if so, the answer is correct (though not spotting all issues in your code). Don’t expect to copy the pattern verbatim from the assignment to the code. Or else it means that the number before the colon is hour in am/pm (1-12), and if so, you’re missing an AM/PM marker, and input times should not be allowed to be for example 15:00:58 or 00:00:00. – Ole V.V. Jun 08 '18 at 11:08
0

You can add date to fix it:

import java.time.LocalTime;
import java.time.LocalDate;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class MyClass {
    public static void main(String args[]) {

        DateTimeFormatter formatter =
            DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss");
        LocalTime timeStart  = LocalTime.parse("00:00:00");
        LocalTime timeStop  = LocalTime.parse("12:05:00");
        LocalDateTime dateTime1 = LocalDateTime.of(LocalDate.now(), timeStart);
        LocalDateTime dateTime2 = LocalDateTime.of(LocalDate.now(), timeStop);
        executeDifference(dateTime1, dateTime2);


        LocalTime timeStart2  = LocalTime.parse("12:05:00");
        LocalTime timeStop2  = LocalTime.parse("00:00:00");
        LocalDateTime dateTime3 = LocalDateTime.of(LocalDate.now(), timeStart2);
        LocalDateTime dateTime4 = LocalDateTime.of(LocalDate.now().plusDays(1), timeStop2);
        executeDifference(dateTime3, dateTime4);
    }

     private static void executeDifference(LocalDateTime timeStart, LocalDateTime timeStop) {
        Duration duration = Duration.between(timeStart, timeStop);
        durationOutput(duration);
    }

    private static void durationOutput(Duration duration) {
        long hours = duration.toHours();
        long minutes = duration.toMinutes() - (hours * 60);
        long seconds = duration.getSeconds() - (hours * 3600) - (minutes * 60);
        System.out.println(timeUnitsOutput(hours) + ":" + timeUnitsOutput(minutes) + ":" + timeUnitsOutput(seconds));
    }

    private static String timeUnitsOutput(long units) {
        return (units < 10) ? ("0" + units) : String.valueOf(units);
    }
}

The output will be:

12:05:00

11:55:00

Ksenia
  • 3,453
  • 7
  • 31
  • 63