PHP将两个单独的冲突日期范围组合为唯一对 [英] PHP combine two seperate conflicting date ranges into unique pairs

查看:69
本文介绍了PHP将两个单独的冲突日期范围组合为唯一对的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

设置一:


  1. 2014-04-05至2014-06-27

  2. 2014-06-28至2014-10-19

设置两个:


  1. 2014-04-05至2014-05-02

  2. 2014-05-03至2014-05-31

  3. 2014-06-01至2014-10-19

我需要输出的是:


  1. 2014-04-05至2014-05-02

  2. 2014-05-03至2014-05-31

  3. 2014-06-01至2014-06-27

  4. 2014-06-28至2014-10-19

  1. 2014-04-05 To 2014-05-02
  2. 2014-05-03 To 2014-05-31
  3. 2014-06-01 To 2014-06-27
  4. 2014-06-28 To 2014-10-19

我试图使用一个函数来检查重叠,例如:

I attempted to use a function to check for overlaps as such:

!($lhs['RecordOnset'] > $rhs['RecordOffset'] || $lhs['RecordOffset'] < $rhs['RecordOnset'])

并使用for循环检查重叠:

And used a for loop to check for the overlap:

for($i = 1; $i < sizeof($arr1); $i++) {
    for($j = 1; $j < sizeof($arr2); $j++) {
        $record = $arr1[$i];
        if($result = $this->intersects($arr1[$i], $arr2[$j])) {
            // $result;
        }
    }
}

我要解决的问题当我打破日期范围时,它不会检查循环时创建的新范围。我没有与此结合使用SQL的能力,因此我必须提出一种编程解决方案。我尝试了几种不同的方法,包括一些foreach循环。

The issue that I'm having is when I break a date range out, it doesn't check the new range that was created when looping. I do not have the ability to use SQL with this so I must come up with a programmatic solution. I've tried several different methods including some foreach loops.

数据以日期格式接收,如数组所示:

The data is received in a date format as show in an array like such:

$arr1 = array(array('start'=>'04/05/2014', 'end'=> '2014-06-27'), array('start'=>'2014-06-28', 'end'=> '2014-10-19'));

$arr2 = array(array('start'=>'04/05/2014', 'end'=> '2014-05-02'), array('start'=>'2014-05-03', 'end'=> '2014-05-31'),array('start'=>'2014-06-01', 'end'=> '2014-10-19'));

第二对将是一个单独的数组,因为它可能具有相同的键。

The second pair would be a separate array, since it may have the same keys.

对此非常感谢。使用PHP的日期范围在线资源非常有限。

Any guidance or help with this is greatly appreciated. Date ranges with PHP has very limited resource online.

推荐答案

用法: $ output = mergeRanges($ input );

此方法最初旨在合并数字范围内的任何种类,包括的时间戳并支持任何种类的重叠。它在输入中包含一组对象,其中包含可自定义的从和到键。

This method is originally designed to merge any kind on numeric ranges, timestamps included and supports any kind of overlaps. It takes an array of objects in input, containing "from" and "to" keys which is customizable.


/**
 * @param        $ranges
 * @param string $keyFrom
 * @param string $keyTo
 *
 * @return array
 */
function mergeRanges($ranges, $keyFrom = 'from', $keyTo = 'to')
{
    // Split from / to values.
    $arrayFrom = [];
    $arrayTo   = [];
    foreach ($ranges as $date)
    {
        $arrayFrom[] = $date->$keyFrom;
        $arrayTo[]   = $date->$keyTo;
    }

    // Sort ASC.
    natsort($arrayFrom);
    natsort($arrayTo);

    $ranges = [];
    // Iterate over start dates.
    foreach ($arrayFrom as $indexFrom => $from)
    {
        // Get previous entry.
        $previousEntry = end($ranges);
        // Find associated default "to" value to "from" one.
        $to = $arrayTo[$indexFrom];

        // If we have a previous entry and "to" is greater than
        // current "from" value.
        if (isset($previousEntry->to) && $from < $previousEntry->to + 1)
        {
            // Do nothing if this range is completely covered
            // by the previous one.
            if ($to > $previousEntry->to)
            {
                // We just change te "to" value of previous range,
                // so we don't create a new entry.
                $previousEntry->to = $to;
            }
        }
        else
        {
            // Create a new range entry.
            $ranges[] = (object) [
                $keyFrom => $from,
                $keyTo   => $to,
            ];
        }
    }

    return $ranges;
}

示例:

$input = [
    // One day.
    (object) [
        'title' => 'One day.',
        'from'  => 1560816000,
        'to'    => 1560902399,
    ],
    // Same day, inner period
    (object) [
        'title' => 'Same day, inner period',
        'from'  => 1560816000 + 1000,
        'to'    => 1560902399 - 1000,
    ],
    // Just before midnight
    (object) [
        'title' => 'Just before midnight',
        'from'  => 1560816000 - 1000,
        'to'    => 1560816000 + 1000,
    ],
    // Just after midnight
    (object) [
        'title' => 'Just after midnight',
        'from'  => 1560902399 - 1000,
        'to'    => 1560902399 + 1000,
    ],
    // Other period before
    (object) [
        'title' => 'Other period before',
        'from'  => 1560902399 - 100000,
        'to'    => 1560902399 - 100000 + 5000,
    ],
    // Other period after
    (object) [
        'title' => 'Other period after',
        'from'  => 1560816000 + 100000,
        'to'    => 1560902399 + 100000 + 5000,
    ],
];

结果:

Array
(
    [0] => Array
        (
            [from] => 2019-06-17 22:13:19
            [to] => 2019-06-17 23:36:39
        )

    [1] => Array
        (
            [from] => 2019-06-18 01:43:20
            [to] => 2019-06-19 02:16:39
        )

    [2] => Array
        (
            [from] => 2019-06-19 05:46:40
            [to] => 2019-06-20 07:09:59
        )

)

这篇关于PHP将两个单独的冲突日期范围组合为唯一对的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆