Я создал 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 ответа
Для меня это выглядит нормально, но заставляет меня прокручивать код, чтобы прочитать его. На этом основании я согласен с Сэмом, что эту строку следует сократить. Для этого я бы
- используйте тот факт, что вам не нужно конвертировать даты в формате 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, так как не вижу смысла вызывать эту функцию только с двумя параметрами.
Однако я не уверен в пустых массивах. Ваша функция вернет истину для одного, но трудно сказать, правильно это или нет. Это похоже на деление на ноль, и может возникнуть исключение.
С функцией вроде нормально. В 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.
Есть плюсы и минусы использования
strtotime
, ваш ответ предполагает, что даты являются датами в правильном формате mysql, но OP не уточняет их, и это может быть не так, для некоторых входов пользовательского интерфейса нули можно забыть, затем'2021-11-19 08:00:00'
и'2021-11-19 8:00:00'
даты не будут сравниваться в алфавитном порядке, в то время какstrtotime
производит правильную метку времени для них обоих.— Каддат
Я согласен. Лучше предоставить экземпляры DateTime поверх строк или в противном случае проверить входные данные.
— Ваш здравый смысл