Not Dutch
Not Dutch

Reputation: 49

Average of two LocalTimes

How do I get the average of two LocalTimes? Can't find any suitable methods for this.

So for example 08:00 and 14:30, should return (14-8)/2 = 3 + minutes (30-00= 30)/2, so 3:15 And then smth like

Localtime xxx = LocalTime.parse("08:00", formatter).plus(3, ChronoUnit.HOURS); 
//and after that's done
xxx = xxx.plus(15, ChronoUnit.MINUTES);

Now suppose that I have the following code:

   //this means that if code is 08:00, it should look whether the average of Strings split21 and split2 (which are put in time2 and time3, where time2 is ALWAYS before time3) is before 08:00
   if(code1.contains("800")) {

        LocalTime time1 = LocalTime.parse("08:00", formatter);
        LocalTime time2 = LocalTime.parse(split21, formatter);
        LocalTime time3 = LocalTime.parse(split2, formatter);
        LocalTime average = 
        if(time2.isBefore(time1)) {
            return true;
        }
        else {
            return false;
        }
    }

Obviously I can use.getHour and .getMinute , but there are two problems here.

  1. I cannot divide LocalTime (only if working with hours and minutes seperately but honestly that's a bit too medieval
  2. If I don't directly divide the hours and minutes, it will be higher than 24:00 and I've no clue what will happen then: I suppose it goes further with 00:00 etc instead of 36:00 for example.

Is there someone who could finish this code/explain what's wrong?

Upvotes: 3

Views: 1334

Answers (5)

Anonymous
Anonymous

Reputation: 86324

The way I am thinking of your question you want the midpoint between your two times. Thinking this way I find it most natural to take the difference between the times, divide by 2 and add to the first time (or subtract from the second). This also seems to be what you tried in the question. Rather than handling hours and minutes yourself use the Duration class:

    LocalTime time1 = LocalTime.of(8, 0);
    LocalTime time2 = LocalTime.of(14, 30);
    Duration diff = Duration.between(time1, time2);
    LocalTime midpoint = time1.plus(diff.dividedBy(2));
    System.out.println(midpoint);

Output:

11:15

It obviously only works for two times, not for three or more. The case of more than two times is handled nicely in a couple of the other answers.

Upvotes: 2

Youcef LAIDANI
Youcef LAIDANI

Reputation: 60026

I think you mean something like so :

public static LocalTime average(LocalTime time1, LocalTime time2) {
    if (time1.isAfter(time2)) {
        return LocalTime.of(
                time1.plusHours(time2.getHour()).getHour() / 2,
                time1.plusMinutes(time2.getMinute()).getMinute() / 2
        );
    } else {
        return LocalTime.of(
                time2.plusHours(time1.getHour()).getHour() / 2,
                time2.plusMinutes(time1.getMinute()).getMinute() / 2
        );
    }
}

Then you can call your method multiples times :

LocalTime time1 = LocalTime.of(14, 30);
LocalTime time2 = LocalTime.of(8, 00);

LocalTime result = average(time1, time2);

In case of three times for example :

LocalTime time1 = LocalTime.of(14, 30);
LocalTime time2 = LocalTime.of(8, 00);
LocalTime time3 = LocalTime.now();

LocalTime result = average(average(time1, time2), time3);

..and so on

Outputs of first example

11:15

Upvotes: 1

MC Emperor
MC Emperor

Reputation: 23017

You can easily do this with the Java 8 java.time package, using the LocalTime.ofSecondOfDay(long) method. This is effectively the hour and minute (and second) of the day combined.

public static LocalTime average(LocalTime... times) {
    return LocalTime.ofSecondOfDay((long) Arrays.stream(times)
        .mapToInt(LocalTime::toSecondOfDay)
        .average()
        .getAsDouble());
}
LocalTime t1 = LocalTime.of(8, 0);
LocalTime t2 = LocalTime.of(14, 30);
System.out.println(average(t1, t2)); // Prints 11:15

Upvotes: 1

Joachim Sauer
Joachim Sauer

Reputation: 308131

Since a LocalTime is effectively defined by the nano seconds since midnight, you can do something like this:

public static LocalTime average(LocalTime t1, LocalTime... others) {
  long nanosSum = t1.toNanoOfDay();
  for (LocalTime other : others) {
    nanoSum += others.toNanoOfDay();
  }
  return LocalTime.ofNanoOfDay(nanoSum / (1+others.length));
}

Upvotes: 6

Aakash Baruah
Aakash Baruah

Reputation: 21

I have come out with this code considering your comment in the code //(which are put in time2 and time3, where time2 is ALWAYS before time3)

DateTimeFormatter formatter = DateTimeFormatter.ISO_LOCAL_TIME;

    LocalTime time1 = LocalTime.parse("08:00", formatter);
    LocalTime time2 = LocalTime.parse("14:30", formatter);

    int hour1 = time1.get(ChronoField.CLOCK_HOUR_OF_DAY);
    int hour2 = time2.get(ChronoField.CLOCK_HOUR_OF_DAY);

    int min1 = time1.get(ChronoField.MINUTE_OF_HOUR);
    int min2 = time2.get(ChronoField.MINUTE_OF_HOUR);

    int avgHour = (hour2-hour1)/2;
    int avgMin = (min2-min1)/2;

    String newavgHour = "00:00";
    if(String.valueOf(avgHour).length() == 1) {
        newavgHour = "0"+avgHour+":00";
    } else {
        newavgHour = avgHour+":00";
    }

    LocalTime avgTime = LocalTime.parse(newavgHour, formatter).plus(avgMin, ChronoUnit.MINUTES);
    System.out.println(avgTime);

Upvotes: 0

Related Questions