📜  如何检查时间重叠 - PHP (1)

📅  最后修改于: 2023-12-03 14:53:11.468000             🧑  作者: Mango

如何检查时间重叠 - PHP

在很多应用中,需要对时间进行操作和验证,其中一个常见的需求就是检查是否有时间重叠的情况。本文将介绍如何在 PHP 中实现时间重叠的检查。

示例数据结构

为方便起见,我们先给出一个示例的数据结构,假设我们有一个数据库表格 events,其中每一行表示一个活动,有如下列:

  • id:活动的唯一标识符(整数类型);
  • start_time:活动的开始时间(UNIX 时间戳);
  • end_time:活动的结束时间(UNIX 时间戳)。
CREATE TABLE `events` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `start_time` int(11) NOT NULL,
  `end_time` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
实现思路

检查时间重叠可以归结为以下几个步骤:

  1. 排序:将所有活动按开始时间升序排序;
  2. 遍历:遍历排序后的活动列表,对于每一个活动:
    1. 如果它的开始时间晚于前一个活动的结束时间,说明它们没有重叠,可以继续遍历下一个活动;
    2. 如果它的开始时间早于或等于前一个活动的结束时间,说明它们有重叠,直接返回结果。
PHP 代码实现
/**
 * 判断给定的活动是否与已有的活动有时间重叠
 *
 * @param array $eventList 已有的活动列表,每个元素包括 id、start_time、end_time 三个字段
 * @param array $event 要新增的活动,包括 start_time 和 end_time 两个字段
 * @return bool 返回是否存在时间重叠
 */
function isOverlapping(array $eventList, array $event)
{
    // 先将已有的活动按开始时间升序排序
    usort($eventList, function ($a, $b) {
        return $a['start_time'] - $b['start_time'];
    });

    // 遍历已有的活动列表,与要新增的活动比较
    foreach ($eventList as $existingEvent) {
        if ($event['start_time'] > $existingEvent['end_time']) {
            // 当前活动的开始时间晚于前一个活动的结束时间,没有重叠,继续遍历
        } elseif ($event['end_time'] < $existingEvent['start_time']) {
            // 当前活动的结束时间早于后一个活动的开始时间,没有重叠,继续遍历
        } else {
            // 发现重叠,直接返回 true
            return true;
        }
    }

    // 遍历完所有已有的活动,没有发现重叠,返回 false
    return false;
}

我们定义了一个 isOverlapping 函数,它接受一个已有的活动列表和一个待新增的活动,返回是否存在时间重叠。函数内部使用了 PHP 的排序函数 usort 对已有的活动按开始时间排序,并使用一次简单的遍历判断时间是否重叠。如果发现重叠,直接返回 true,不必再继续遍历。

测试样例

以下是一些测试样例,它们分别表示在不同条件下的时间重叠情况:

$eventList = [
    ['id' => 1, 'start_time' => 1609459200, 'end_time' => 1609473600], // 2021-01-01 00:00:00 - 2021-01-01 04:00:00
    ['id' => 2, 'start_time' => 1609466400, 'end_time' => 1609480800], // 2021-01-01 02:00:00 - 2021-01-01 06:00:00(与前一个活动有重叠)
    ['id' => 3, 'start_time' => 1609473600, 'end_time' => 1609488000], // 2021-01-01 04:00:00 - 2021-01-01 08:00:00(与前一个活动有重叠,与后一个活动无重叠)
    ['id' => 4, 'start_time' => 1609495800, 'end_time' => 1609506600], // 2021-01-01 10:50:00 - 2021-01-01 13:10:00(与前一个活动无重叠)
];

$eventToAdd = ['start_time' => 1609462800, 'end_time' => 1609470000]; // 2021-01-01 01:00:00 - 2021-01-01 03:00:00(与已有的活动有重叠)

var_dump(isOverlapping($eventList, $eventToAdd)); // true

$eventToAdd = ['start_time' => 1609488000, 'end_time' => 1609491600]; // 2021-01-01 08:00:00 - 2021-01-01 09:00:00(与已有的活动无重叠)

var_dump(isOverlapping($eventList, $eventToAdd)); // false

我们可以通过调用 isOverlapping 函数,传入不同的测试样例进行验证。在上面的测试样例中,第一次调用 isOverlapping 传入的是一个与已有的活动有时间重叠的活动,第二次调用传入的是一个与已有的活动没有时间重叠的活动。期望的结果是第一次调用返回 true,第二次调用返回 false