Search code examples
javatimejava-8java-timelocaltime

LocalTime between 23.59 and 00:01


I want to check if a LocalTime is midnight. For this use case midnight is defined as anything in between 23:59 and 00:01. That is a range of 2 minutes.

private final LocalTime ONE_MINUTE_BEFORE_MIDNIGHT = LocalTime.of(23, 59, 0);
private final LocalTime ONE_MINUTE_AFTER_MIDNIGHT = LocalTime.of(0, 1, 0);

I have a method

public boolean isAtMidnight(LocalTime time) {
    return time.isAfter(ONE_MINUTE_BEFORE_MIDNIGHT)
        && time.isBefore(ONE_MINUTE_AFTER_MIDNIGHT);
}

This method is always returning false. Even for LocalTime.MIDNIGHT. it should, however, return true.

How can I check if the time is +-1 minute from midnight?


Solution

  • Instead of checking if time is after 23:59 and before 00:01, you should check if it is after 23:59 or before 00:01.

    public boolean isAtMidnight(LocalTime time){
        return time.isAfter(ONE_MINUTE_BEFORE_MIDNIGHT) || time.isBefore(ONE_MINUTE_AFTER_MIDNIGHT);
    }
    

    If we look at the implementation for LocalTime#isAfter, we see the following:

    public boolean isAfter(LocalTime other) {
        return compareTo(other) > 0;
    }
    

    Looking at LocalTime#compareTo:

    @Override
    public int compareTo(LocalTime other) {
        int cmp = Integer.compare(hour, other.hour);
        if (cmp == 0) {
            cmp = Integer.compare(minute, other.minute);
            if (cmp == 0) {
                cmp = Integer.compare(second, other.second);
                if (cmp == 0) {
                    cmp = Integer.compare(nano, other.nano);
                }
            }
        }
        return cmp;
    }
    

    We can see that two instances of LocalTime are first compared by their respective hours, then minutes, then seconds, and finally nanoseconds. For LocalTime#compareTo to return a value greater than 0 to satisfy LocalTime#isAfter, the hour of the first LocalTime instance must be greater than the second instance's. This is not true for 00:00 and 23:59, hence why your method returns false. The same analysis can be done for LocalTime#isBefore, and you'll arrive at the same result.

    Keep in mind that you can just check against LocalTime.MIDNIGHT if you want to be exact, but I assume you're considering any time within a 1-minute range to be "midnight" (including seconds).