<?php/** * Created by PhpStorm. * User: duyue * Date: 2018/2/20 * Time: 23:10 * 此類僅用於判斷給定的時間是否符合時間規則,如果符合則返回true其它商務邏輯自行處理 * 使用說明 * format = '* * * * * '; * 本類模仿crond的規則分5個部分分別是分、時、日期、月、周(的第幾天) * 每部分可單獨設定為一個數,如:1 * * * * ,當分為1時 true * 可以使用 '/' 來分開設定重複規則,如: * / 1 * * * * , 每分鐘 ; * / 2 * * * * 每兩分鐘(注意每部分之間是沒有空格的,這裡是PHP的注釋部分) * 可以設定區間: 4-20/2 * * * * , 當分為4 - 20之間,並且為2的倍數時 * 可以為集合: * /5,8,10 * * * * , 當分為5,8,10時返回true,其它部分同理。 * '0 23 * * 6' 每周六的11點 * '* 23-7/1 * * * ' 每天晚上23-7點,每隔一小時 */namespace app\extend;class CrondTime{public static function check($format,$check_time = 0){$time = intval($check_time) > 0 ? $check_time : time();$cNumber = [date('i',$time), //分 0 - 59date('H',$time), //時 0 - 23date('j',$time), //日期, 1- 31date('m',$time), //月 1 - 12date('w',$time), //周 星期中的第幾天 0(周日)至6(周六)];$cronArr = explode(' ',$format);//逐個檢查,非*全符合則返回true,否則返回falsefor($i = 0; $i<5;$i++){if($cronArr[$i] == '*' || empty($cronArr[$i])) continue;if(self::checkNumber($cNumber[$i],$cronArr[$i]) === false){return false;}}return true;}/** * 檢查一個數字是否符合 * @param $number 要檢查的數字 * @param $str 規則字元 * @return bool 符合返回true */private function checkNumber($number,$str){if(strpos($str,'/') === false && strpos($str,',') === false && strpos($str,'-') === false){//單數if($number == $str) return true;return false;}//檢查是否含有'/'if(strpos($str,'/') === false){//不含'/'if(strpos($str,',') !== false){//集合if(in_array($number,explode(',',$str))) return true;return false;}if(strpos($str,'-') !== false){//區間$areaArr = explode('-',$str);$min = intval(trim($areaArr[0]));$max = intval(trim($areaArr[1]));if($number >= $min && $number <= $max) return true;return false;}}else{//有 '/' ,分左右兩部分,左邊檢查集合、區間。右側檢查餘數是否為0$leftCheck = $rightCheck = false;$tmp = explode('/',$str);$leftStr = $tmp[0];$rightStr = $tmp[1];//如果左側是*的話,右側為數字則模數$leftCheck = self::checkLevel3($number,$leftStr,true);$rightCheck = self::checkLevel3($number,$rightStr,false);if($leftCheck===true && $rightCheck === true) return true;return false;}}/** * 檢查3級字元 * @param $number * @param $str * @param bool $is_left * @return bool */private function checkLevel3($number,$str,$is_left = false){if($str === '*') return true;//三級中已經沒有 '/' ,只需要檢查是否是單數、集合、區間。if(strpos($str,',') === false && strpos($str,'-') === false){if($is_left === true){if($number == $str) return true;return false;}else{//echo $number;exit();//右側單數,進行模數運算if($number%$str == 0) return true;return false;}}if(strpos($str,',') !== false){//集合if(in_array($number,explode(',',$str))) return true;return false;}if(strpos($str,'-') !== false){//區間$areaArr = explode('-',$str);$min = intval(trim($areaArr[0]));$max = intval(trim($areaArr[1]));if($number >= $min && $number <= $max) return true;return false;}}}
這裡使用的命名空間,複製的時候稍注意一點。
防linux crond 時間規則演算法,初步測試暫未發現什麼問題。如果你發現的BUG歡迎留言。