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 相关文章推荐
一个可查询所有表的“通用”查询分页类
Oct 09 PHP
php学习笔记 PHP面向对象的程序设计
Jun 13 PHP
从手册去理解分析PHP session机制
Jul 17 PHP
PHP图片裁剪函数(保持图像不变形)
May 04 PHP
PHP return语句另类用法不止是在函数中
Sep 17 PHP
php文件上传简单实现方法
Jan 24 PHP
mysql_escape_string()函数用法分析
Apr 25 PHP
PHP编程文件处理类SplFileObject和SplFileInfo用法实例分析
Jul 22 PHP
php读取本地json文件的实例
Mar 07 PHP
PHP安装BCMath扩展的方法
Feb 13 PHP
laravel实现上传图片,并且制作缩略图,按照日期存放的代码
Oct 16 PHP
tp5.1 实现setInc字段自动加1
Oct 18 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
全国FM电台频率大全 - 16 河南省
2020/03/11 无线电
PHP也能干大事 随机函数
2015/04/14 PHP
PHP如何通过AJAX方式实现登录功能
2015/11/23 PHP
使用Composer安装Yii框架的方法
2016/03/15 PHP
PHP结合Redis+MySQL实现冷热数据交换应用案例详解
2019/07/09 PHP
php 命名空间(namespace)原理与用法实例小结
2019/11/13 PHP
php让json_encode不自动转义斜杠“/”的方法
2020/04/27 PHP
JS维吉尼亚密码算法实现代码
2010/11/09 Javascript
通过jQuery源码学习javascript(二)
2012/12/27 Javascript
多选列表框动态添加,移动,删除,全选等操作的简单实例
2014/01/13 Javascript
JavaScript Serializer序列化时间处理示例
2014/07/31 Javascript
关于javascript中dataset的问题小结
2015/11/16 Javascript
JS运动相关知识点小结(附弹性运动示例)
2016/01/08 Javascript
js获取上传文件的绝对路径实现方法
2016/08/02 Javascript
JS关闭窗口时产生的事件及用法示例
2016/08/20 Javascript
Angular路由简单学习
2016/12/26 Javascript
js实现上下左右弹框划出效果
2017/03/08 Javascript
nodeJS进程管理器pm2的使用
2019/01/09 NodeJs
微信小程序图片加载失败时替换为默认图片的方法
2019/12/09 Javascript
微信小程序点击生成朋友圈分享图(遇到的坑)
2020/06/17 Javascript
python密码错误三次锁定(实例讲解)
2017/11/14 Python
python爬虫爬取淘宝商品信息
2018/02/23 Python
python爬取cnvd漏洞库信息的实例
2019/02/14 Python
详解Python3序列赋值、序列解包
2019/05/14 Python
Python 堆叠柱状图绘制方法
2019/07/29 Python
如何基于Python获取图片的物理尺寸
2019/11/25 Python
Python函数调用追踪实现代码
2020/11/27 Python
Numpy ndarray 多维数组对象的使用
2021/02/10 Python
详解CSS3浏览器兼容
2016/12/14 HTML / CSS
Bjorn Borg官方网上商店:国际运动时尚品牌
2016/08/27 全球购物
惊艳的手工时装首饰:Migonne Gavigan
2018/02/23 全球购物
亮化工程实施方案
2014/03/17 职场文书
审计班子对照检查材料
2014/08/27 职场文书
一份恶作剧的检讨书
2014/09/13 职场文书
手机销售员岗位职责
2015/04/11 职场文书
项目备案申请报告
2015/05/15 职场文书