PHP实现两种排课方式
发布:smiling 来源: PHP粉丝网 添加日期:2022-05-05 20:08:40 浏览: 评论:0
这篇文章主要介绍了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 (emptyempty($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 && !emptyempty($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;
- }
(例子,只用来展示数据结构)排课数据:
(例子,只用来展示数据结构) 排课结果:
Tags: PHP排课方式
- 上一篇:php生成用户密码的两种方式
- 下一篇:最后一页

推荐文章
热门文章
最新评论文章
- 写给考虑创业的年轻程序员(10)
- PHP新手上路(一)(7)
- 惹恼程序员的十件事(5)
- PHP邮件发送例子,已测试成功(5)
- 致初学者:PHP比ASP优秀的七个理由(4)
- PHP会被淘汰吗?(4)
- PHP新手上路(四)(4)
- 如何去学习PHP?(2)
- 简单入门级php分页代码(2)
- php中邮箱email 电话等格式的验证(2)