Question

Je suis en train d'écrire un calendrier en PHP. Compte tenu de la semaine, je veux que mes événements à la liste comme iCal, où les événements simultanés réduit la largeur de la taille moitié.

J'ai un temps extrêmement mal à comprendre celui-ci dehors, donc je l'espère, vous pouvez me aider. Ce que je veux est que si un événement est chevauchant, il devrait mettre [split] => true sur les deux tableaux d'événements - ou quelque chose dans ce sens (lire: Je ne suis pas sûr que ce soit la solution la plus efficace). Ensuite, je peux vérifier split == true dans la boucle foreach qui imprime les événements.

Voici un exemple de matrice contenant deux événements simultanés:

$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);

Comment voulez-vous résoudre cette question?

Était-ce utile?

La solution

J'ai dû faire face à des problèmes de collision de date alot ces derniers temps, et le meilleur que je suis en mesure de trouver est:

date1.start date2.start = collision

Cette formule simple représentera toutes les situations suivantes:

--same for all situations:
date1.start = 1/1/2009
date1.end = 1/10/2009

--Start date is in first dates range:
date2.start = 1/9/2009
date2.end = 2/10/2009

--End date is in first dates range:
date2.start = 12/10/2008
date2.end = 1/3/2009

--Start & End date is inside first dates range:
date2.start = 1/2/2009
date2.end = 1/3/2009

--First date is inside of second dates range:
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;
}

D'après ce commentaire est probablement la solution que vous cherchez: Notez que cette solution ne soit pas très optimisé, et ne doit être utilisé pour déterminer une meilleure solution. code Ne faites jamais confiance à partir du Web.

$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;
}

* code n'a pas été testé

Autres conseils

J'ai posté la question de savoir si trois événements se chevauchent, ce qui conduit à une meilleure solution. Ne mettez pas votre interface graphique et vos données dans la même structure. Sauvegardez vos données, puis comprendre comment l'afficher.

Je retourneraient votre problème. Carte des événements sur un tableau représentant la semaine que vous souhaitez afficher:

$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;
    }
  }
}

}

où toThisWeek () est une fonction telle que

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

$ eventCollisions vous avez le nombre maximum de collision se produire sur un événement pour tous les événements qui se produisent au cours de la semaine, vous devez afficher. Maintenant, vous pouvez utiliser les valeurs dans ce tableau pour remplir la division sur le terrain dans les événements $ sous-tableau:

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

Ou tout simplement utiliser les valeurs dans eventCollisions $ "OnDemand"

Voici le travail, le code modifié en fonction de la réponse de Rob:

// 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;
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top