1

i need java code to find difference between two times in 24 hour format for example: 20:00:00 - 04:00:00

and the expected output is 8 hrs but now output is 16 hrs when i tried 12 hour format out put is coming 4.

below is the code used to parse and to find difference

SimpleDateFormat readFormat = new SimpleDateFormat("HH:mm");
Date d1 = readFormat.parse(txtshiftIn);
Date d2 = readFormat.parse(txtshiftOut);
long diff = d2.getTime() - d1.getTime();

input is just 20:00 and 04:00 no seconds and AM/PM part.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Cimy Riya
  • 75
  • 1
  • 13
  • @Govinda Sakhare String txtshiftIn=request.getParameter("shiftIn"); – Cimy Riya Jan 29 '20 at 13:05
  • So the times expand two different days and it is not part of the same day? – locus2k Jan 29 '20 at 13:25
  • yes,time expands two different days,its not part of the same day – Cimy Riya Jan 29 '20 at 13:26
  • I 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` and `DateTimeFormatter`, both from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). – Ole V.V. Jan 30 '20 at 03:26

2 Answers2

3

The issue with using Date is it still expects an actual date even though you are using just the time portion of it, so if you're just sending it the time it will not be correct.

Instead use LocalTime and ChronoUnit.HOURS to get the difference between the time.

DateTimeFormatter dtf = DateTimeFormatter.ofPattern("HH:mm");
LocalTime lt1 = LocalTime.parse(txtshiftIn, dtf);
LocalTime lt2 = LocalTime.parse(txtshiftOut, dtf);

long diff = ChronoUnit.HOURS.between(lt1, lt2);

This will show -16 which means that lt1 is ahead of lt2 which indicates lt2 is the next day so we can modify it to get the differences as such

if (diff < 0) {
  diff += 24;
}

This will give you the 8 hour difference you're expecting.

UPDATE To account the difference in minutes you can do the following:

DateTimeFormatter dtf = DateTimeFormatter.ofPattern("HH:mm");
LocalTime lt1 = LocalTime.parse(txtshiftIn, dtf);
LocalTime lt2 = LocalTime.parse(txtshiftOut, dtf);

long diff = ChronoUnit.MINUTES.between(lt1, lt2); //get diff in minutes

if (lt2.isBefore(lt1)) {
  diff += TimeUnit.DAYS.toMinutes(1); //add a day to account for day diff
}

long hours = diff / 60;
long minutes = diff % 60;

LocalTime newTime = LocalTime.parse(String.format("%02d:%02d", hours, minutes), dtf); //Format the difference to be converted to LocalTime

System.out.println(newTime);

This will produce the difference in minutes:

08:30

Update 2

Here is a cleaner method that returns a Duration

public Duration timeDifference(String txtshiftIn, String txtshiftOut) {
  DateTimeFormatter dtf = DateTimeFormatter.ofPattern("HH:mm");
  LocalTime lt1 = LocalTime.parse(txtshiftIn, dtf);
  LocalTime lt2 = LocalTime.parse(txtshiftOut, dtf);

  Duration between = Duration.between(lt1, lt2);

  if (lt2.isBefore(lt1)) { //account for lt2 being on the next day
    between = Duration.ofMinutes(TimeUnit.DAYS.toMinutes(1)).plus(between);
  }

  return between;
}
locus2k
  • 2,802
  • 1
  • 14
  • 21
  • expected output is 8,but the output of above code is -16 – Cimy Riya Jan 29 '20 at 13:23
  • 1
    Fixed answer to accommodate the difference in days. – locus2k Jan 29 '20 at 13:33
  • 3
    Great. You can use `lt2.isBefore(lt1)` to improve readibility – Govinda Sakhare Jan 29 '20 at 13:51
  • You can even parse without the formatter, just `LocalTime.parse(txtshiftIn)` and the same for the shift out time. – Ole V.V. Jan 30 '20 at 03:28
  • but when i executed the code to find time between 20:00 and 4:30 it is giving 9 hrs,the expected output is 8 hrs 30 minutes – Cimy Riya Jan 30 '20 at 06:39
  • Because its rounding. If you change `ChronoUnit.HOURS` to `ChronoUnits.MINUTES` itll return the minutes between then you can do the conversion on how many hours and minutes it is – locus2k Jan 30 '20 at 06:41
  • i tried but i am not able to obtain the expected output as 8 hrs 30 min .can you please provide the code to convert to hours and minutes after finding difference – Cimy Riya Jan 30 '20 at 08:24
  • See my edit. It returns a `LocalTime` now so it will be hours and minutes – locus2k Jan 30 '20 at 16:18
  • Using a `LocalTime` for an amount of time is wrong. You should use `Duration`. It will also be simpler. I have retracted my upvote. – Ole V.V. Jan 31 '20 at 21:31
  • @OleV.V.You're correct `Duration` is the simplest way to do it and that would be what I would do. I was thinking of more what the OP wanted. I updated my answer to include the Duration – locus2k Feb 02 '20 at 07:03
1

While it is strongly recommended you use a more up-to-date Java time library like LocalTime your logic so far actually is correct with one little caveat:

SimpleDateFormat readFormat = new SimpleDateFormat("HH:mm");
Date d1 = readFormat.parse(txtshiftIn);
Date d2 = readFormat.parse(txtshiftOut);
long diff = d2.getTime() - d1.getTime();

In your code if d1 is after d2 you will get a negativ result for long diff

So when you say

"but now output is 16 hrs"

The actual output is -16 hrs

Of course minus sixteen hours doesn't make much sense in your case, but you can easily fix that with the simple trick of just adding 24 hours in case of a negative result for diff. (And -16+24 is the 8 you expected as a result).

So just add the following lines at the end of your posted code

if(diff < 0) {
    diff = 86400000 + diff;
} 

And you will get the results you expect! (86400000 is the 24h expressed in milliseconds)

OH GOD SPIDERS
  • 3,091
  • 2
  • 13
  • 16