从多个时间段创建连续时间线

Hey stackoverflow community,

I'm currently trying to archive an continuous timeline from an array of time periods. My input array looks like this:

$array = array(
0 => array(
    'from' => '2019-01-01 00:00:00',
    'to' => '2019-03-31 00:00:00'
),
1 => array(
    'from' => '2019-02-04 00:00:00',
    'to' => '2019-03-15 00:00:00'
));

And the result I'm looking for, is this:

$array = array(
0 => array(
    'from' => '2019-01-01 00:00:00',
    'to' => '2019-02-03 23:59:59'
),
1 => array(
    'from' => '2019-02-04 00:00:00',
    'to' => '2019-03-14 23:59:59'
),
2 => array(
    'from' => '2019-03-15 00:00:00',
    'to' => '2019-03-31 00:00:00'
));

As hard as I'm trying, I'm unable to find a proper solution. Has anyone an idea how to solve this in PHP?

Simply convert all times into Unix timestamps, put them into a simple array, sort and then convert them back to datetimes by constructing the desired array:

<?php
$array = array(
    0 => array(
        'from' => '2019-01-01 00:00:00',
        'to' => '2019-03-31 00:00:00'
    ),
    1 => array(
        'from' => '2019-02-04 00:00:00',
        'to' => '2019-03-15 00:00:00'
    ));

$unixTS = array();
foreach ($array as $arr => $times) {
    foreach ($times as $str => $time) {
        $unixTS[] = strtotime($time);
    }
}

sort($unixTS);

$newArray = array();
for ($i = 0; $i < count($unixTS); $i++) {
    if ($i < count($unixTS) - 1) {
        if ($i + 2 >= count($unixTS))
            $newArray[] = array('from' => date("Y-m-d H:i:s", $unixTS[$i]), 'to' => date("Y-m-d H:i:s", $unixTS[$i + 1]));
        else
            $newArray[] = array('from' => date("Y-m-d H:i:s", $unixTS[$i]), 'to' => date("Y-m-d H:i:s", $unixTS[$i + 1] - 1));
    }
}

print_r($newArray);

Output:

Array
(
[0] => Array
    (
        [from] => 2019-01-01 00:00:00
        [to] => 2019-02-03 23:59:59
    )

[1] => Array
    (
        [from] => 2019-02-04 00:00:00
        [to] => 2019-03-14 23:59:59
    )

[2] => Array
    (
        [from] => 2019-03-15 00:00:00
        [to] => 2019-03-31 00:00:00
    )
)

Probably playing with $i index is not the most elegant way, but you can get the concept and improve your code if needed.

I think a naive for-in-for solution should work.

  • You take the smallest(min) date in the arrays, and put in the newArray
  • then go on to find the next min in the oldArray which is bigger than the last element in the newArray
  • subtract a day from it and insert it in the newArray
  • put the date you found at step 2 as the next element
  • repeat from step 2 until no new min is found (or until the oldArray is empty if you choose to remove the elements in the oldArray)