PHP实现两种排课方式

这篇文章主要介绍了PHP实现两种排课方式,第一种排课方式比较好理解,开始时间和结束时间,第二种比较复杂一些,有开始上课时间和结束上课时间和第几周,具体实现代码参考下本文

Posted in PHP onJune 26, 2021

两种排课方式:

固定每周的固定时间上课(例:共上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日开始排课,每周一、周六上课:

PHP实现两种排课方式

(例子,只用来展示数据结构)排课结果为:

PHP实现两种排课方式


第二种排课方式稍微麻烦一点,简要代码如下:

/**
     * 生成日期列表
     *
     * @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实现两种排课方式

到此这篇关于PHP实现两种排课方式的文章就介绍到这了,更多相关PHP实现排课内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

PHP 相关文章推荐
提升PHP执行速度全攻略(下)
Oct 09 PHP
PHP分页显示制作详细讲解
Nov 19 PHP
php 数组的创建、调用和更新实现代码
Mar 09 PHP
PHPEXCEL 使用小记
Jan 06 PHP
基于php使用memcache存储session的详解
Jun 25 PHP
php合并数组中相同元素的方法
Nov 13 PHP
php编写的抽奖程序中奖概率算法
May 14 PHP
PHP网络操作函数汇总
May 18 PHP
php判断邮箱地址是否存在的方法
Feb 13 PHP
PHP is_array() 检测变量是否是数组的实现方法
Jun 13 PHP
thinkphp5框架前后端分离项目实现分页功能的方法分析
Oct 08 PHP
Laravel框架源码解析之反射的使用详解
May 14 PHP
Linux系统下安装PHP7.3版本
详细分析PHP7与PHP5区别
Jun 26 #PHP
laravel添加角色和模糊搜索功能的实现代码
一文搞懂php的垃圾回收机制
PHP中strval()函数实例用法
Jun 07 #PHP
使用php的mail()函数实现发送邮件功能
PHP实现rar解压读取扩展包小结
Jun 03 #PHP
You might like
虫族 Zerg 历史背景
2020/03/14 星际争霸
php miniBB中文乱码问题解决方法
2008/11/25 PHP
解决PHP mysql_query执行超时(Fatal error: Maximum execution time …)
2013/07/03 PHP
可以保证单词完整性的PHP英文字符串截取代码分享
2014/07/15 PHP
PHP类型约束用法示例
2016/09/28 PHP
php中的buffer缓冲区用法分析
2019/05/31 PHP
获取当前网页document.url location.href区别总结
2008/05/10 Javascript
jquery星级插件、支持页面中多次使用
2012/03/25 Javascript
常用的几段javascript代码分享
2014/03/25 Javascript
jquery防止重复执行动画避免页面混乱
2014/04/22 Javascript
javascript获取和判断浏览器窗口、屏幕、网页的高度、宽度等
2014/05/08 Javascript
JQuery中使文本框获得焦点的方法实例分析
2015/02/28 Javascript
js实现向右横向滑出的二级菜单效果
2015/08/27 Javascript
轻松实现js弹框显示选项
2016/09/13 Javascript
JS实现页面进入和返回定位到具体位置
2016/12/08 Javascript
详解基于 axios 的 Vue 项目 http 请求优化
2017/09/04 Javascript
jQuery实现的页面遮罩层功能示例【测试可用】
2017/10/14 jQuery
常用的9个JavaScript图表库详解
2017/12/19 Javascript
JS中数组与对象的遍历方法实例小结
2018/08/14 Javascript
一文看懂如何简单实现节流函数和防抖函数
2019/09/05 Javascript
vue 使用鼠标滚动加载数据的例子
2019/10/31 Javascript
JavaScript中继承原理与用法实例入门
2020/05/09 Javascript
[01:52]2014DOTA2西雅图邀请赛 V社开大会你不知道的小秘密
2014/07/08 DOTA
详解Python中的文本处理
2015/04/11 Python
python中的编码知识整理汇总
2016/01/26 Python
django初始化数据库的实例
2018/05/27 Python
python实现超级玛丽游戏
2020/03/18 Python
利用python绘制中国地图(含省界、河流等)
2020/09/21 Python
利用CSS3实现炫酷的飞机起飞动画
2016/09/17 HTML / CSS
Html5适配iphoneX刘海屏的简单实现
2019/04/09 HTML / CSS
Nebula美国官网:便携式投影仪
2019/03/15 全球购物
趣味比赛活动方案
2014/02/15 职场文书
经贸专业毕业生求职信范文
2014/05/01 职场文书
社区文艺活动方案
2014/08/19 职场文书
2014年大学教师工作总结
2014/12/02 职场文书
Win11开始菜单添加休眠选项
2022/04/19 数码科技