2014-12-22 2 views
0
function checkDateOverlap($ranges) { 
    $res = $ranges[0]; 
    $countRanges = count($ranges); 

    for ($i = 0; $i < $countRanges; $i++) { 

     $r1s = $res['start']; 
     $r1e = $res['end']; 

     $r2s = $ranges[$i]['start']; 
     $r2e = $ranges[$i]['end']; 

     if ($r1s >= $r2s && $r1s <= $r2e || $r1e >= $r2s && $r1e <= $r2e || $r2s >= $r1s && $r2s <= $r1e || $r2e >= $r1s && $r2e <= $r1e) { 
      $res = array(
       'start' => $r1s > $r2s ? $r1s : $r2s, 
       'end' => $r1e < $r2e ? $r1e : $r2e 
      ); 
     } else 
      return false; 
    } 
    return $res; 
} 
// example of returned dates that overlap 
$ranges = array(
    array('start' => '2014-01-01', 'end' => '2014-01-04'), 
    array('start' => '2014-01-05', 'end' => '2014-01-10'), 
    array('start' => '2014-01-04', 'end' => '2014-01-07') 
); 
//example of failure 
$ranges2 = array(
     array('start' => '2014-01-01', 'end' => '2014-01-04'), 
     array('start' => '2014-01-05', 'end' => '2014-01-10'), 
     array('start' => '2014-01-11', 'end' => '2014-01-17') 
    ); 

var_dump(checkDateOverlap($ranges)); 

다음은 날짜 범위의 교차를 확인하려고 시도한 것입니다. "ranges1"배열에서이 예제는 중복되는 날짜를가집니다. 날짜를 반환해야합니다. 배열 $ ranges2에서 교차하는 날짜가 없어야합니다.중복의 날짜 범위 (시작일 및 종료일) 확인

이상한 일은 시작일과 종료일이 똑같을 수 있으므로 단 하루 만 입력 할 수 있습니다. 나는 많은 것을 시도해 왔으며, 나는 혼란 스럽다.

다른 루프가 있어야한다고 생각하지만 관계없이 성공하지 못합니다.

<?php 

//이 방법으로 범위를 통과하고 공통 intersecion가있는 경우는 // 또는 거짓

function checkDateOverlap($ranges){ 
    $res = $ranges[0]; 
    $countRanges = count($ranges); 
    for ($i = 0; $i < count($countRanges); $i++) { 
     for($j = $i+1; $j < count($countRanges); $j++) { 
      $r1s = $res['start']; 
      $r1e = $res['end']; 

      $r2s = $ranges[$i]['start']; 
      $r2e = $ranges[$i]['end']; 

      if (($r1s >= $r2e && $r2s <= $r1e)) { 

       $res[] = array(
        'start' => $r1s > $r2s ? $r1s : $r2s, 
        'end' => $r1e < $r2e ? $r1e : $r2e 
       ); 

      } else 
       return false; 
     } 
    } 
    return $res; 
} 

// example 
$ranges = array(
    array('start' => '2014-01-04', 'end' => '2014-01-05'), 
    array('start' => '2014-01-06', 'end' => '2014-01-10'), 
    array('start' => '2014-01-11', 'end' => '2014-01-13') 
); 

echo "<pre>"; 

var_dump(checkDateOverlap($ranges)); 
echo "</pre>"; 

모든 IT를 반환합니다 여기

다른 내가 있었다 이동했다 조언 크게 감사드립니다.

답변

0
$ranges = array(
     array('start' => new DateTime('2014-01-01'), 'end' => new DateTime('2014-01-05')), 
     array('start' => new DateTime('2014-01-06'), 'end' => new DateTime('2014-01-06')), 
     array('start' => new DateTime('2014-01-07'), 'end' => new DateTime('2014-01-07')), 
    ); 

    function intersects($lhs, $rhs) { 
     // Note that this function allows ranges that "touch", 
     // eg. one pair starts at the exact same time that the other ends. 
     // Adding less "or equal to" will allow same start date 
     return !($lhs['start'] > $rhs['end'] || $lhs['end'] < $rhs['start']); 
    } 

    function checkDates($ranges) { 
     // Comparison loop is of size n•log(n), not doing any redundant comparisons 
     for($i = 0; $i < sizeof($ranges); $i++) { 
      for($j = $i+1; $j < sizeof($ranges); $j++) { 
       if(intersects($ranges[$i], $ranges[$j])) { 
        echo "Date {$i} intersects with date {$j}\n"; 
       } 
      } 
     } 
    } 

    checkDates($ranges); 

나는 희망 같은 솔루션을 찾고 미래에 다른 사람을 돕기 위해 내 작업 코드 샘플을 첨부했습니다. 이것은 교차하는 배열을 인쇄합니다.

0

먼저 usort를 사용하여 날짜를 정렬하면 작업이 훨씬 쉬워집니다. 다음은 많이 최적화 할 수 있지만 단계별로 이해하면 이해하기 쉽습니다.

//The date comparison function, sort on start and then on end 
function cmp($a, $b) 
{ 
    if($a['start']<$b['start']) return -1; 
    if($a['start']>$b['start']) return 1; 
    if($a['end']<$b['end']) return -1; 
    if($a['end']>$b['end']) return 1; 
    return 0; // start=start and end=end 
} 

$ranges = array(
    array('start' => '2014-01-01', 'end' => '2014-01-04'), 
    array('start' => '2014-01-05', 'end' => '2014-01-10'), 
    array('start' => '2014-01-04', 'end' => '2014-01-07') 
); 

usort($ranges, 'cmp'); // Sort the dates 

$output = array(); 
for($i=0; $i<sizeof($ranges); $i++) 
{ 
    $endindex = $i; // The index containing the proper 'end' value 
    for($j=$i+1; $j<sizeof($ranges); $j++) 
    { 
     if($ranges[$endindex]['start'] == $ranges[$j]['start']) // Overlap 
      $endindex = $j; 
     elseif($ranges[$endindex]['end']>=$ranges[$j]['start']) // Overlap 
      $endindex = $j; 
    } 
    $output[] = array('start' => $ranges[$i]['start'], 'end' => $ranges[$endindex]['end']); 
    // Break the rules by hard-setting $i from the for loop - it works great in this case 
    $i = $endindex; 
} 

print_r($output); 

예를 들어 작동합니다. 다른 규칙을 사용해야하는 경우이 코드를 조정할 수 있습니다.

+0

문제는 OP가 행 [0]을 (를) 찾을 데이터로 사용하고 있습니다. 배열을 정렬하면 그 날짜 엔트리를 다른 곳으로 옮길 수 있습니다. 이제 완전히 다른 범위를 검색합니다. –

+0

Marc 입력을 주셔서 감사 드리며이 코드를 테스트하면 문자 그대로 다시 배열이 반복됩니다. –

+0

그는 행 [0]을 찾을 데이터로 사용하고 있다고 생각 하겠지만 질문에서 "행 [0]"또는 "찾을"에 대해서는 아무 것도 볼 수 없습니다. 내가 볼 수있는 것은 중복 된 날짜를 날짜 범위의 배열에서 제거하려고 시도하는 것입니다. 이 코드를 테스트 할 때 :이 코드를 정확히 쓰면, start = 2014-01-1 및 end = 2014-01-10이있는 항목이 하나있는 배열이 생깁니다. 주의 :이 코드는 원래 $ ranges 배열을 변경하지 않습니다. $ output이라는 배열에는 겹치는 부분이없는 모든 날짜 범위가 들어 있습니다. – kainaw

0

다음은 일부 설명입니다.
- '시작'및 '종료'로 구성된 날짜의 유효성을 확인하지 않습니다.
- 왜 날짜를 타임 스탬프로 변환하지 않습니까?
-> 문자열 대신 정수 값을 비교하는 것이 더 쉽고 빠릅니까?

왜 PHP DateTime 및 DateInterval 객체를 사용하지 않습니까?
http://php.net/manual/en/book.datetime.php

+0

안녕하세요! 만약 당신이 실제로 당신의 발언을하는 방법에 대한 몇 가지 코드를 추가하면 이것이 대답이 될 것입니다. :) –

+0

예를 들어 도울 수 있다면 정말 좋을 것 같습니다. 또한 time()으로 변환 할 계획입니다 ... 그러나 이것은 타임 스탬프가 아닌 날짜로 테이블에 저장됩니다. –

관련 문제