2016年11月1日 16:18:19 星期二
主要用到的函數是 strtotime()
strtotime('+1 Tuesday', $timestamp) 獲取下周二, 從時間戳$timestamp開始計算, 如果$timestamp留空, 則從當天開始計算
strtotime('+1 month', $timestamp) 獲取下個月的x號, 還是以$timestamp開始計算的
1 /** 2 * desc 獲取每周X執行的所有日期 3 * @param string $start 開始日期, 2016-10-17 4 * @param string $end 結束日期, 2016-10-17 5 * @param int $weekDay 1~5 6 * @return array 7 */ 8 public function getWeeklyBuyDate($start, $end, $weekDay) 9 { 10 //獲取每周要執行的日期 例如: 2016-01-02 11 $start = empty($start) ? date('Y-m-d') : $start; 12 $startTime = strtotime($start); 13 14 $startDay = date('N', $startTime); 15 if ($startDay < $weekDay) { 16 $startTime = strtotime(self::$WORK_DAY[$weekDay]['en'], strtotime($start)); //本周x開始, 例如, 今天(周二)用戶設置每周四執行, 那本周四就會開始執行 17 } else { 18 $startTime = strtotime('next '.self::$WORK_DAY[$weekDay]['en'], strtotime($start));//下一個周x開始, 今天(周二)用戶設置每周一執行, 那應該是下周一開始執行 19 } 20 21 $endTime = strtotime($end); 22 $list = []; 23 for ($i=0;;$i++) { 24 $dayOfWeek = strtotime("+{$i} week", $startTime); //每周x 25 if ($dayOfWeek > $endTime) { 26 break; 27 } 28 $list[] = date('Y-m-d', $dayOfWeek); 29 } 30 31 return $this->getExedate($start, $end, $list); 32 } 33 34 /** 35 * desc 獲取每月X號執行的所有日期 36 * @param string $start 開始日期, 2016-10-17 37 * @param string $end 結束日期, 2016-10-17 38 * @param int $monthDay 1~28 39 * @return array 40 */ 41 public function getMonthlyBuyDate($start, $end, $monthDay) 42 { 43 $monthDay = str_pad($monthDay, 2, '0', STR_PAD_LEFT); //左邊補零 44 $start = empty($start) ? date('Y-m-d') : $start; 45 $startTime = strtotime($start); 46 $startDay = substr($start, 8, 2); 47 48 if (strcmp($startDay, $monthDay) < 0) { 49 $startMonthDayTime = strtotime(date('Y-m-', strtotime($start)).$monthDay); //本月開始執行, 今天(例如,26號)用戶設置每月28號執行, 那么本月就開始執行 50 } else { 51 $startMonthDayTime = strtotime(date('Y-m-', strtotime('+1 month', $startTime)).$monthDay); //從下個月開始 52 } 53 $endTime = strtotime($end); 54 55 $list = []; 56 for ($i=0;;$i++) { 57 $dayOfMonth = strtotime("+{$i} month", $startMonthDayTime);//每月x號 58 if ($dayOfMonth > $endTime) { 59 break; 60 } 61 $list[] = date('Y-m-d', $dayOfMonth); 62 } 63 64 return $this->getExedate($start, $end, $list); 65 66 } 67 68 /** 69 * desc 返回順延后的執行日期列表 70 * @param string $start 開始日期, 2016-10-17 71 * @param string $end 結束日期, 2016-10-17 72 * @param array $planDate 73 * @return array 74 */ 75 public function getExedate($start, $end, $planDate) 76 { 77 //獲取所有交易日 78 $allTradeDate = $this->getTradeDate($start, $end); 79 80 //取最后一個交易日 81 $endTradeDate = end($allTradeDate); //返回格式: ['2016-11-01' => '2016-11-01', '2016-11-02' => '2016-11-02', ...], 有冗余,方便編程 82 83 $exeDate = []; //順延后的執行日期 84 foreach ($planDate as $date) { 85 if (!empty($allTradeDate[$date])) { 86 $exeDate[$date] = $date; 87 } else { //沒找到, 需要往后順延到下一個交易日 88 $exeDate[$date] = ''; 89 90 $endTradeTime = strtotime($endTradeDate); 91 $currentTime = strtotime($date); 92 93 for ($i=$currentTime; $i<=$endTradeTime; $i+=86400) {//一天一天往后順延, 直到找到下一個交易日, 直到數據庫存儲的最后一個交易日 94 $tmpDate = date('Y-m-d', $i); 95 if (!empty($allTradeDate[$tmpDate])) { //找到就退出循環 96 $exeDate[$date] = $tmpDate; 97 break; 98 } 99 } 100 } 101 } 102 103 return $exeDate; 104 }
其中:
1 public static $WORK_DAY = [ 2 1 => ['en' => 'Monday', 'cn' => '一'], 3 2 => ['en' => 'Tuesday', 'cn' => '二'], 4 3 => ['en' => 'Wednesday', 'cn' => '三'], 5 4 => ['en' => 'Thursday', 'cn' => '四'], 6 5 => ['en' => 'Friday', 'cn' => '五'] 7 ];