php教程 排除週末與公休日程式實例代碼
date_default_timezone_set('prc');
/**
* 求取從某日起經過一定天數後的日期,
* 排除週六周日和公休日
* @param $start 開始日期
* @param $offset 經過天數
* @param $exception 例外的公休日
* @param $allow 允許的日期(預留參數)
* @return
* examples:輸入(2010-06-25,5,''),得到2010-07-02
*/
function getendday( $start='now', $offset=0, $exception='', $allow='' ){
//先計算不排除週六周日及公休日的結果
$starttime = strtotime($start);
$endtime = $starttime + $offset * 24 * 3600;
$end = date('y-m-d', $endtime);
//然後計算週六周日引起的偏移
$weekday = date('n', $starttime);//得到星期值:1-7
$remain = $offset % 7;
$newoffset = 2 * ($offset - $remain) / 7;//每一周需重新計算兩天
if( $remain > 0 ){//周余湊整
$tmp = $weekday + $remain;
if( $tmp >= 7 ){
$newoffset += 2;
}else if( $tmp == 6 ){
$newoffset += 1;
}
//考慮當前為週六周日的情況
if( $weekday == 6 ){
$newoffset -= 1;
}else if( $weekday == 7 ){
$newoffset -= 2;
}
}
//再計算公休日引起的偏移
if( is_array($exception) ){//多個公休日
foreach ($exception as $day){
$tmp_time = strtotime($day);
if( $tmp_time>$starttime && $tmp_time<=$endtime ){//在範圍(a,b]內
$weekday_t = date('n', $tmp_time);
if($weekday_t <= 5){//防止公休日與週末重複
$newoffset += 1;
}
}
}
}else{//單個公休日
if( $exception!='' ){
$tmp_time = strtotime($exception);
if( $tmp_time>$starttime && $tmp_time<=$endtime ){
$weekday_t = date('n', $tmp_time);
if($weekday_t <= 5){
$newoffset += 1;
}
}
}
}
//根據偏移天數,遞迴做等價運算jzread.com
if($newoffset > 0){
#echo "[{$start} -> {$offset}] = [{$end} -> {$newoffset}]"." <br />n";
return getendday($end,$newoffset,$exception,$allow);
}else{
return $end;
}
}
/**
* 暴力迴圈方法
*/
function getendday2( $start='now', $offset=0, $exception='', $allow='' ){
$starttime = strtotime($start);
$tmptime = $starttime + 24*3600;
while( $offset > 0 ){
$weekday = date('n', $tmptime);
$tmpday = date('y-m-d', $tmptime);
$bfd = false;//是否公休日
if(is_array($exception)){
$bfd = in_array($tmpday,$exception);
}else{
$bfd = ($exception==$tmpday);
}
if( $weekday<=5 && !$bfd){//不是週末和公休日
$offset--;
#echo "tmpday={$tmpday}"." <br />";
}
$tmptime += 24*3600;
}
return $tmpday;
}
$exception = array(
'2010-01-01','2010-01-02','2010-01-03',
'2010-04-03','2010-04-04','2010-04-05',
'2010-05-01','2010-05-02','2010-05-03',
'2010-06-14','2010-06-15','2010-06-16',
'2010-09-22','2010-09-23','2010-09-24',
'2010-10-01','2010-10-02','2010-10-03','2010-10-04',
'2010-10-05','2010-10-06','2010-10-07',
);
//echo getendday('2010-08-27',3,'');
//echo getendday('2010-06-25',15,'2010-07-07');
$t1 = microtime();
echo getendday('2010-05-12',66,$exception)." <br />";
$t2 = microtime();echo "use ". ($t2-$t1)." s <br />";
echo getendday2('2010-05-12',66,$exception)." <br />";
$t3 = microtime();echo "use ". ($t3-$t2)." s <br />";