检查数组中同一日期的重叠时间?

时间:2012-05-23 13:06:27

标签: php arrays overlap

我有一个阵列,是由那些想要预留时间段来为我们的组织做志愿者的人制作的。我想检查他们是否在重叠的同一天选择了时间块。在我的示例数组中,第一个和第三个元素重叠,我需要检测它。任何建议都将非常感谢:

 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
        )

)

3 个答案:

答案 0 :(得分:1)

不建议用于HUGE阵列,但这是一个快速的解决方案。你需要将unte时间分解为comparisson的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';
            }
        }
    }
}

答案 1 :(得分: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++;
           }     
    }   

答案 2 :(得分:0)

罗比的回答对我不起作用。我发现需要制定的规则仅仅是关于日期的例子:

$ i [start]需要小于且不等于$ i [stop]

$ i [start]需要大于且不等于$ j [stop]

$ j [start]需要小于且不等于$ j [stop]

因此我的解决方案是:

$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;
}