Как рассчитать диапазон дат между несколькими датами, которые перекрываются

У меня много дат, которые мне нужно проверить.

Например:

1 - Start: 1387267200, End: 1387274400
2 - Start: 1387270800, End: 1387275000 
3 - Start: 1387250200, End: 1387273000 
4 - Start: 1387285200, End: 1387288800

Что мне нужно, чтобы рассчитать foreach перекрывает минимальную дату начала и максимальную дату окончания.

Для примера выше, что алгоритм должен дать в выводе:

Start1: 1387250200 -> End1: 1387275000.
Start2: 1387285200 -> End2: 1387288800.

Как мне это сделать?

Спасибо!

2 ответа

Решение

Этот скрипт ищет перекрывающиеся интервалы и получает новые с минимальной датой начала и максимальной датой окончания:

// Input
$intervals = array(
    array(1387267200, 1387274400),
    array(1387270800, 1387275000),
    array(1387250200, 1387273000),
    array(1387285200, 1387288800),
);
// Overlapped intervals
$overlapped = array();
foreach ($intervals as $i => $a) {
    $group = [$a];
    foreach ($intervals as $j => $b) {
        if (
            $i !== $j && (($a[0] <= $b[0] && $a[1] >= $b[0])
                || ($a[0] <= $b[1] && $a[0] >= $b[0]))
        ) {
            $group[] = $b;
        }
    }
    sort($group);
    $overlapped[] = $group;
}
// Multidimensional array_unique()
$overlapped = array_map('unserialize',
    array_unique(array_map('serialize', $overlapped))
);
// Output
$output = array();
// Get min/max dates for each overlapped group
foreach ($overlapped as $group) {
    $min = null;
    $max = null;
    foreach ($group as $interval) {
        if ($min === null || $interval[0] < $min) {
            $min = $interval[0];
        }
        if ($max === null || $interval[1] > $max) {
            $max = $interval[1];
        }
    }
    $output[] = array($min, $max);
}
print_r($output);

Выход:

Array
(
    [0] => Array
        (
            [0] => 1387250200
            [1] => 1387275000
        )

    [1] => Array
        (
            [0] => 1387285200
            [1] => 1387288800
        )

)

Сортировать все время начала и окончания в массиве.

  1. Итерация по массиву.
  2. Задавать i = 0; а также count = 0; (количество отслеживает количество активных интервалов)
  3. Когда вы встречаете время начала, запишите его как время начала i'th перекрытия. Кроме того, увеличить счетчик count,
  4. Когда вы столкнетесь с временем окончания, уменьшите count, Если count становится равным нулю, отметьте это как время окончания ith интервал и приращение i,
Другие вопросы по тегам