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 相关文章推荐
Search Engine Friendly的URL设计
Oct 09 PHP
用PHP读取IMAP邮件
Oct 09 PHP
php查看session内容的函数
Aug 27 PHP
flash用php连接数据库的代码
Apr 21 PHP
php采集文章中的图片获取替换到本地(实现代码)
Jul 08 PHP
php实现通过ftp上传文件
Jun 19 PHP
Yii2增加验证码步骤详解
Apr 25 PHP
Yii2选项卡的简单使用
May 26 PHP
PHP获取本周所有日期或者最近七天所有日期的方法
Jun 20 PHP
PHP中一个有趣的preg_replace函数详解
Aug 15 PHP
PHP使用glob方法遍历文件夹下所有文件的实例
Oct 17 PHP
PHP实现基本留言板功能原理与步骤详解
Mar 26 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
轻松入门: 煮好咖啡的七个诀窍
2021/03/03 冲泡冲煮
PHP - Html Transfer Code
2006/10/09 PHP
php数据结构与算法(PHP描述) 查找与二分法查找
2012/06/21 PHP
PHP7.1新功能之Nullable Type用法分析
2016/09/26 PHP
有关DOM元素与事件的3个谜题
2010/11/11 Javascript
基于jquery的图片幻灯展示源码
2012/07/15 Javascript
node.js中的fs.statSync方法使用说明
2014/12/16 Javascript
JQUERY表单暂存功能插件分享
2016/02/23 Javascript
深入理解js generator数据类型
2016/08/16 Javascript
javascript实现消灭星星小游戏简单版
2016/11/15 Javascript
JavaScript定时器制作弹窗小广告
2017/02/05 Javascript
微信小程序图片横向左右滑动案例
2017/05/19 Javascript
如何在vue中使用ts的示例代码
2018/02/28 Javascript
基于Axios 常用的请求方法别名(详解)
2018/03/13 Javascript
Layui数据表格之获取表格中所有的数据方法
2018/08/20 Javascript
详解如何在Angular优雅编写HTTP请求
2018/12/05 Javascript
微信小程序实现图片滚动效果示例
2018/12/05 Javascript
Javascript读取上传文件内容/类型/字节数
2019/04/30 Javascript
微信小程序结合Storage实现搜索历史效果
2019/05/18 Javascript
vue input输入框关键字筛选检索列表数据展示
2020/10/26 Javascript
关于ligerui子页面关闭后,父页面刷新,重新加载的方法
2019/09/27 Javascript
Layui选项卡制作历史浏览记录的方法
2019/09/28 Javascript
[02:40]DOTA2英雄基础教程 巨牙海民
2013/12/23 DOTA
使用Python操作Elasticsearch数据索引的教程
2015/04/08 Python
Python中文竖排显示的方法
2015/07/28 Python
Django中使用Celery的方法示例
2018/11/29 Python
详解python中的数据类型和控制流
2019/08/08 Python
Python实现爬取网页中动态加载的数据
2020/08/17 Python
简历上的自我评价
2014/02/03 职场文书
家长寄语大全
2014/04/02 职场文书
雷人标语集锦
2014/06/19 职场文书
授权委托书公证
2014/09/14 职场文书
2015年干部教育培训工作总结
2015/05/15 职场文书
乡镇团委工作总结2015
2015/05/26 职场文书
Jupyter Notebook 如何修改字体和大小以及更改字体样式
2021/06/03 Python
彩虹社八名人气艺人全新周边限时推出,性转女装男装一次拥有!
2022/04/01 日漫