Checking if LocalDateTime falls within a time range

11,999

Solution 1

As @JB Nizet said in the comments, you're using the OR operator (||).
So you're testing if A is after B - 90 OR A is before B + 90. If only one of the conditions is satisfied, it returns true.

To check if A is in the range, both conditions must be satisfied, so you must use the AND operator (&&):

if (timeA.isAfter(timeB.minusMinutes(90)) && timeA.isBefore(timeB.plusMinutes(90))) {
    return isInRange;   
}

But the code above doesn't return true if A is exactly 90 minutes before or after B. If you want it to return true when the difference is also exactly 90 minutes, you must change the condition to check this:

// lower and upper limits
LocalDateTime lower = timeB.minusMinutes(90);
LocalDateTime upper = timeB.plusMinutes(90);
// also test if A is exactly 90 minutes before or after B
if ((timeA.isAfter(lower) || timeA.equals(lower)) && (timeA.isBefore(upper) || timeA.equals(upper))) {
    return isInRange;
}

Another alternative is to use a java.time.temporal.ChronoUnit to get the difference between A and B in minutes, and check its value:

// get the difference in minutes
long diff = Math.abs(ChronoUnit.MINUTES.between(timeA, timeB));
if (diff <= 90) {
    return isInRange;
}

I used Math.abs because the difference can be negative if A is after B (so it's adjusted to be a positive number). Then I check if the difference is less than (or equal) to 90 minutes. You can change it to if (diff < 90) if you want to exclude the "equals to 90 minutes" case.


There's a difference between the approaches.

ChronoUnit rounds the difference. e.g. If A is 90 minutes and 59 seconds after B, the difference will be rounded to 90 minutes and if (diff <= 90) will be true, while using isBefore and equals will return false.

Solution 2

LocalDateTime implements the Comparable interface. Why not use it to check if a value falls within a range like this:

public static boolean within(
    @NotNull LocalDateTime toCheck, 
    @NotNull LocalDateTime startInterval, 
    @NotNull LocalDateTime endInterval) 
{
    return toCheck.compareTo(startInterval) >= 0 && toCheck.compareTo(endInterval) <= 0;
}
Share:
11,999
Rk R Bairi
Author by

Rk R Bairi

Runs things using thoughts. Interested in tech and agriculture.

Updated on July 15, 2022

Comments

  • Rk R Bairi
    Rk R Bairi almost 2 years

    I have a time A which should fall within 90 minutes range of timeB (before and after).

    Example: if timeB is 4:00 pm , time A should be between 2:30pm (-90) to 5:30pm (+90)

    Tried the following :

    if(timeA.isAfter(timeB.minusMinutes(90)) || timeA.isBefore(timeB.plusMinutes(90))) {
        return isInRange;   
    }
    

    Can you help me whats wrong with the logic here?

    • JB Nizet
      JB Nizet over 6 years
      || should be &&.