我想知道如何获取与其他日期时间范围重叠的日期时间范围。 特殊之处在于日期范围的时间范围可以连续两天重叠。
例如,我有一个经常性的预订 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的角度来看,我有以下保留意见: 为了便于阅读,日期和时间在此处表示为字符串。实际上,它们是日期时间。
//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')
),
),
...
);
谢谢!
使用对象让生活更轻松
首先,你真的应该简化你的结构。如果你真的到处都有日期时间,那么预订应该看起来更像:
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;
}
}
以这种方式构建您的预订将为您的问题提供一些非常简单的解决方案,例如创建可以为给定日期范围生成一系列Reservations
的RecurringReservation
。或者一种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
最后一个附录,使用生成器创建结果列表。
生成器很棒(当没有滥用时)。当您需要结果列表时,它们提供非常高的性能。他们唯一的问题是,你必须将他们的结果直接传递到一个循环中才能获得好处。
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
}
您要测试约会开始是否在另一个约会开始和结束之间,然后对于约会结束也是如此。 如果任一为真,则存在重叠。