LocalTime между 23.59 и 00:01

Я хочу проверить, является ли LocalTime полночь. Для этого случая использования полночь определяется как что-либо между 23:59 и 00:01. Это диапазон 2 минуты.

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

У меня есть метод

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

Этот метод всегда возвращает false. Даже для LocalTime.MIDNIGHT. он должен, однако, вернуться к true.

Как я могу проверить, является ли время +-1 минутой с полуночи?

Ответ 1

Вместо того, чтобы проверять, прошло ли time после 23:59 и до 00:01, вы должны проверить, есть ли это после 23:59 или до 00:01.

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

Если мы посмотрим на реализацию для LocalTime#isAfter, мы увидим следующее:

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

Просмотр 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;
}

Мы видим, что два экземпляра LocalTime сначала сравниваются по их часам, а затем по минутам, секундам и, наконец, наносекундам. Для LocalTime#compareTo возвращает значение больше 0 чтобы удовлетворить LocalTime#isAfter, час первого экземпляра LocalTime должен быть больше, чем второй экземпляр. Это не относится к 00:00 и 23:59, поэтому ваш метод возвращает false. Такой же анализ можно сделать для LocalTime#isBefore, и вы получите тот же результат.

Имейте в виду, что вы можете просто проверить с LocalTime.MIDNIGHT если хотите быть точным, но я предполагаю, что вы рассматриваете любое время в пределах 1-минутного диапазона как "полночь" (включая секунды).

Ответ 2

Решение состоит в использовании || вместо &&:

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

Это настолько противоречиво, не так ли? Фокус в том, что 00:00:01 не после 23:59, так что всегда будет терпеть неудачу. Это так, потому что LocalTime.isAfter или LocalTime.isBefore предполагает, что те времена в тот же день.

Ответ 3

Если вам действительно нужно это делать, он не может выполнять оба утверждения. Подумайте об использовании или, этот код возвращает true для меня:

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

Ответ 4

Как уже объяснялось, вы должны использовать || вместо &&. Я думаю, это более читаемо, если вы реорганизовываете переменные в условии следующим образом:

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

За одну минуту до полуночи до...