PHP实现两种排课方式
2022/3/31 8:19:33
本文主要是介绍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", //结束时间 "week_at": 1 //周几 }, { "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, 0, 0, $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; } } } } $weeksTime = null; unset($weeksTime); return $list; }
(例子,只用来展示数据结构)假如总共5节课时,从6-25日开始排课,每周一、周六上课:
(例子,只用来展示数据结构)排课结果为:
第二种排课方式稍微麻烦一点,简要代码如下:
/** * 生成日期列表 * * @param int $startDate 开始日期 时间戳格式 * @param array $taskList 任务列表 [ { "start_at": "09:09", //开始上课时间 "end_at": "10:09", //结束时间 "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) { // 计算开始日期是周几 $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($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('上课时间不能小于当前时间'); 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实现两种排课方式的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-11开源 PHP 商城项目 CRMEB 二次开发和部署教程
- 2024-11-09怎么使用php在kaufland平台刊登商品?-icode9专业技术文章分享
- 2024-11-05PHP的抽象类和接口是什么,有什么区别-icode9专业技术文章分享
- 2024-11-01开源 PHP 商城项目 CRMEB 安装和使用教程
- 2024-11-01用php和mysql写无限分类,有哪几种方法-icode9专业技术文章分享
- 2024-10-31php数据分表导出时部分数据无法导出什么原因-icode9专业技术文章分享
- 2024-10-30有经验的 PHP 开发者学习一门新的编程语言,有哪些推荐的有前景的语言-icode9专业技术文章分享
- 2024-10-21php 检测图片是否篡改过-icode9专业技术文章分享
- 2024-10-20fruitcake/php-cors 该怎么使用-icode9专业技术文章分享
- 2024-10-18PHP7.1可以使用哪个版本的swoole-icode9专业技术文章分享