如何计算“可用时间段”

时间:2013-08-31 16:54:36

标签: php algorithm

我正在建立一个服务预订系统,并希望在一些预订后获得“可用时间段”列表。

例如,一天有24小时,所以可用时间是

{"begin":"0:00","end":"23:59"}, 

已经有几个预订:[{"begin":"9:30","end":"10:30"},{"begin":"12:30","end":"14:00"}]

我希望得到一份可用时间列表:[{"begin":"0:0","end":"9:30"},{"begin":"10:30",to:"12:30"},{"begin":"14:00","to":"23:59"}]

PHP中是否有可用的工具?或者是否有可以使用的算法?

更新 不可用的时间可能会重叠,因为我正在考虑添加“规则”(每天从10开始,每月的第3天关闭等),例如: [{"begin":0:00,"end":10:00},{"begin":"9:30","end":"10:30"},{"begin":"12:30","end":"14:00"}]

3 个答案:

答案 0 :(得分:3)

这是一个php解决方案:

$busy_slots = array(
                array("begin"=>new DateTime("2013-01-01 09:30"),
                      "end"=>new DateTime("2013-01-01 10:30")) 
                ,array("begin"=>new DateTime("2013-01-01 12:30"),
                      "end"=>new DateTime("2013-01-01 14:00"))
);

$free_slots = array(
                array("begin"=>new DateTime("2013-01-01 00:00"),
                        "end"=>new DateTime("2013-01-02 00:00")));

foreach ($busy_slots as $slot) {
    $free_slots=ocupe_slot($free_slots, $slot);
}

var_dump($free_slots);

function ocupe_slot($free_slots,$b_slot) {
    $result=array();
    foreach ($free_slots as $free_slot) {
        if ($b_slot["begin"] <= $free_slot["begin"]) {
            if ($b_slot["end"] < $free_slot["begin"]) {
                array_push($result, $free_slot);
            } else if ($b_slot["end"] < $free_slot["end"]) {
                array_push($result,array("begin"=>$b_slot["end"], "end"=>$free_slot["end"]));
            } else {
                // the whole slot is busy
            }
        } else if ($b_slot["begin"] < $free_slot["end"]) {
            if ($b_slot["end"] < $free_slot["end"]) {
                array_push($result,array("begin"=>$free_slot["begin"], "end"=>$b_slot["begin"]));
                array_push($result,array("begin"=>$b_slot["end"], "end"=>$free_slot["end"]));
            } else {
                array_push($result,array("begin"=>$free_slot["begin"], "end"=>$b_slot["begin"]));
            }
        } else {
            array_push($result, $free_slot);
        }   
    }       
    return $result;
}

答案 1 :(得分:2)

这是我得到的,它很好地划分了时间段,考虑到重叠的占用时段和超出范围的占用时段。

function getAvailable(){
    //Container of the results
    $result=[];

    //container of unprocessed period
    $toProcess=[
        "from"=>(new DateTime("2013-8-31 0:0:0")),
        "to"=>(new DateTime("2013-8-31 23:59:59"))
    ];

    //already occupied periods, should be ordered by "from" time
    $unavailable=[
        [
            "from"=>(new DateTime("2013-8-30 5:0:0")),
            "to"=>(new DateTime("2013-8-30 7:0:0"))
        ],
        [
            "from"=>(new DateTime("2013-8-31 5:0:0")),
            "to"=>(new DateTime("2013-8-31 7:0:0"))
        ],
        [
            "from"=>(new DateTime("2013-8-31 6:0:0")),
            "to"=>(new DateTime("2013-8-31 13:0:0"))
        ],
        [
            "from"=>(new DateTime("2013-9-1 20:0:0")),
            "to"=>(new DateTime("2013-9-1 21:0:0"))
        ]
    ];
    foreach($unavailable as $one){
        //divide unprocessed period with a booked period
        $res=divideTime($toProcess,$one);
        //Get an unbooked period
        if($res[0])array_push($result,$res[0]);
        //The rest is for further dividing 
        $toProcess=$res[1];
        //If there's no more periods to divide
        if(!$res[1]){
            break;
        }
    }
    //All the already occupied periods have been processed.
    //The rest is unoccupied.
    if($toProcess){
        array_push($result,$toProcess);
    }
    //Display the result
    exit(var_dump($result));
}
//Divide period $c0 by $c1
function divideTime($c0,$c1){
    //result containers
    $r0=[];
    $r1=[];

    if($c1["from"]<=$c0["from"]){
        $r0=Null;
    }else{
        $r0["from"]=$c0["from"];
        if($c1["from"]>=$c0["to"]){
            $r0["to"]=$c0["to"];
        }else{
            $r0["to"]=$c1["from"];
        }
    }
    if($c1["to"]>=$c0["to"]){
        $r1=Null;
    }else{
        if($c1["to"]<=$c0["from"]){
            $r1["from"]=$c0["from"];
        }else{
            $r1["from"]=$c1["to"];
        }
        $r1["to"]=$c0["to"];
    }
    return [$r0,$r1];
}

答案 2 :(得分:0)

我认为您不需要算法,请尝试以下代码:

$slots = '[{"begin":"9:30","end":"10:30"},{"begin":"12:30","end":"14:00"}]';

$slots = json_decode($slots );

$check_time = "13:30";

$check_timestamp = strtotime($check_time);

$status = FALSE;

foreach($slots as $slot){
  $start = strtotime($slot->begin);
  $end = strtotime($slot->end);

  if($check_timestamp >= $start && $check_timestamp <= $end )
   $status = TRUE;

}

var_dump( $status);

Eval

相关问题