首页后端开发PHP用PHP如何实现排课的效果?教你两种技巧

用PHP如何实现排课的效果?教你两种技巧

时间2024-03-26 13:12:03发布访客分类PHP浏览1174
导读:这篇文章给大家分享的是用PHP如何实现排课的内容,下文介绍了两种排课方式,小编觉得挺实用的,因此分享给大家做个参考,文中示例代码介绍的非常详细,感兴趣的朋友接下来一起跟随小编看看吧。 固定每周的固定时间上课(例:共上20节,每周六、周日早上...

这篇文章给大家分享的是用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 (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有帮助,想要了解更多可以继续浏览网络其他相关的文章。

文本转载自脚本之家

声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!


若转载请注明出处: 用PHP如何实现排课的效果?教你两种技巧
本文地址: https://pptw.com/jishu/653521.html
Go语言中错误抛出怎么实现,错误处理策略有什么 Golang中读取json数据的方法是什么,怎么用

游客 回复需填写必要信息