PHP實(shí)現(xiàn)兩種排課方式
兩種排課方式:
固定每周的固定時(shí)間上課(例:共上20節(jié),每周六、周日早上8點(diǎn)-10點(diǎn)上課。假如今天周六凌晨1點(diǎn),那么排課也需要從今天開(kāi)始)總共上幾個(gè)周,每周上課時(shí)間比較個(gè)性化(例:共上三周,第一周周一周二早上8點(diǎn)-10點(diǎn)上課;第二周周三周四下午8點(diǎn)-10點(diǎn)上課;第三周周日中午11點(diǎn)-12點(diǎn)上課。)
第一種排課比較好實(shí)現(xiàn),簡(jiǎn)要代碼如下:
/** * 生成日期列表 * * @param int $startDate 開(kāi)始日期 時(shí)間戳格式 * @param array $timeList 課時(shí)計(jì)劃列表 [ { "start_at": "09:09", //開(kāi)課時(shí)間 "end_at": "10:09", //結(jié)束時(shí)間 "week_at": 1 //周幾 }, { "start_at": "12:09", //開(kāi)課時(shí)間 "end_at": "13:09", //結(jié)束時(shí)間 "week_at": 1 //周幾 }, { "start_at": "09:09", "end_at": "10:09", "week_at": 5 } ] * @param int $amount 課時(shí)計(jì)劃數(shù)量 * @param int $skipHoliday 跳過(guò)節(jié)假日 * * @return array */ public function generateDateList($startDate, $timeList, $amount, $skipHoliday = 0) { // 計(jì)算開(kāi)始日期是周幾 $startDateWeek = intval(date('N', $startDate)); //規(guī)范化課時(shí)數(shù)據(jù) week_at 做key的三維數(shù)組 foreach ($timeList as $item) { $weekAt = $item['week_at']; array_splice($item, 0, 0, $weekAt); $key = array_shift($item); $weeksTime[$key][] = $item; $item = null; } unset($timeList); if (empty($weeksTime)) { $this->addError('課時(shí)計(jì)劃數(shù)據(jù)為空'); return false; } //設(shè)置跳過(guò)假期,獲取開(kāi)始日期之后的節(jié)假日 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) { //算出對(duì)應(yīng)的日期時(shí)間戳 $currentDateTime = $weekStartTime + (($startDateWeek <= $currentWeek ? ($currentWeek - $startDateWeek) : (7 - $startDateWeek + $currentWeek)) * 86400); //對(duì)應(yīng)的日期 = 開(kāi)始時(shí)間 + ((開(kāi)始時(shí)間對(duì)應(yīng)周 <= 數(shù)據(jù)對(duì)應(yīng)的周幾 ? (數(shù)據(jù)對(duì)應(yīng)的周幾 - 開(kāi)始時(shí)間對(duì)應(yīng)周) :(7 - 開(kāi)始時(shí)間對(duì)應(yīng)周 + 數(shù)據(jù)對(duì)應(yīng)的周幾)) * 86400) //假期跳過(guò)排課 if ($skipHoliday && !empty($holidayData)) { $startUnix = $currentDateTime + $time['start_at'] * 3600; //開(kāi)始時(shí)間 $endUnix = $currentDateTime + $time['end_at'] * 3600; //結(jié)束時(shí)間 $skip = false; //選擇跳過(guò)節(jié)假日,且節(jié)假日與當(dāng)前課程時(shí)間有重疊跳過(guò) 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('上課時(shí)間不能小于當(dāng)前時(shí)間'); return false; } $list[] = [ 'date_at' => $currentDateTime, //日期 'week_at' => $currentWeek, //周幾 'start_at' => $startAt, 'end_at' => $endAt ]; $count++; if ($count >= $amount) { break 3; } } } } $weeksTime = null; unset($weeksTime); return $list; }
(例子,只用來(lái)展示數(shù)據(jù)結(jié)構(gòu))假如總共5節(jié)課時(shí),從6-25日開(kāi)始排課,每周一、周六上課:
(例子,只用來(lái)展示數(shù)據(jù)結(jié)構(gòu))排課結(jié)果為:
第二種排課方式稍微麻煩一點(diǎn),簡(jiǎn)要代碼如下:
/** * 生成日期列表 * * @param int $startDate 開(kāi)始日期 時(shí)間戳格式 * @param array $taskList 任務(wù)列表 [ { "start_at": "09:09", //開(kāi)始上課時(shí)間 "end_at": "10:09", //結(jié)束時(shí)間 "week_at": 1, //周幾 "week_number": 1 //第幾周 }, { "start_at": "09:09", "end_at": "10:09", "week_at": 2, "week_number": 1 }, { "start_at": "09:09", "end_at": "10:09", "week_at": 1, "week_number": 3 } ] * * @return array */ public function generateDateList($startDate, $taskList) { // 計(jì)算開(kāi)始日期是周幾 $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; } //計(jì)算每條數(shù)據(jù)對(duì)應(yīng)的日期 $key == 0:確定第一周第一節(jié)課是在本周還是下一周 if($key == 0 || $task['week_number'] == $week){ if($task['week'] >= $startDateWeek){ $task['date_at'] = $startDate + (($weekSign - 1) * 7 + ($task['week'] - $startDateWeek)) * 86400; }else{ $task['date_at'] = $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'])) * 86400; } } $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('上課時(shí)間不能小于當(dāng)前時(shí)間'); return false; } $task['start_at'] = $startAt; $task['end_at'] = $endAt; //生成課時(shí)數(shù)據(jù) $list[] = [ 'date_at' => $task['date_at'], 'week_at' => $task['week'], 'start_at' => $startAt, 'end_at' => $endAt ]; } return $list; }
(例子,只用來(lái)展示數(shù)據(jù)結(jié)構(gòu))排課數(shù)據(jù):
(例子,只用來(lái)展示數(shù)據(jù)結(jié)構(gòu)) 排課結(jié)果:
到此這篇關(guān)于PHP實(shí)現(xiàn)兩種排課方式的文章就介紹到這了,更多相關(guān)PHP實(shí)現(xiàn)排課內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
版權(quán)聲明:
本站所有文章和圖片均來(lái)自用戶(hù)分享和網(wǎng)絡(luò)收集,文章和圖片版權(quán)歸原作者及原出處所有,僅供學(xué)習(xí)與參考,請(qǐng)勿用于商業(yè)用途,如果損害了您的權(quán)利,請(qǐng)聯(lián)系網(wǎng)站客服處理。