我需要开发一个能够在不支持crontab的服务器上工作的任务系统。
我问是否有任何现有代码可以接受cron字符串(例如'0 0,12 1 * / 2 *'并返回下一次计划运行的时间戳。
如果找不到这样的代码,那我该怎么做呢?
答案 0 :(得分:12)
您可以使用此课程PHP-Parse-cron-strings-and-compute-schedules
它还会计算最后一次预定的运行
答案 1 :(得分:8)
使用此功能:
function parse_crontab($time, $crontab)
{$time=explode(' ', date('i G j n w', strtotime($time)));
$crontab=explode(' ', $crontab);
foreach ($crontab as $k=>&$v)
{$time[$k]=intval($time[$k]);
$v=explode(',', $v);
foreach ($v as &$v1)
{$v1=preg_replace(array('/^\*$/', '/^\d+$/', '/^(\d+)\-(\d+)$/', '/^\*\/(\d+)$/'),
array('true', $time[$k].'===\0', '(\1<='.$time[$k].' and '.$time[$k].'<=\2)', $time[$k].'%\1===0'),
$v1
);
}
$v='('.implode(' or ', $v).')';
}
$crontab=implode(' and ', $crontab);
return eval('return '.$crontab.';');
}
var_export(parse_crontab('2011-05-04 02:08:03', '*/2,3-5,9 2 3-5 */2 *'));
var_export(parse_crontab('2011-05-04 02:08:03', '*/8 */2 */4 */5 *'));
答案 2 :(得分:3)
你可以试试这个:http://mtdowling.com/blog/2012/06/03/cron-expressions-in-php/使用PHP Cron-Expression解析器库,一个php类https://github.com/mtdowling/cron-expression
答案 3 :(得分:2)
我发现diyism有一个很好的答案,但发现了一个关键的错误。
如果输入0 * * * *
等cron时间,它将在0分钟,8分钟,9分钟和第9分钟运行。代码给出一个条件08===0
,它返回true,因为PHP将以0开头的数字解释为八进制,而08和09不是有效的八进制数,因此它们被解释为0.更多信息在这里。
How to prevent PHP from doing octal math in conditionals? (why does 08 === 0)
这是一个固定且评论很好的diyism代码版本。
// Parse CRON frequency
function parse_crontab($time, $crontab) {
// Get current minute, hour, day, month, weekday
$time = explode(' ', date('i G j n w', strtotime($time)));
// Split crontab by space
$crontab = explode(' ', $crontab);
// Foreach part of crontab
foreach ($crontab as $k => &$v) {
// Remove leading zeros to prevent octal comparison, but not if number is already 1 digit
$time[$k] = preg_replace('/^0+(?=\d)/', '', $time[$k]);
// 5,10,15 each treated as seperate parts
$v = explode(',', $v);
// Foreach part we now have
foreach ($v as &$v1) {
// Do preg_replace with regular expression to create evaluations from crontab
$v1 = preg_replace(
// Regex
array(
// *
'/^\*$/',
// 5
'/^\d+$/',
// 5-10
'/^(\d+)\-(\d+)$/',
// */5
'/^\*\/(\d+)$/'
),
// Evaluations
// trim leading 0 to prevent octal comparison
array(
// * is always true
'true',
// Check if it is currently that time,
$time[$k] . '===\0',
// Find if more than or equal lowest and lower or equal than highest
'(\1<=' . $time[$k] . ' and ' . $time[$k] . '<=\2)',
// Use modulus to find if true
$time[$k] . '%\1===0'
),
// Subject we are working with
$v1
);
}
// Join 5,10,15 with `or` conditional
$v = '(' . implode(' or ', $v) . ')';
}
// Require each part is true with `and` conditional
$crontab = implode(' and ', $crontab);
// Evaluate total condition to find if true
return eval('return ' . $crontab . ';');
}
答案 4 :(得分:0)
在parse_crontab
函数中:
将$time[$k]
替换为intval($time[$k])
行内的preg_replace
正确比较两个base10
数字。
答案 5 :(得分:0)
很久以前我写了一个名为CalendarEvent的非常强大的PHP类:
https://github.com/cubiclesoft/php-misc/
它支持两种不同的模式语法。普通的cron无法处理某些复杂的模式,而默认的CalendarEvent语法会处理您可能需要的任何调度模式。 cron模式语法支持实际上是一个回退(带有cron
和空格的前缀cron行。)
CalendarEvent主要是作为日历事件计算类编写的,恰好支持cron风格的“下一个触发器”机制。实际上,它旨在计算多个月的整个计划,以便向用户显示日历(因此是类名)。我还使用该类作为在日历平台之间转换事件的中间解决方案。这是最罕见的情况 - 我更频繁地将它用于AddSchedule()/ NextTrigger()类似cron的解决方案。
答案 6 :(得分:0)
您可以使用流行的软件包 PHP Cron Expression Parser :https://github.com/dragonmantank/cron-expression
这也是Laravel框架的内置部分)