Местное время с 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 минутах от полуночи?

4 ответов


вместо проверки, если 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 экземпляр должен быть больше, чем у второго экземпляра. Это не true для 00:00 и 23:59, следовательно, почему ваш метод возвращает false. Такой же анализ можно сделать по LocalTime#isBefore, и вы получите тот же результат.

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


решение заключается в использовании || вместо &&:

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 предполагает, что это времена в тот же день.


Если вам действительно нужно сделать это таким образом, он не может выполнить оба утверждения. Рассмотрите возможность использования or, этот код возвращает 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));
}

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

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

минуту до полночь до...