PHP教程

PHP实现两种排课方式

本文主要是介绍PHP实现两种排课方式,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

这篇文章主要介绍了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日开始排课,每周一、周六上课:

https://img1.sycdn.imooc.com/6243b3d90001b6d112620152.jpg

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

https://img3.sycdn.imooc.com/6243b3da0001611e03930255.jpg


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

/**     * 生成日期列表     *     * @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;    }




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

https://img1.sycdn.imooc.com/6243b3eb0001571913080417.jpg

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

https://img1.sycdn.imooc.com/6243b3eb0001c5b204040409.jpg

到此这篇关于PHP实现两种排课方式的文章就介绍到这了。


















这篇关于PHP实现两种排课方式的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!