Intereting Posts
Как настроить php для включения pdo и включить mysqli в CentOS? Как попытаться поймать в symfony Мой сервер был взломан закодированным кодом. я не мог узнать, в чем цель этого кода? Пожалуйста, помогите мне Вставка нескольких элементов в один ID MySQL из флажка ввода PHP-формы Все значения = 's' в таблице в ошибке PHP Предупреждение: mysqli_stmt :: bind_param (): Число элементов в строке определения типа не совпадает с числом переменных связывания 11 Lumen make: команда Paypal Скрытые переменные не работают Как stripslashes все элементы массива сразу? PHP: заполнение массива с именами следующих 12 месяцев Класс «Symfony \ Component \ Form \ Form» не был найден в цепочках имен, заданных цепочкой во время представления формы Как избежать повторного обновления страницы на привязке (<a> </a>)? PHP и mysqli: таблица HTML из базы данных Как динамически изменять переменные в .env-файле в Laravel? Не удалось подключиться к серверу PostgreSQL

Календарь, смещение перекрывающихся событий

Я пытаюсь написать календарь в PHP. В режиме недели я хочу, чтобы мои события были перечислены как iCal, где одновременные события уменьшают их ширину до половины размера.

Мне очень сложно понять, что это такое, поэтому я надеюсь, что вы можете мне помочь. Я хочу, чтобы, если одно событие перекрывает другое, оно должно установить [split] => true на обоих массивах событий – или что-то в этом направлении (читайте: я не уверен, является ли это наиболее эффективным решением). Затем я могу проверить split == true в цикле foreach, который печатает события.

Вот пример массива, содержащий два одновременных события:

 $events = array( array( "id" => 21, "start" => 1242219600, "end" => 1242237600, "title" => "foo", "split" => false ), array( "id" => 22, "start" => 1242223200, "end" => 1242234000, "title" => "foo", "split" => false ) ); $events = someFunctionToOffsetEvents($events); 

Как бы вы решили этот?

В последнее время мне приходилось сталкиваться с проблемами столкновения с датами, и лучшее, что я смог придумать, это:

date1.start <date2.end и date1.end> date2.start = collision

Эта простая формула будет учитывать все следующие ситуации:

 - для всех ситуаций:
 date1.start = 1/1/2009
 date1.end = 1/10/2009

 - Дата начала в первом диапазоне дат:
 date2.start = 1/9/2009
 date2.end = 2/10/2009

 - Дата указана в первом диапазоне дат:
 date2.start = 12/10/2008
 date2.end = 1/3/2009

 - Дата начала и окончания внутри первого диапазона дат:
 date2.start = 1/2/2009
 date2.end = 1/3/2009

 - Первая дата находится во втором диапазоне дат:
 date2.start = 12/1/2008
 date2.end = 2/1/2009
 $date1 = array('start' => '2009-01-05', 'end' => '2009-01-10'); $date2 = array('start' => '2009-01-01', 'end' => '2009-01-04'); // end inside one $date3 = array('start' => '2009-01-04', 'end' => '2009-01-15'); // start inside one $date4 = array('start' => '2009-01-01', 'end' => '2009-01-15'); // one inside me $date5 = array('start' => '2009-01-04', 'end' => '2009-01-05'); // inside one function datesCollide($date1, $date2) { $start1TS = strtotime($date1['start']); $end1TS = strtotime($date1['end']); $start2TS = strtotime($date2['start']); $end2TS = strtotime($date2['end']); if ($start1TS <= $end2TS && $end1TS >= $start2) { return true; } return false; } 

На основе вашего комментария это, вероятно, решение, которое вы ищете: обратите внимание, что это решение не очень оптимизировано и должно использоваться только для определения лучшего решения. Никогда не доверяйте коду из Интернета.

 $events = array( array( "id" => 21, "start" => 1242219600, "end" => 1242237600, "title" => "foo", "split" => false ), array( "id" => 22, "start" => 1242223200, "end" => 1242234000, "title" => "foo", "split" => false ) ); foreach ($events as $key => $event) { $events[$key]->split = dateCollisionCheck($event, $events); } function dateCollisionCheck(&$event, &$eventList) { foreach ($eventList as $checkEvent) { if ($event->id != $checkEvent->id) { if ($event->start <= $checkEvent->end && $event->end >= $checkEvent->start) { return true; // return as soon as we know there is a collision } } } return false; } 

* Код не был протестирован

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

Я бы отменил вашу проблему. Сопоставьте события в массиве, представляющие неделю, которую вы хотите отобразить:

 $weekdayEvents=array(); foreach ($events as $event) { $day=toThisWeek($event['start'], $firstweekday), $lastDay=toThisWeek($event['end'], $firstweekday); while ($day<=$lastDay) { $weekdayEvents[$day++][]=$event['id']; } } // now you have an array of array filled with ids $eventCollisions=array(); foreach($weekdaysEvents as $activeDay) { $eventsOnDay = count($activeDay); foreach($activeDay as $eventID) { if ($eventCollisions[$eventID]<$eventsOnDay) { $eventCollisions[$eventID]=$eventsOnDay; } } } с $weekdayEvents=array(); foreach ($events as $event) { $day=toThisWeek($event['start'], $firstweekday), $lastDay=toThisWeek($event['end'], $firstweekday); while ($day<=$lastDay) { $weekdayEvents[$day++][]=$event['id']; } } // now you have an array of array filled with ids $eventCollisions=array(); foreach($weekdaysEvents as $activeDay) { $eventsOnDay = count($activeDay); foreach($activeDay as $eventID) { if ($eventCollisions[$eventID]<$eventsOnDay) { $eventCollisions[$eventID]=$eventsOnDay; } } } 

}

где toThisWeek () – это функция, подобная

 function toThisWeek($dayTimestamp, $firstDayOfWeekTimestamp) { $dayOfWeek = unixtojd($firsDayOfWeekTimestamp) - unixtojd($dayTimestamp); if($dayOfWeek<0) return 0; if($dayOfWeek>6) return 6; return $dayOfWeek; } 

Теперь в $ eventCollisions у вас есть максимальное количество столкновений в событии для каждого события, происходящего в течение недели, которую вы должны отображать. Теперь вы можете использовать значения в этом массиве для заполнения разделения полей в субаре $ events:

 foreach ($events as $event) { $event['split']=$eventCollisions[$event['id']]-1; } 

Или просто используйте значения в $ eventCollisions "ondemand"

Вот рабочий, измененный код, основанный на ответе Роба:

 // this is in my getEvents function if(is_array($events)) { foreach ($events as $key => $event) { $events[$key]['collides'] = $this->dateCollisionCheck($event, $events); } } //this is another function added to calendar.class.php function dateCollisionCheck(&$event, &$eventList) { foreach ($eventList as $checkEvent) { if ($event['id'] != $checkEvent['id']) { if ($event['start'] <= $checkEvent['end'] && $event['end'] >= $checkEvent['start']) { return true; } } } return false; }