Rk R Bairi
Rk R Bairi

Reputation: 1359

Checking if LocalDateTime falls within a time range

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?

Upvotes: 9

Views: 18200

Answers (2)

Maddin
Maddin

Reputation: 1047

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;
}

Upvotes: 2

user7605325
user7605325

Reputation:

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.

Upvotes: 11

Related Questions