PHP实现两种排课方式

admin3年前PHP教程59

两种排课方式:

固定每周的固定时间上课总共上几个周,每周上课时间比较个性化

第一种排课比较好实现,简要代码如下:


/**
     * 生成日期列表
     *
     * @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实现排课内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

免责声明:本文内容来自用户上传并发布,站点仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。请核实广告和内容真实性,谨慎使用。

相关文章

网络安全为什么如此重要?美国电信高防服务器如何防御网络攻击?

网络安全至关重要,因为它保护所有形式的数据和信息,如敏感数据、个人识别信息(PII)、受保护的健康信息(PHI)、知识产权、信息以及和工业信息系统。如果没有广泛的网络安全战略和计划,和组织就无法抵御数...

PHP+Mysql分布式事务与解决方案深入理解

事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元;事务的ACID特性事务应该具有4个属性:原子性、一致性、隔离性、持续性原子性(atomicity)。一个事务是一个不...

Laravel实现登录跳转功能

前言登录跳转:不同的用户在登录成功之后跳转到不同的网页当中例如:网站管理员登录成功后跳转到网站后台,vip用户登录成功后跳转到vip页面准备工作用户表CREATE TABLE `users` (&nb...

tp5使用layui实现多个图片上传(带附件选择)的方法实例

tp5使用layui实现多个图片上传(带附件选择),如何加载layui在此不详细说明,有需要可以百度html代码,主要处理都是在jq中,完成方法全部原创,也许不是最简单的,但也能实现效果?123456...

聊聊PHP中require_once()函数为什么不好用

在上一篇《聊聊PHP中die()和sleep()函数的用法》中给大家简单介绍了die()和sleep()函数的使用方法,感兴趣的朋友可以去学习了解一下~本文将告诉你PHP中require_once()...

显卡服务器用途有哪些美国显卡服务器租用教程

显卡服务器用途有哪些?显卡服务器又称作为GPU服务器,显卡服务器在处理图形处理能力的时候,有着高性能的效率和计算能力,适用于视频、大数据深度学习、大型数据的处理等多种场景。相比普通的服务器,显卡服务器...