1. 程式人生 > 程式設計 >PHP實現兩種排課方式

PHP實現兩種排課方式

兩種排課方式:

固定每週的固定時間上課(例:共上20節,每週六、週日早上8點-10點上課。假如今天週六凌晨1點,那麼排課也需要從今天開始)總共上幾個周,每週上課時間比較個性化(例:共上三週,第一週週一週二早上8點-10點上課;第二週週三週四下午8點-10點上課;第三週週日中午11點-12點上課。)

第一種排課比較好實現,簡要程式碼如下:

/**
     * 生成日期列表
     *
     * @param  int $startDate 開始日期 時間戳格式
     * @param  array $timeList 課時計劃列表
       [
        {
            "start_at": "09:09",//開課時間
            "end_at": "10:09",//結束時間
            "week_at": 1         //周幾
        },{
            "start_at": "12:09",//開課時間
            "end_at": "13:09",{
            "start_at": "09:09","end_at": "10:09","week_at": 5
        }
       ]
     * @param  int $amount 課時計劃數量
     * @param  int $skipHoliday 跳過節假日
     *
     * @return array
     */
    public function generateDateList($startDate,$timeList,$amount,$skipHoliday = 0)
    {
        // 計算開始日期是周幾
        $startDateWeek = intval(date('N',$startDate));
 
        //規範化課時資料 week_at 做key的三維陣列
        foreach ($timeList as $item) {
 
            $weekAt = $item['week_at'];
            
            array_splice($item,$weekAt);
            $key = array_shift($item);
            $weeksTime[$key][] = $item;
            $item = null;
        }
 
        unset($timeList);
 
        if (empty($weeksTime)) {
            $this->addError('課時計劃資料為空');
            return false;
        }
 
        //設定跳過假期,獲取開始日期之後的節假日
        if ($skipHoliday) {
            $holiday = new Holiday();
            $holidayData = $holiday->getHolidayList($startDate);
            $holiday = null;
            unset($holiday);
        }
 
        $nowTime = time();
        $list = array();
 
        for ($weekStartTime = $startDate,$count = 0; $count < $amount; $weekStartTime += 86400 * 7) {
 
            //$currentWeek :周幾
            foreach ($weeksTime as $currentWeek => $weekTime) {
 
                foreach ($weekTime as $time) {
 
                    //算出對應的日期時間戳
                    $currentDateTime = $weekStartTime + (($startDateWeek <= $currentWeek ? ($currentWeek - $startDateWeek) : (7 - $startDateWeek + $currentWeek)) * 86400);
                    //對應的日期 = 開始時間 + ((開始時間對應周 <= 資料對應的周幾 ? (資料對應的周幾 - 開始時間對應周) :(7 - 開始時間對應周 + 資料對應的周幾)) * 86400)
                    //假期跳過排課
                    if ($skipHoliday && !empty($holidayData)) {
                        $startUnix = $currentDateTime + $time['start_at'] * 3600;  //開始時間
                        $endUnix = $currentDateTime + $time['end_at'] * 3600;     //結束時間
 
                        $skip = false;
 
                        //選擇跳過節假日,且節假日與當前課程時間有重疊跳過
                        foreach ($holidayData as $item) {
                            if (($item['start_at'] < $endUnix && $item['end_at'] > $startUnix) || ($item['start_at'] === $startUnix && $item['end_at'] === $endUnix)) {
                                $skip = true;
                                continue;
                            }
                        }
 
                        if ($skip) {
                            continue;
                        }
                    }
 
                    $currentDate = date('Y/m/d',$currentDateTime);
                    $startAt = strtotime($currentDate . $time['start_at'] . ':00');
                    $endAt = strtotime($currentDate . $time['end_at'] . ':00');
 
                    if($startAt < $nowTime || $endAt < $nowTime){
                        $this->addError('上課時間不能小於當前時間');
                        return false;
                    }
 
                    $list[] = [
                        'date_at' => $currentDateTime,//日期
                        'week_at' => $currentWeek,//周幾
                        'start_at' => $startAt,'end_at' => $endAt
                    ];
 
                    $count++;
 
                    if ($count >= $amount) {
                        break 3;
                    }
              www.cppcns.com
} } } $weeksTime = null; unset($weeksTime); return $list; }

(例子,只用來展示資料結構)假如總共5節課時,從6-25日開始排課,每週一、週六上課:

PHP實現兩種排課方式

(例子,只用來展示資料結構)排課結果為:

PHP實現兩種排課方式


第二種排課方式稍微麻煩一點,簡要程式碼如下:

/**
     * 生成日期列表
     *
     * @param  int $startDate 開始日期 時間戳格式
     * @param  array $taskList 任務列表
    [
        {
            "start_at": "09:09",//開始上課時間
            "end_at": "10:09",//結束時間
            "week_at": 1,//周幾
            "week_number": 1     //第幾周
        },"week_at": 2,"week_number": 1
        },"week_at": 1,"week_number": 3
        }
    ]
     *
     * @return array
     */
    public function generateDateList($startDate,$taskList)
    {
        // 計算開始日期是周幾
        $startDateWeek = intval(date('N',$startDate));
 
        $list = [];
        $nowTime = time();
        $weekSign = $week = 0;
 
        foreach($taskList as $key => $task){
 
            if($task['week_number'] > $weekSign && $task['week_number'] != $week){
                $weekSign = $task['week_number'] - $week;
            }
 
            //計算每條資料對應的日期 $key == 0:確定第一週第一節課是在本週還是下一週
            if($ke
y == 0 || $task['week_number'] == $week){ if($task['week'] >= $startDateWeek){ $task['date_at'] = $startDate + (($weekSign - 1) * 7 + ($task['week'] - $startDateWeek)) * 86400; }else{ $task['date_at'] keqUB
= $startDate + (($weekSign) * 7 - ($startDateWeek - $task['week'])) * 86400; } }else{ if($task['week'] > $startDateWeek){ $task['date_at'] = $startDate + (($weekSign) * 7 + ($task['week'] - $startDateWeek)) * 86400; }else{ $task['date_at'] = $startDate + (($weekSign) * 7 - ($startDateWeek - $task['week'])) * keqUB86400; } } $startDateWeek = intval(date('N',$task['date_at'])); $week = $task['week_number']; $startDate = $task['date_at']; $dateAt = date('Y/m/d',$task['date_at']); $startAt = strtotime($dateAt . '00:00:00'); if($task['start_at']){ $startAt = strtotime($dateAt . $task['start_at'] . ':00'); } $endAt = strtotime($dateAt . '23:59:59'); if($task['end_at']){ $endAt = strtotime($dateAt . $task['end_at'] . ':00'); } if($startAt < $nowTime || $endAt < $nowTime){ $this->addError('上課時間不能小於當前時間'); return false; } $task['start_at'] = $startAt; $task['end_at'] = $endAt; //生成課時資料 $list[] = [ 'date_at' => $task['date_at'],'week_at' => $task['week'],'start_at' => $startAt,'end_at' => $endAt ]; } return $list; }

(例子,只用來展示資料結構)排課資料:

PHP實現兩種排課方式

(例子,只用來展示資料結構)排課結果:

PHP實現兩種排課方式

到此這篇關於實現兩種排課方式的文章就介紹到這了,更多相關PHP實現排課內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!