2012-05-23 58 views
0

我有一個數組是由想要預留時間塊的人員組織的志願者創建的。我想檢查他們是否在重疊的同一天選擇時間塊。在我的第一個和第三個元素下面的示例數組是重疊的,我需要檢測。任何建議將不勝感激:檢查數組中同一日期的重疊時間嗎?

Array 
(
    [0] => Array 
     (
      [id_pc_time_blocks] => 3 
      [id_pc] => 2 
      [pc_date] => 2012-11-21 
      [pc_time_block] => 9:00 AM-1:00 PM 
      [pc_time_block_max] => 25 
      [pc_time_block_count] => 0 
      [pc_name] => Atlanta 
     ) 

    [1] => Array 
     (
      [id_pc_time_blocks] => 4 
      [id_pc] => 2 
      [pc_date] => 2012-11-21 
      [pc_time_block] => 1:00 PM-5:00 PM 
      [pc_time_block_max] => 25 
      [pc_time_block_count] => 10 
      [pc_name] => Atlanta 
     ) 

    [2] => Array 
     (
      [id_pc_time_blocks] => 6 
      [id_pc] => 2 
      [pc_date] => 2012-11-21 
      [pc_time_block] => 10:00 AM-2:00 PM 
      [pc_time_block_max] => 25 
      [pc_time_block_count] => 0 
      [pc_name] => Atlanta 
     ) 

     [3] => Array 
     (
      [id_pc_time_blocks] => 6 
      [id_pc] => 2 
      [pc_date] => 2012-11-23 
      [pc_time_block] => 10:00 AM-2:00 PM 
      [pc_time_block_max] => 25 
      [pc_time_block_count] => 0 
      [pc_name] => Atlanta 
     ) 

     [4] => Array 
     (
      [id_pc_time_blocks] => 6 
      [id_pc] => 2 
      [pc_date] => 2012-11-23 
      [pc_time_block] => 3:00 AM-6:00 PM 
      [pc_time_block_max] => 25 
      [pc_time_block_count] => 0 
      [pc_name] => Atlanta 
     ) 

) 
+0

對不起,哪些元素重疊,請清除 – RSM

+0

我的數組沒有正確複製。元素0和2的pc_time_block在10:00 am重疊 – champton

回答

0

這是我的解決方案檢查每個日期的重疊時間。唯一的問題是,這是針對我的特定情況,並沒有考慮重疊的年份,因爲我沒有這個應用程序的需要。

這是我的工作例如:

$dateIdx = 0; 
    foreach($timeblocks_array as $obj) { 
      $timeblocks_array[$dateIdx]["intDay"] = idate("z",strtotime($obj["pc_date"])); 
      $timeblocks_array[$dateIdx]["intStart"] = intval($obj["start_time"]); 
      $timeblocks_array[$dateIdx]["intEnd"] = intval($obj["end_time"]); 
      $mindates[] = idate("z",strtotime($obj["pc_date"])); 
      $dateIdx++; 
    } 
    $minDateSingle = min($mindates); 
    $maxDateSingle = max($mindates); 

    $currentDate = $minDateSingle; 
    $dateIdx = 0; 
    while ($currentDate <= $maxDateSingle) { 
      $hrIndex = 0; 
      while ($hrIndex < 24) { 
        $matrixArray[$dateIdx][$hrIndex]["count"] = 0; 
        $matrixArray[$dateIdx][$hrIndex]["intDay"] = $currentDate; 
        $hrIndex++;   
      } 
      // calculate counts: 
      $hourIdx = 0; 
      foreach($matrixArray[$dateIdx] as $hour){ 
        foreach($timeblocks_array as $block) { 
         if ($hour["intDay"] == $block["intDay"]) { 
           if ($hourIdx >= $block["intStart"] && $hourIdx < $block["intEnd"]) { 
             $matrixArray[$dateIdx][$hourIdx]["count"] = $matrixArray[$dateIdx][$hourIdx]["count"] + 1; 
             $matrixArray[$dateIdx][$hourIdx]["requests"][] = $block; 
           } 
         } 
        } 
        $hourIdx++; 
      } 
      $dateIdx++; 
      $currentDate = $currentDate + 1; 
    } 

    //loop through the matrix array and timeblocks array to see if they intersect 
    foreach($matrixArray as $day) { 
      $hourIdx = 0; 
      foreach($day as $hour) { 
        if ($hour["count"] > 1) { 
         //echo $hour["intDay"]." - Overlap on Hour $hourIdx\n"; 
         $smarty->assign('overlappingError', 1); 
         $error = 1; 
         foreach($hour["requests"] as $overlapblock) { 
           //echo " --> conflict: ". $overlapblock["pc_date"]." ".$overlapblock["pc_time_block"]." (".$overlapblock["intStart"]." to ".$overlapblock["intEnd"].")\n"; 
         } 
        } else if ($hour["count"] == 1) { 
         // these are valid hours 
        }  
        $hourIdx++; 
      }  
    } 
1

不建議巨大的陣列,但這裏有一個快速的解決方案。你需要打破時間到unix時間戳比較

// Run down each element of the array. (I've called it MyStartArray) 
$numElements = count($MyStartArray); 
for ($i=0; $i<$numElements ; $i++) { 

    // Calculate "Start Time" and "End Time" as Unix time stamps (use mktime function) and store as another items in the array 
    // You can use preg_match or substr to get the values to pump into mktime() below - not writing hte whole thing for you ;) 
    $MyStartArray[$i]['start_time'] = mktime(...); 
    $MyStartArray[$i]['end_time'] = mktime(...); 

    // Now run through all the previous elements to see if a start time is before the end time, or an end time is after the start time. 
    if ($i > 0) { 
     for ($j=0; $j<$i;$j++) { 
      if ($MyStartArray[$i]['start_time'] < $MyStartArray[$j]['end_time'] || 
        $MyStartArray[$j]['end_time'] > $MyStartArray[$j]['start_time']) { 
        echo 'CLASH'; 
      } 
     } 
    } 
} 
+0

您認爲這不會縮放的任何原因?儘管我同意這種做法。需要比較的日期/時間需要以某種日期/時間格式存儲,並且不需要轉換unix時間戳以進行比較。 –

+0

它不會像你有3行一樣擴展,你需要1 + 2 = 3檢查,如果你有5行,它是1 + 2 + 3 + 4 = 10檢查,如果你有100行檢查4950。 1000行不到五十萬。因此,在100到1000行之間會出現你的「我開始注意到」捏點 – Robbie

+0

我看,你正在看O(n²)。夠公平的,那不好。你怎麼設計它是可擴展的? –

0

羅比的回答並沒有爲我工作。我發現在地方去了他的例子只是日期是必要的規則是:

$ I [開始]必須小於並且不等於$ I [停止]

$ I [開始]需要大於並且不等於$ f] [停止]

$ f] [開始]必須小於並且不等於$ f] [停止]

所以我的解決辦法是:

$numElements = count($dates); 

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

    $dates[$i]['start_time'] = strtotime($dates[$i]['start']); 
    $dates[$i]['end_time'] = strtotime($dates[$i]['end']); 

    if ($i > 0) { 

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

      if($dates[$i]['start_time'] >= $dates[$i]['end_time'] || $dates[$i]['start_time'] <= $dates[$j]['end_time'] || $dates[$j]['start_time'] >= $dates[$j]['end_time']) { 
       $this->set_error(['dates_overlap']); 
       $this->dates_overlap = true; 
       break; 
      } 

     } 
    } 

    if(isset($this->dates_overlap)) 
     break; 
}