当前位置:首页 > PHP教程 > php应用 > 列表

PHP实现两种排课方式

发布:smiling 来源: PHP粉丝网  添加日期:2022-05-05 20:08:40 浏览: 评论:0 

这篇文章主要介绍了PHP实现两种排课方式,第一种排课方式比较好理解,开始时间和结束时间,第二种比较复杂一些,有开始上课时间和结束上课时间和第几周,具体实现代码参考下本文。

两种排课方式:

固定每周的固定时间上课(例:共上20节,每周六、周日早上8点-10点上课。假如今天周六凌晨1点,那么排课也需要从今天开始)总共上几个周,每周上课时间比较个性化(例:共上三周,第一周周一周二早上8点-10点上课;第二周周三周四下午8点-10点上课;第三周周日中午11点-12点上课。)

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

  1. /** 
  2.      * 生成日期列表 
  3.      * 
  4.      * @param  int $startDate 开始日期 时间戳格式 
  5.      * @param  array $timeList 课时计划列表 
  6.        [ 
  7.         { 
  8.             "start_at": "09:09", //开课时间 
  9.             "end_at": "10:09",   //结束时间 
  10.             "week_at": 1         //周几 
  11.         }, 
  12.         { 
  13.             "start_at": "12:09", //开课时间 
  14.             "end_at": "13:09",   //结束时间 
  15.             "week_at": 1         //周几 
  16.         }, 
  17.         { 
  18.             "start_at": "09:09", 
  19.             "end_at": "10:09", 
  20.             "week_at": 5 
  21.         } 
  22.        ] 
  23.      * @param  int $amount 课时计划数量 
  24.      * @param  int $skipHoliday 跳过节假日 
  25.      * 
  26.      * @return array 
  27.      */ 
  28.     public function generateDateList($startDate$timeList$amount$skipHoliday = 0) 
  29.     { 
  30.         // 计算开始日期是周几 
  31.         $startDateWeek = intval(date('N'$startDate)); 
  32.    
  33.         //规范化课时数据 week_at 做key的三维数组 
  34.         foreach ($timeList as $item) { 
  35.    
  36.             $weekAt = $item['week_at']; 
  37.               
  38.             array_splice($item, 0, 0, $weekAt); 
  39.             $key = array_shift($item); 
  40.             $weeksTime[$key][] = $item
  41.             $item = null; 
  42.         } 
  43.    
  44.         unset($timeList); 
  45.    
  46.         if (emptyempty($weeksTime)) { 
  47.             $this->addError('课时计划数据为空'); 
  48.             return false; 
  49.         } 
  50.    
  51.         //设置跳过假期,获取开始日期之后的节假日 
  52.         if ($skipHoliday) { 
  53.             $holiday = new Holiday(); 
  54.             $holidayData = $holiday->getHolidayList($startDate); 
  55.             $holiday = null; 
  56.             unset($holiday); 
  57.         } 
  58.    
  59.         $nowTime = time(); 
  60.         $list = array(); 
  61.    
  62.         for ($weekStartTime = $startDate$count = 0; $count < $amount$weekStartTime += 86400 * 7) { 
  63.    
  64.             //$currentWeek :周几 
  65.             foreach ($weeksTime as $currentWeek => $weekTime) { 
  66.    
  67.                 foreach ($weekTime as $time) { 
  68.    
  69.                     //算出对应的日期时间戳 
  70.                     $currentDateTime = $weekStartTime + (($startDateWeek <= $currentWeek ? ($currentWeek - $startDateWeek) : (7 - $startDateWeek + $currentWeek)) * 86400); 
  71.                     //对应的日期 = 开始时间 + ((开始时间对应周 <= 数据对应的周几 ? (数据对应的周几 - 开始时间对应周) :(7 - 开始时间对应周 + 数据对应的周几)) * 86400) 
  72.                     //假期跳过排课 
  73.                     if ($skipHoliday && !emptyempty($holidayData)) { 
  74.                         $startUnix = $currentDateTime + $time['start_at'] * 3600;  //开始时间 
  75.                         $endUnix = $currentDateTime + $time['end_at'] * 3600;     //结束时间 
  76.    
  77.                         $skip = false; 
  78.    
  79.                         //选择跳过节假日,且节假日与当前课程时间有重叠跳过 
  80.                         foreach ($holidayData as $item) { 
  81.                             if (($item['start_at'] < $endUnix && $item['end_at'] > $startUnix) || ($item['start_at'] === $startUnix && $item['end_at'] === $endUnix)) { 
  82.                                 $skip = true; 
  83.                                 continue
  84.                             } 
  85.                         } 
  86.    
  87.                         if ($skip) { 
  88.                             continue
  89.                         } 
  90.                     } 
  91.    
  92.                     $currentDate = date('Y/m/d'$currentDateTime); 
  93.                     $startAt = strtotime($currentDate . $time['start_at'] . ':00'); 
  94.                     $endAt = strtotime($currentDate . $time['end_at'] . ':00'); 
  95.    
  96.                     if($startAt < $nowTime || $endAt < $nowTime){ 
  97.                         $this->addError('上课时间不能小于当前时间'); 
  98.                         return false; 
  99.                     } 
  100.    
  101.                     $list[] = [ 
  102.                         'date_at' => $currentDateTime//日期 
  103.                         'week_at' => $currentWeek,     //周几 
  104.                         'start_at' => $startAt
  105.                         'end_at' => $endAt 
  106.                     ]; 
  107.    
  108.                     $count++; 
  109.    
  110.                     if ($count >= $amount) { 
  111.                         break 3; 
  112.                     } 
  113.                 } 
  114.             } 
  115.         } 
  116.    
  117.         $weeksTime = null; 
  118.         unset($weeksTime); 
  119.    
  120.         return $list
  121.     } 

(例子,只用来展示数据结构)假如总共5节课时,从6-25日开始排课,每周一、周六上课:

PHP实现两种排课方式

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

PHP实现两种排课方式

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

  1. /** 
  2.      * 生成日期列表 
  3.      * 
  4.      * @param  int $startDate 开始日期 时间戳格式 
  5.      * @param  array $taskList 任务列表 
  6.     [ 
  7.         { 
  8.             "start_at": "09:09", //开始上课时间 
  9.             "end_at": "10:09",   //结束时间 
  10.             "week_at": 1,        //周几 
  11.             "week_number": 1     //第几周 
  12.         }, 
  13.         { 
  14.             "start_at": "09:09", 
  15.             "end_at": "10:09", 
  16.             "week_at": 2, 
  17.             "week_number": 1 
  18.         }, 
  19.         { 
  20.             "start_at": "09:09", 
  21.             "end_at": "10:09", 
  22.             "week_at": 1, 
  23.             "week_number": 3 
  24.         } 
  25.     ] 
  26.      * 
  27.      * @return array 
  28.      */ 
  29.     public function generateDateList($startDate$taskList
  30.     { 
  31.         // 计算开始日期是周几 
  32.         $startDateWeek = intval(date('N'$startDate)); 
  33.    
  34.         $list = []; 
  35.         $nowTime = time(); 
  36.         $weekSign = $week = 0; 
  37.    
  38.         foreach($taskList as $key => $task){ 
  39.    
  40.             if($task['week_number'] > $weekSign && $task['week_number'] != $week){ 
  41.                 $weekSign = $task['week_number'] - $week
  42.             } 
  43.    
  44.             //计算每条数据对应的日期 $key == 0:确定第一周第一节课是在本周还是下一周 
  45.             if($key == 0 || $task['week_number'] == $week){ 
  46.    
  47.                 if($task['week'] >= $startDateWeek){ 
  48.                     $task['date_at'] = $startDate + 
  49.                         (($weekSign - 1) * 7 + ($task['week'] - $startDateWeek)) * 86400; 
  50.                 }else
  51.                     $task['date_at'] = $startDate + 
  52.                         (($weekSign) * 7 - ($startDateWeek - $task['week'])) * 86400; 
  53.                 } 
  54.             }else
  55.                 if($task['week'] > $startDateWeek){ 
  56.                     $task['date_at'] = $startDate + 
  57.                         (($weekSign) * 7 + ($task['week'] - $startDateWeek)) * 86400; 
  58.                 }else
  59.                     $task['date_at'] = $startDate + 
  60.                         (($weekSign) * 7 - ($startDateWeek - $task['week'])) * 86400; 
  61.                 } 
  62.             } 
  63.    
  64.             $startDateWeek = intval(date('N'$task['date_at'])); 
  65.    
  66.             $week = $task['week_number']; 
  67.    
  68.             $startDate = $task['date_at']; 
  69.    
  70.             $dateAt = date('Y/m/d'$task['date_at']); 
  71.    
  72.             $startAt = strtotime($dateAt . '00:00:00'); 
  73.             if($task['start_at']){ 
  74.                 $startAt = strtotime($dateAt . $task['start_at'] . ':00'); 
  75.             } 
  76.    
  77.             $endAt = strtotime($dateAt . '23:59:59'); 
  78.             if($task['end_at']){ 
  79.                 $endAt = strtotime($dateAt . $task['end_at'] . ':00'); 
  80.             } 
  81.    
  82.             if($startAt < $nowTime || $endAt < $nowTime){ 
  83.                 $this->addError('上课时间不能小于当前时间'); 
  84.                 return false; 
  85.             } 
  86.    
  87.             $task['start_at'] = $startAt
  88.             $task['end_at'] = $endAt
  89.    
  90.             //生成课时数据 
  91.             $list[] = [ 
  92.                     'date_at' => $task['date_at'], 
  93.                     'week_at' => $task['week'], 
  94.                     'start_at' => $startAt
  95.                     'end_at' => $endAt 
  96.                 ]; 
  97.         } 
  98.    
  99.         return $list
  100.     } 

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

PHP实现两种排课方式

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

PHP实现两种排课方式

Tags: PHP排课方式

分享到: