이 재귀 함수는 가능한 한 많이 결합 될 때까지 겹치는 범위를 결합하여 범위 배열을 통과합니다. 결과가 둘 이상의 범위 인 경우 간격이 있습니다. 나는 또한 도우미 함수를 사용하여 겹쳐진 부분을 더 깔끔하고 쉽게 찾을 수있게했으며, 귀하의 날짜가 'Y-m-d'
인 것으로 가정합니다.
<?php
// First, here's how to use it. If we can't combine all the ranges, and the
// final combined range doesn't reach back 5 years or to the present,
// we have a gap.
$mergedRanges = combineRanges($myArray);
if (count($mergedRanges) > 1
|| $mergedRanges[0]['from'] > date('Y-m-d', time() - 157680000) // 5 years ago
|| $mergedRanges[0]['to'] < date('Y-m-d')) // present
echo 'Gaps found';
/**
* Recursive function to combine ranges.
*
* @param array $ranges
* @return array Array of combined ranges (has only 1 element if no gaps)
*/
function combineRanges(array $ranges)
{
$mergedRanges = array();
$usedKeys = array();
// Nested foreach compares each unique pair of ranges for overlap.
// If the a range has already been accounted for, it can be skipped.
foreach ($ranges as $k1 => $range1) {
if (!in_array($k1, $usedKeys)) {
foreach ($ranges as $k2 => $range2) {
if (!in_array($k1, $usedKeys) && $k1 > $k2) {
// If ranges overlap, combine them and make a note that
// they've already been included
if (rangesOverlap($range1, $range2)) {
$newRange = array(
'from' => min($range1['from'], $range2['from']),
'to' => max($range1['to'], $range2['to'])
);
// It's possible the resulting range could already
// be accounted for by a different combo of ranges,
// so check first
if (!in_array($newRange, $mergedRanges))
$mergedRanges[] = $newRange;
$usedKeys[] = $k1;
$usedKeys[] = $k2;
// Otherwise, add the 2nd range to $mergedRanges
} elseif (!in_array($k2, $usedKeys)) {
$mergedRanges[] = $range2;
$usedKeys[] = $k2;
}
// If $range1 didn't have any overlaps, add it here
if (!in_array($k1, $usedKeys)) {
$mergedRanges[] = $range1;
$usedKeys[] = $k1;
}
}
}
}
}
// If $ranges and $mergedRanges have the same # of elements,
// or if $ranges only had 1 element to begin with,
// that means we couldn't merge any more. Otherwise, recurse!
if (count($ranges) == 1)
return $ranges;
return count($mergedRanges) == 1 || (count($ranges) == count($mergedRanges))
? $mergedRanges
: combineRanges($mergedRanges);
}
/**
* Helper function to see if 2 ranges overlap.
*
* @param array $range1
* @param array $range2
* @return boolean
*/
function rangesOverlap(array $range1, array $range2)
{
// Find the day before each range in order to combine ranges
// that don't overlap but are right next to each other.
$overlap = false;
$range1Before = date('Y-m-d', strtotime('-1 day', strtotime($range1['from'])));
$range2Before = date('Y-m-d', strtotime('-1 day', strtotime($range2['from'])));
// Account for when $range1 is first or when $range 2 is first
if ($range1['from'] <= $range2['from'] && $range1['to'] >= $range2Before
|| $range2['from'] <= $range1['from'] && $range2['to'] >= $range1Before)
$overlap = true;
return $overlap;
}
SQL 솔루션을 원할 경우 데이터가 제공되는 테이블 구조에 대한 추가 정보를 제공해야합니다. 샘플 데이터는 항상 도움이됩니다. –
@ GordonLinoff 나는 그것이 도움이되었을 것 인 방법을 볼 수있다. .. 미안 2am이었다! – SLV