Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LocalTime between 23.59 and 00:01 [closed]

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?

like image 762
isADon Avatar asked Mar 23 '18 13:03

isADon


3 Answers

The solution is to use || instead of &&:

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

This is so counter-intuitive, isn't it? The trick is that 00:00:01 are not after 23:59, so that's always going to fail. This is so because LocalTime.isAfter or LocalTime.isBefore assumes that those are times of the same day.

like image 152
Tamas Rev Avatar answered Oct 10 '22 10:10

Tamas Rev


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).

like image 21
Jacob G. Avatar answered Oct 10 '22 11:10

Jacob G.


If you really need to do this that way, it cannot fulfil both statements. Consider using or, this code returns true for me:

public static void main(String[] args)
{
    LocalTime ONE_MINUTE_BEFORE_MIDNIGHT = LocalTime.of(23, 59, 0);
    LocalTime ONE_MINUTE_AFTER_MIDNIGHT = LocalTime.of(0, 1, 0);
    LocalTime md = LocalTime.MIDNIGHT;
    System.out.println(md.isBefore(ONE_MINUTE_AFTER_MIDNIGHT) || md.isAfter(ONE_MINUTE_BEFORE_MIDNIGHT));
}
like image 36
Andronicus Avatar answered Oct 10 '22 10:10

Andronicus