• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    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实现排课内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

    您可能感兴趣的文章:
    • 详细分析PHP7与PHP5区别
    • php生成用户密码的两种方式
    • php类中static与self的使用区别浅析
    • php如何用PDO操作大数据对象
    • php使用workman框架实现socket服务以及连接客户端
    上一篇:Linux系统下安装PHP7.3版本
    下一篇:php使用workman框架实现socket服务以及连接客户端
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    PHP实现两种排课方式 PHP,实现,两种,排课,方式,