Проверка, находится ли массив дат в диапазоне дат

Я создал dates_in_range() функция, которая проверяет, все ли даты ей переданы ($dates массив) находятся внутри $start_date и $end_date. Если это не так, он вернет false.

Код работает нормально, но мне интересно, есть ли способ лучше его реорганизовать, используя что-то вроде array_filter? Или это нормально выглядит?

function dates_in_range( $start_date, $end_date, $dates = array() ) {

    foreach ( $dates as $date ) {
        if ( ! ( ( (strtotime( $date ) >= strtotime( $start_date ) ) && ( strtotime( $date ) <= strtotime( $end_date ) ) ) ) ) {
            return false;
        }
    }

    return true;
}

$dates = array(
    '2021-11-19 00:00:00',
    '2020-11-20 00:00:00',
);

$start_date="2021-10-01 00:00:00";
$end_date="2021-12-31 00:00:00";

// Returns true
if ( dates_in_range( $start_date, $end_date, $dates ) ) {
    echo "In range.";
} else {
    echo "Not in range.";
}

2 ответа
2

Для меня это выглядит нормально, но заставляет меня прокручивать код, чтобы прочитать его. На этом основании я согласен с Сэмом, что эту строку следует сократить. Для этого я бы

  • используйте тот факт, что вам не нужно конвертировать даты в формате mysql для их сравнения
  • удалить излишние распорки
  • использовать закон Де Моргана, чтобы обратить условие

и получить это

function dates_in_range( string $start_date, string $end_date, array $dates ): bool
{
    foreach ( $dates as $date ) {
        if ( $date < $start_date || $date > $end_date ) {
            return false;
        }
    }
    return true;
}

Кроме того, я удалил значение по умолчанию для $ date, так как не вижу смысла вызывать эту функцию только с двумя параметрами.

Однако я не уверен в пустых массивах. Ваша функция вернет истину для одного, но трудно сказать, правильно это или нет. Это похоже на деление на ноль, и может возникнуть исключение.

  • Есть плюсы и минусы использования strtotime, ваш ответ предполагает, что даты являются датами в правильном формате mysql, но OP не уточняет их, и это может быть не так, для некоторых входов пользовательского интерфейса нули можно забыть, затем '2021-11-19 08:00:00' и '2021-11-19 8:00:00' даты не будут сравниваться в алфавитном порядке, в то время как strtotime производит правильную метку времени для них обоих.

    — Каддат


  • Я согласен. Лучше предоставить экземпляры DateTime поверх строк или в противном случае проверить входные данные.

    — Ваш здравый смысл


С функцией вроде нормально. В Javascript можно использовать метод Array.every(), но этот вопрос StackOverflow показывает, что на самом деле в PHP нет эквивалентного метода или функционального подхода, который остановил бы цикл, как только один элемент не соответствует требованиям.

Вы можете подумать о соблюдении Стандарты кодирования PSR PHP — особенно PSR 12.

В ПСР-12 есть раздел о строках:

2.3 Линии

НЕ ДОЛЖНО быть жесткого ограничения на длину строки.

Мягкое ограничение на длину строки ДОЛЖНО составлять 120 символов.

Строки НЕ ДОЛЖНЫ быть длиннее 80 символов; строки длиннее этого ДОЛЖНЫ быть разделены на несколько последующих строк не более 80 символов каждая.
1

Читабельность страдает, потому что условная строка немного длиннее, частично из-за отступа, но также из-за дополнительных пробелов, разделяющих круглые скобки. Возможно, это не проблема для любого, у кого широкий экран, но, как видно из фрагмента кода, нужно прокрутить вправо, чтобы увидеть всю строку. Хотя это может быть только микро-оптимизация, можно вытащить strototime($date) out в переменную, что не только уменьшит количество вызовов функций, но и позволит сделать строку короче. Аналогично призывы к strtotime() даты начала и окончания могут быть извлечены из foreach loop и хранятся в переменных, поэтому их нужно вычислять только один раз за вызов функции, и они могут уменьшить длину этой строки с помощью условия.

Я сомневаюсь, подходит ли третий параметр, имеющий значение по умолчанию — пустой массив. Если функция вызывается без аргументов, будет использован пустой массив, и функция вернет true. Возможно, использование подсказки типов было бы лучшим методом:

function dates_in_range( string $start_date, string $end_date, array $dates) : bool {

Обратите внимание, что подпись метода включает в себя объявление типа возврата bool. Это было добавлено в PHP 7.0. 2. Надеюсь, ваш код работает на PHP 7.3 или новее, так как это официально поддерживаемая версия. 3.

    Добавить комментарий

    Ваш адрес email не будет опубликован. Обязательные поля помечены *