/**
* 度量周期去除节假日和周末
* 算法:得到正常周末和法定节假日,然后减去这段时间
* @param string $end
* @param string $start
* @param string $returnType 返回单位
* @param int $precision 精度,表示保留小数点后几位
* @access public
* @return string
*/
public function minusHoliday($end, $start, $returnType='hour', $precision = 0)
{
if($end == '0000-00-00 00:00:00' || $start == '0000-00-00 00:00:00' || empty($end) || empty($start))
return '';
//如果开始|结束时间在节假日,则时间重置为后面最近的一个工作日
$startDate = $this->nextWorkDay($start);
$endDate = $this->nextWorkDay($end);
if($startDate>$endDate) return 0;
$diffPeriod = '';
$precision = 0;
switch ($returnType){
case 'hour':
$holidaysArr = $this->dao->select('id,hdtime,hdduty')->from(TABLE_HOLIDAY)->where('hdtime')->between($startDate,$endDate)->andWhere('hdduty')->eq('y')->fetchAll('id');
$minusDays = $this->getMinusDays($startDate, $endDate)+count($holidaysArr);
$diffPeriod = helper::diffHour($end, $start,$precision) - ($minusDays*24);
break;
case 'day':
$holidaysArr = $this->dao->select('id,hdtime,hdduty')->from(TABLE_HOLIDAY)->where('hdtime')->between($startDate,$endDate)->andWhere('hdduty')->eq('y')->fetchAll('id');
$minusDays = $this->getMinusDays($startDate, $endDate)+count($holidaysArr);
$diffPeriod = helper::diffDate($end, $start) - $minusDays;
break;
case 'month':
break;
default:
return round((strtotime($end) - strtotime($start)) / 3600, $precision);
break;
}
return $diffPeriod;
}
/**
* 计算周期内需要减掉的普通周末
* @param date $start Y-m-d
* @param date $end Y-m-d
* return int 天数 */
public function getMinusDays($start, $end){
if(strtotime($start) > strtotime($end)){
list($start,$end) = array($end,$start);
}
$minus = 0;
for($date=$start; $date<=$end; $date = date("Y-m-d", strtotime($date." +1 days"))){
//0(星期天)"至"6(星期六),判断是普通的周末还是节假日中的周末
$weekDay = date("w", strtotime($date));
if($weekDay == 0 ||$weekDay == 6){
//是法定节假日的话,后面直接从holidays里计算
$checkHoliday = $this->dao->select('id,hdtime,hdduty')->from(TABLE_HOLIDAY)->where('hdtime')->eq($date)->fetch();
if($checkHoliday){
//if($checkHoliday->hdduty == 'n'){}
}else{
$minus += 1; //正常周末
}
}
}
return $minus;
}
/**
* 判断日期是否是节假日
* @param date $date
* return boolean */
public function isHoliday($date){
$checkHoliday = $this->dao->select('id,hdtime,hdduty')->from(TABLE_HOLIDAY)->where('hdtime')->eq($date)->fetch();
if($checkHoliday){
return ($checkHoliday->hdduty == 'n')? false:true;
}else{
$weekDay = date("w", strtotime($date));
if($weekDay == 0 ||$weekDay == 6){
return true;
}else{
return false;
}
}
}
/**
* 如果在节假日中,获取最近的工作日,如果$date本身就是工作日,则返回$date
* 用于周期计算扣除节假日
* @param date $date
* return boolean */
public function nextWorkDay(&$dateTime){
$tmpDate = date('Y-m-d',strtotime($dateTime));
$resetDate = false;
while (1){
$isHoliday = $this->isHoliday($tmpDate);
if($isHoliday){
$resetDate = true;
$tmpDate = date("Y-m-d", strtotime($tmpDate." +1 days"));
}else{
$date = $tmpDate;
if($resetDate) $dateTime = $tmpDate;
break;
}
}
return $date;
}