2017-09-21 11 views
0

Je voudrais savoir comment faire coïncider les plages horaires de dates avec d'autres plages de dates. La particularité est qu'une plage de dates peut avoir plage de temps se chevauchant deux jours consécutifs.PHP: Sélection de plages de dates chevauchantes avec chevauchement de plages horaires

Par exemple, j'ai une réservation récurrente les 01/01 et 02/01 commençant à 20h00 et finissant le lendemain à 02h00.

Premier jour:

$start = '2017-01-01 20:00'; 
$end = '2017-01-02 02:00'; 

Deuxième jour:

$start = '2017-01-02 20:00'; 
$end = '2017-01-03 02:00'; 

Maintenant, je voudrais savoir comment obtenir des réserves qui se chevauchent cette réserve.

Remarque: Toutes les réservations peuvent avoir ou non une période de chevauchement. Par exemple, d'un point de vue PHP, j'ai les réserves suivantes: Les dates et les heures sont représentées ici sous forme de chaîne pour la lisibilité. En réalité, ils sont DateTime.

//The reservation 
$reservation= array(
    array(
     'day' => '2017-01-01', 
     'time_range' => array('20:00', '23:59') 
    ), 
    array(
     'day' => '2017-01-02', 
     'time_range' => array('00:00', '02:00') 
    ), 
); 

//Other reservations 
$reservations= array(
    //Reservation doesn't overlap 
    array(
     'day' => '2017-01-01', 
     'time_range' => array('18:00', '19:00') 
    ), 
    //Reservation overlaps 
    array(
     'day' => '2017-01-01', 
     'time_range' => array('21:00', '22:00') 
    ), 
    //Reservation overlaps 
    array(
     array(
     'day' => '2017-01-01', 
     'time_range' => array('23:00', '23:59') 
    ), 
     array(
     'day' => '2017-01-02', 
     'time_range' => array('00:00', '01:00') 
    ), 
    ), 
    ... 
); 

Merci!

+0

Avez-vous essayé quelque chose? – ishegg

+0

@ishegg Oui j'ai essayé de comparer chaque intervalle de temps de chaque jour de la réservation à chaque intervalle de temps de chaque jour de toutes les autres réservations par 'startA startB'. Mais je ne sais pas s'il n'y a pas une meilleure solution. – Tsounabe

Répondre

1

Utilisez des objets pour rendre la vie plus facile

D'abord, vous devriez vraiment simplifier votre structure. Si vraiment vous n'avez DateTimes partout, alors les réservations devraient regarder quelque chose comme:

class Reservation 
{ 
    /** @var DateTime $start */ 
    public $start; 
    /** @var DateTime $stop */ 
    public $stop; 

    public function _construct(DateTime $start, DateTime $stop): void 
    { 
     $this->start = $start; 
     $this->stop = $stop; 
    } 

    public function isOverlapping(Reservation $reservation): bool 
    { 
     if ($reservation->start >= $this->start && $reservation->start <= $this->stop) { 
      // starts during reservation 
      return true; 
     } 

     if ($reservation->stop >= $this->start && $reservation->stop <= $this->stop) { 
      // ends during reservation 
      return true; 
     } 

     if ($reservation->start <= $this->start && $reservation->end >= $this->stop) { 
      // $this is contained by $reservation 
      return true; 
     } 

     return false; 
    } 
} 

Structurer vos réservations ainsi permettra des solutions très simples à votre problème, comme la création d'RecurringReservation qui peut générer un tableau de Reservations pour une plage de dates donnée. Ou une méthode Reservation->isToday() qui pourrait vérifier les propriétés $start et $stop dans les cas où il enveloppe minuit.

Pour le problème que vous demandez cependant:

class Reservation 
{ 

    . . . 

    public function anyOverlap(array $reservations): bool 
    { 
     foreach ($reservations as $checkMe) { 
      if ($this->isOverlapping($checkMe)) { 
       return true; 
      } 
     } 
     return false; 
    } 
} 

$reservation = new Reservation(new DateTime('2017-01-01 20:00'), new DateTime('2017-01-02 02:00')); 

$reservations = [ 
    new Reservation(new DateTime('2017-01-01 18:00'), new DateTime('2017-01-01 19:00')), 
    new Reservation(new DateTime('2017-01-01 21:00'), new DateTime('2017-01-01 22:00')), 
    new Reservation(new DateTime('2017-01-01 23:00'), new DateTime('2017-01-02 01:00')), 
]; 

$reservation->anyOverlap($reservations); // true 

Edit: Je viens de réaliser que vous voulez un tableau des réserves qui se chevauchent:

class Reservation 
{ 

. . . 

public function getOverlapping(array $reservations): array 
    { 
     $result = []; 
     foreach ($reservations as $checkMe) { 
      if ($this->isOverlapping($checkMe)) { 
       $result[] = $checkMe; 
      } 
     } 
     return $result; 
    } 
} 

. . . 

$overlapping = $reservation->getOverlapping($reservations); // array 

Un dernier supplément, utiliser des générateurs pour créer des listes de résultats .

Generators sont impressionnants (lorsqu'ils ne sont pas utilisés à mauvais escient). Ils offrent de très hautes performances lorsque vous avez besoin d'une liste de résultats. Ils sont seulement attraper, c'est que vous devez passer leur résultat directement dans une boucle pour en tirer les avantages.

public function getOverlapping(array $reservations): Generator 
{ 
    foreach ($reservations as $checkMe) { 
     if ($this->isOverlapping($checkMe)) { 
      yield $checkMe; 
     } 
    } 
} 

... 

foreach($reservation->getOverlapping($reservations) as $overlap) { 
    yellAtReceptionistFor($overlap); // ... or whatever 
} 
+1

Merci! C'est en effet une approche intéressante que j'ai déjà à l'exception de RecurrentReservation. – Tsounabe

-1

Vous souhaitez tester un rendez-vous, commencez entre le début et la fin de l'autre rendez-vous, puis le même pour la fin du rendez-vous. Si l'une ou l'autre est vraie, vous avez un chevauchement.

+0

Oui, je l'ai déjà connu, mais je voudrais une réponse plus détaillée. – Tsounabe