Возможный дубликат:
Определите, перекрываются ли два диапазона дат
Я пытаюсь работать, если два временных интервала в PHP перекрываются. Я имел в виду определение двух верхних диапазонов дат для моей первоначальной попытки, однако это не соответствует всем случаям. Если временной интервал вложен между начальным и конечным временами другого временного диапазона, он не сопоставляется. Если он перекрывает начало или конец сдвига или если смены являются точными совпадениями, он работает так, как ожидалось.
Посмотрите этот образ того, что я говорю:
В основном, я пытаюсь скрыть любые оранжевые смены, если они пересекают любые красные сдвиги в любом месте. Вот соответствующая часть кода, который я пытаюсь использовать, чтобы это произошло.
if(($red['start'] <= $orange['end']) && ($red['end'] >= $orange['start'])) { //Conflict handling }
Значения переменных – это временные метки UNIX. Работая по номерам логически, я понимаю, почему утверждение выше не работает. Очевидно, что я мог бы сделать больше логики, чтобы определить, попадает ли одна смена в другую смену (что мне может понадобиться), но я надеялся на более универсальный улов.
EDIT: добавление значений времени начала и окончания каждого блока. Я согласен с тем, что должен работать. Тот факт, что это не то, где моя проблема. Я, вероятно, не замечаю ничего глупого.
orange-start = 1352899800 orange-end = 1352907000 red-start = 1352923200 red-end = 1352926200
Поэтому в моей логике указывалось:
if((1352923200 <= 1352907000) && (1352926200 >= 1352899800))
Таким образом, первое сравнение не выполняется.
EDIT 2: Похоже, моя логика звучит (как мне показалось, это так), и моя проблема связана с временной отметкой UNIX, не соответствующей фактическому отображаемому времени. Я благодарю тех, кто работал вместе со мной, и помог мне понять, что это проблема. Хотел бы я согласиться с ответами Андрея и Джейсона.
Логика правильная. Временные метки, которые вы указали для $red
(8-8: 50pm) и $orange
(1: 30-3: 30pm) , не перекрываются .
Учитывая правильные значения (которые отражают ваш снимок экрана), перекрытие действительно найдено:
function show_date($value, $key) { echo $key, ': ', date('r', $value), PHP_EOL; } $red = array('start' => strtotime('today, 2pm'), 'end' => strtotime('today, 2:45pm')); $orange = array('start' => strtotime('today, 1:30pm'), 'end' => strtotime('today, 4pm')); array_walk($red, 'show_date'); array_walk($orange, 'show_date'); if (($red['start'] <= $orange['end']) && ($red['end'] >= $orange['start'])) { echo 'Conflict handling'; }
Я предполагаю, что у вас есть проблема с изменением часового пояса.
Если у вас есть два диапазона [b1, e1]
и [b2, e2]
(где уже установлено, что b1 < e1
и b2 < e2
), то перекрытие обнаруживается следующим логическим выражением
not (e2 < b1 or e1 < b2)
которые можно переписать как
e2 >= b1 and e1 >= b2
В вашем синтаксисе, который был бы
if(($orange['end'] >= $red['start']) && ($red['end'] >= $orange['start'])) { //Conflict handling }
Т.е. вы поняли правильно. Почему вы утверждаете: «Работая по номерам логически, я понимаю, почему утверждение выше не работает». мне непонятно. Что именно не удается? (И я не знаю, почему все придумывают смехотворно «overengineered» чеки, с более чем двумя сравнениями.)
Конечно, вам нужно решить, будут ли касательные диапазоны считаться перекрывающимися и соответственно регулировать строгость сравнений.
PS Диапазоны выборки, которые вы предоставили в своем редактировании, не перекрываются, и ваше сравнение правильно распознает его как неконфликтную ситуацию. Т.е. все работает так, как должно. Где вы видите проблему?
Вам нужно проверить, есть ли у вас задача «КРАСНАЯ», которая начинается ИЛИ заканчивается между началом и концом задачи «ОРАНЖЕВЫЙ». Таким образом, вы должны обнаружить, что каждая задача ORANGE перекрывает задачу «RED».
if((($red['start'] <= $orange['end']) && ($red['start'] >= $orange['start'])) || (($red['end'] <= $orange['end']) && ($red['end'] >= $orange['start'])) ) { //Conflict handling }
EDIT: как сказал AndreyT, это своего рода перебор, и вы можете сделать лучше с меньшим количеством проверки
if ((($red['start'] <= $orange['end']) && ($red['start'] >= $orange['start'])) || (($red['end'] <= $orange['end']) && ($red['end'] >= $orange['start'])) || (($red['start'] >= $orange['start']) && ($red['end'] >= $orange['end'])) ) { // conflict happens if Red starts sometime between Orange start and end // or if Red ends sometime between Orange start and end // or if Red starts before Orange starts and ends after Orange ends }