commoncount
7/27/2018 - 2:54 AM

周期去除节假日

/**
     * 度量周期去除节假日和周末
     * 算法:得到正常周末和法定节假日,然后减去这段时间
     * @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;
    }