我希望从Cron Format的给定字符串中获取下一个运行cron 的日期seconds
参数(不完全等于cron格式)。
我的代码:
$cron_format = explode(" ", "00 00 00 01 * *"); // <second> <minute> <hour> <day> <month> <week_day>
$date_diff = explode(" ", "s i H d m w"); // php Date @link http://php.net/manual/en/function.date.php
$format = [];
foreach( $date_diff as $key=>$value) {
$format[$value] = $cron_format[$key] !== "*" ? date($value, strtotime($cron_format[$key])) : date($value);
}
$spf = sprintf(
"%s-%s-%s %s:%s:%s",
date("Y"), $format["m"], $format["d"], $format["H"], $format["i"], $format["s"]
);
$date = DateTime::createFromFormat("Y-m-d H:i:s", $spf);
// returns 2018-03-01 00:00:00, expected was 2018-04-01 00:00:00
echo $date->format("Y-m-d H:i:s");
它按预期显示2018-03-01 00:00:00
,但我要找的是获得下一个Crontab运行日期(2018-04-01 00:00:00)
的方法。
设置添加月份的方法无法解决问题,因为 cron格式可以按小时设置,如下:
<second> <minute> <hour> <day> <month> <week_day>
00 00 * * * *
答案 0 :(得分:13)
无需为此编写更多代码。请使用下面的库来做到这一点
https://github.com/mtdowling/cron-expression
用法:
<?php
// Works with cron expression
$cron = new Cron\CronExpression::factory('15 2,6-12 */15 1 *');
$cron->getNextRunDate();
答案 1 :(得分:6)
我玩了一下,这是我的结果作为一个功能。基本上我拆分元素,检查通配符的值。如果找到它将忽略所有其他通配符并使用第一个通配符+1设置元素的值。此外,我检查d和m的零值,如果发现它们被值1替换。最后检查,如果当前年份的日期小于当前日期。如果是,它将使用当前年份,如果没有它将使用下一年。
function calculate_next_cronjob($cronjob, $elementpositions){
$wildcard = false;
$elements = preg_split('/[^\d*]+/', $cronjob);
foreach(preg_split('/[^a-z]+/i', $elementpositions) as $key => $element){
$value[$element] = $elements[$key];
switch($element){
case 's':
if($value[$element] == '*'){
$value[$element] = date('s') + 1;
$wildcard = true;
}
break;
case 'i':
if($value[$element] == '*'){
$value[$element] = date('i') + ($wildcard === true ? 0 : 1);
$wildcard = true;
}
break;
case 'H':
if($value[$element] == '*'){
$value[$element] = date('H') + ($wildcard === true ? 0 : 1);
$wildcard = true;
}
break;
case 'd':
if($value[$element] == '*'){
$value[$element] = date('d') + ($wildcard === true ? 0 : 1);
$wildcard = true;
}
if(intval($value[$element]) == 0){
$value[$element] = 1;
}
break;
case 'm':
if($value[$element] == '*'){
$value[$element] = date('m') + ($wildcard === true ? 0 : 1);
$wildcard = true;
}
if(intval($value[$element]) == 0){
$value[$element] = 1;
}
break;
default:
unset($value[$element]);
}
}
$cy = date('Y');
$ny = $cy + 1;
if(time() < mktime($value['H'], $value['i'], $value['s'], $value['m'], $value['d'], $cy)){
$value['Y'] = $cy;
}else{
$value['Y'] = $ny;
}
return date('Y-m-d H:i:s', mktime($value['H'], $value['i'], $value['s'], $value['m'], $value['d'], $value['Y']));
}
Testrun:
$cronjobs = array();
$cronjobs[] = array('00 00 00 00 * 00', 's i H d m N');
$cronjobs[] = array('00 00 00 * * 00', 's i H d m N');
$cronjobs[] = array('00 00 * * * 00', 's i H d m N');
$cronjobs[] = array('00 * * * * 00', 's i H d m N');
$cronjobs[] = array('* * * * * 00', 's i H d m N');
echo '<table>';
foreach($cronjobs as $data){
echo '<tr><td>';
echo $data[0];
echo '</td><td>';
echo $data[1];
echo '</td><td>';
echo calculate_next_cronjob($data[0], $data[1]);
echo '</td></tr>';
}
echo '</table>';
输出:
00 00 00 00 * 00 s i H d m N 2018-05-01 00:00:00
00 00 00 * * 00 s i H d m N 2018-04-17 00:00:00
00 00 * * * 00 s i H d m N 2018-04-16 09:00:00
00 * * * * 00 s i H d m N 2018-04-16 08:25:00
* * * * * 00 s i H d m N 2018-04-16 08:24:59