2017-09-21 199 views
0

我想知道如何获取与其他日期时间范围重叠的日期时间范围。 特殊性在于日期范围可以有时间范围连续两天重叠。PHP:选择重叠的日期时间范围与时间范围重叠的日期

例如,我有一个经常性预订01/01和02/01从20:00开始,第二天在02:00结束。

第一天:

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

第二天:

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

现在我想知道如何得到保留重叠的预订。

注:所有预订可以有或没有时间范围重叠的一天。

例如,从PHP的角度来看,我有以下保留: 日期和时间在这里表示为字符串的可读性。实际上他们是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') 
    ), 
    ), 
    ... 
); 

谢谢!

+0

你有什么尝试吗? – ishegg

+0

@ishegg是的,我尝试通过'startA startB'来比较预订每一天的每个时间范围和其他所有预定的每个时间范围。但不确定是否没有更好的解决方案。 – Tsounabe

回答

1

使用对象来使生活更轻松

首先,你真的应该简化结构。如果你真的有日期时间无处不在,然后保留看起来应该更像:

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

构建您的预约这种方式将允许一些非常简单的解决您的问题,如创建RecurringReservation它可以产生的Reservations一个数组给定的日期范围。或者一个Reservation->isToday()方法可以检查$start$stop属性的情况下,它包装午夜。

对于你问然而问题:

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 

编辑:我只是意识到你想重叠保留数组:

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 

最后一编,使用发电机,用于创建结果的列表。

Generators很棒(没有误用时)。当您需要结果列表时,它们提供非常高的性能。他们唯一能抓到的就是你必须把他们的结果直接传递给一个循环来获得好处。

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

谢谢!这确实是一个有趣的方法,除了RecurrentReservation,我已经有了。 – Tsounabe

-1

你想测试一个约会开始是在另一个约会开始和结束之间,然后相同的约会结束。如果两者都是真的,你有重叠。

+0

是的,我已经知道,但我想更详细的答案。 – Tsounabe