Как проверить, перекрывает ли период времени другой период времени независимо от AM / PM - PullRequest
0 голосов
/ 09 февраля 2020

Следующая ссылка: Как проверить, перекрывает ли период времени другой период времени в java, полезно проверить, перекрывается ли данная отметка времени с другой отметкой времени.

Однако это только работает, если две метки времени находятся в AM или PM. Что я хочу проверить, так это то, что данная временная метка перекрывает другую временную метку независимо от того, находится ли она в AM или PM.

Например: если у меня есть Array меток времени (в 24-часовом формате ):

1:00 - 3:00

13:45 - 14:45

3:15 - 4:00.

Первые два технически перекрываются с 13:45 - 14:45 между 1: 00-3: 00 (если преобразовать в 12-часовой формат)

Как сделать Я проверяю на то же самое? Я хочу по существу проверить, есть ли какое-либо совпадение между временными метками (+/- 30 минут)

1 Ответ

1 голос
/ 09 февраля 2020

Предполагая, что каждый интервал находится в пределах либо AM, либо PM

Я предполагаю, что каждый интервал полностью находится в пределах AM (с 00:00 до 12) или PM (с 12:00 до 00). Я не понял, что вы имели в виду под «(+/- 30 минут)», поэтому я проигнорировал это.

В целом, я считаю это искусственным испытанием. В реальном мире 2 часа ночи и 2 часа дня - это не одно и то же, просто они имеют одинаковое представление на 12-часовых часах. Точно так же, как флагшток и человек из Польши не одинаковы, хотя у них обоих есть представление «Полюс».

Как предложил Свипер в комментарии, я конвертирую каждый интервал в AM (если это было в PM). ) до сопоставления.

    LocalTime begin1 = LocalTime.of(1, 0);
    LocalTime end1 = LocalTime.of(3, 0);
    LocalTime begin2 = LocalTime.of(13, 45);
    LocalTime end2 = LocalTime.of(14, 45);

    // Convert interval 1 to AM
    if (begin1.get(ChronoField.AMPM_OF_DAY) == 1) { // PM
        begin1 = begin1.minusHours(12);
        end1 = end1.minusHours(12);
    }
    // validate
    if (end1.isBefore(begin1)) {
        throw new IllegalStateException("end1 " + end1 + " must not be before begin1 " + begin1);
    }
    if (end1.isAfter(LocalTime.NOON)) {
        throw new IllegalStateException("Interval 1 must be completely within either AM or PM");
    }

    // Convert interval 2 to AM
    if (begin2.get(ChronoField.AMPM_OF_DAY) == 1) {
        begin2 = begin2.minusHours(12);
        end2 = end2.minusHours(12);
    }
    // validate
    if (end2.isBefore(begin2)) {
        throw new IllegalStateException("end2 " + end2 + " must not be before begin2 " + begin2);
    }
    if (end2.isAfter(LocalTime.NOON)) {
        throw new IllegalStateException("Interval 2 must be completely within either AM or PM");
    }

    if (end2.isAfter(begin1) && end1.isAfter(begin2)) {
        System.out.println("They overlap");
    } else {
        System.out.println("They do not overlap");
    }

Выходные данные из этого кода:

Они перекрываются

Угловой случай: я принимаю время окончания 12 : 00 (полдень) для интервала AM и 00:00 для интервала PM. У LocalTime.minusHours() есть циклический c недостаток, поэтому вычитание 12 часов с 00:00 дает 12: 00.

Код может быть проще и проще, если вы определите класс TimePeriod с помощью поля для начала и конца, метод проверки перекрытия и вспомогательный метод для преобразования в AM.

Без ограничений

Редактировать: Предполагая, что каждый интервал может иметь любую длину от 0 (включительно) до 24 часов (не включительно) и может пересекать 00:00, это несколько сложнее, но я не мог позволить заданию отдохнуть.

Некоторые наблюдения:

  1. Если один интервал составляет 12 часов или более, а другой имеет ненулевую длину, оба обязательно перекрываются.
  2. Если оба интервала короче 12 часов, то, если они не перекрываются, мы можем go (считать) циклически вперед от begin1 до end1 и begin2 до end2 в указанном здесь порядке и либо не пересекают 12 часов или пересекают 12 один раз и заканчиваются раньше begin1. Если этот цикл не работает, интервалы должны как-то перекрываться.

В коде:

public static boolean overlaps(LocalTime begin1, LocalTime end1, LocalTime begin2, LocalTime end2) {
    if (begin1.equals(end1)) { // zero length, cannot overlap anything
        return false;
    }
    if (begin2.equals(end2)) {
        return false;
    }

    // If any interval is 12 hours or longer,
    // the other one is necessarily included, that is, overlaps
    if (is12HoursOrLonger(begin1, end1)) {
        return true;
    }
    if (is12HoursOrLonger(begin2, end2)) {
        return true;
    }

    // Convert all times to AM
    begin1 = toAm(begin1);
    end1 = toAm(end1);
    begin2 = toAm(begin2);
    end2 = toAm(end2);

    // For the two intervals *not* to overlap we must be able to go forward
    // from begin1 through end1 and begin2 to end2 in this order either
    // not crossing 12 or crossing 12 once and ending before or on begin1
    boolean crossed12OClock = false;
    if (end1.isBefore(begin1)) { // to go forward to end1 we are crossing 12 o’clock
        crossed12OClock = true;
    }
    if (begin2.isBefore(end1)) {
        if (crossed12OClock) {
            // crossing 12 for the second time;
            // intervals cannot be in non-overlapping order
            return true;
        }
        crossed12OClock = true;
    }
    if (end2.isBefore(begin2)) {
        if (crossed12OClock) {
            return true;
        }
        crossed12OClock = true;
    }
    if (crossed12OClock) {
        return end2.isAfter(begin1);
    } else {
        return false;
    }
}

Этот метод использует следующие два вспомогательных метода:

private static boolean is12HoursOrLonger(LocalTime begin, LocalTime end) {
    Duration length = Duration.between(begin, end);
    if (length.isNegative()) {
        length = length.plusDays(1);
    }
    return ! length.minusHours(12).isNegative();
}

private static LocalTime toAm(LocalTime time) {
    return time.with(ChronoField.AMPM_OF_DAY, 0);
}

Давайте попробуем это, используя время, указанное ранее:

    if (overlaps(begin1, end1, begin2, end2)) {
        System.out.println("They overlap");
    } else {
        System.out.println("They do not overlap");
    }

Они перекрываются

Поскольку код и аргументы сложны, убедитесь, что методы тщательно с юнит-тестами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...