PHP从重叠事件数组中获取正常运行时间周期

PHP从重叠事件数组中获取正常运行时间周期,php,logic,uptime,Php,Logic,Uptime,解决方案: 我看了这个, 在这个例子中解决了我的问题: 此处的非工作代码示例: 基本上,我有一系列重叠的停机事件,如下所示: $incidents = [ ['start' => '2016-01-05 00:00:00', 'end' => '2016-01-10 23:59:59'], ['start' => '2016-01-07 00:00:00', 'end' => '2016-01-15 23:59:59'], // overlapping

解决方案:

我看了这个,

在这个例子中解决了我的问题:

此处的非工作代码示例:

基本上,我有一系列重叠的停机事件,如下所示:

$incidents = [
  ['start' => '2016-01-05 00:00:00', 'end' => '2016-01-10 23:59:59'],
  ['start' => '2016-01-07 00:00:00', 'end' => '2016-01-15 23:59:59'], // overlapping
  ['start' => '2016-01-12 00:00:00', 'end' => '2016-01-13 23:59:59'], // overlapping
  ['start' => '2016-01-20 00:00:00', 'end' => '2016-01-25 23:59:59'],
  ['start' => '2016-01-23 00:00:00', 'end' => '2016-01-24 23:59:59']  // overlapping
];
从事件数组中,我希望得到以下作为正常运行时间数组的结果

Array
(
    [0] => Array
        (
            [start] => 2016-01-01 00:00:00
            [end] => 2016-01-05 00:00:00
        )

    [1] => Array
        (
            [start] => 2016-01-15 23:59:59
            [end] => 2016-01-20 00:00:00
        )

    [2] => Array
        (
            [start] => 2016-01-25 23:59:59
            [end] => 2016-01-31 23:59:59
        )
)
不幸的是,我的逻辑游戏不够好,无法可靠、高效地完成任务。在实际示例中,我在一个DB中有大约250万行事件

对于使用2 for循环计算正常运行时间,您有什么想法

有没有更有效/更简单的方法


您是否能够完成逻辑以使正常运行时间结果按预期工作?

这样的算法有四个步骤:

$incidents = [
  ['start' => '2016-01-05 00:00:00', 'end' => '2016-01-10 23:59:59'],
  ['start' => '2016-01-07 00:00:00', 'end' => '2016-01-15 23:59:59'], // overlapping
  ['start' => '2016-01-12 00:00:00', 'end' => '2016-01-13 23:59:59'], // overlapping
  ['start' => '2016-01-20 00:00:00', 'end' => '2016-01-25 23:59:59'],
  ['start' => '2016-01-23 00:00:00', 'end' => '2016-01-24 23:59:59']  // overlapping
];
  • 将事件筛选为与报告日期范围重叠的事件
  • 按事件开始对事件进行排序
  • 将所有事件合并到连续块中(
    O(n)
    operation)
  • 通过返回合并事件之间的间隔来反转这些范围(
    O(n)
    operation)
  • 步骤1和2可以在数据库查询中简单处理,例如:

    select    start, end
    from      incidents
    where     start < :reportEnd and
              end   > :reportStart
    order by  start
    
    选择开始、结束
    从事件中
    其中开始<:报告结束和
    结束>:报告开始
    按开始顺序订购
    
    注意一点:如果可能的话,您应该考虑使用DATE时间范围(包含开始,排他性结束)的[开始,结束]格式。例如,当试图计算出
    2016-01-25 00:00:00->2016-01-25 23:59:59
    2016-01-26 00:00:00->2016-01-26 23:59
    相邻时,这将使算法更加简单。