我正在建立一个服务预订系统,并希望在一些预订后获得“可用时间段”列表。
例如,一天有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"}]
答案 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);