PHP函数,它接收一个cron字符串并返回下一个运行时间戳

时间:2011-01-03 19:05:36

标签: php cron scheduled-tasks scheduling crontab

我需要开发一个能够在不支持crontab的服务器上工作的任务系统。

我问是否有任何现有代码可以接受cron字符串(例如'0 0,12 1 * / 2 *'并返回下一次计划运行的时间戳。

如果找不到这样的代码,那我该怎么做呢?

7 个答案:

答案 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框架的内置部分)