Функция PHP, которая получает строку cron и возвращает следующую метку времени выполнения

Мне нужно разработать систему задач, которая должна работать на серверах, не поддерживающих crontab.

Я спрашиваю, есть ли какой-либо существующий код, который может принимать строку cron (например, '0 0,12 1 */2 *-и верните отметку времени следующего запланированного рейса.

Если такой код не найден, то как я должен начать с этого?

6 ответов


вы можете использовать этот класс PHP-Parse-cron-strings-and-compute-schedules

Он также вычислит последний запланированный запуск


использовать эту функцию:

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].'===', '(<='.$time[$k].' and '.$time[$k].'<=)', $time[$k].'%===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 *'));

вы можете попробовать это:http://mtdowling.com/blog/2012/06/03/cron-expressions-in-php/ которые используют библиотеку синтаксического анализатора Cron-Expression PHP, класс phphttps://github.com/mtdowling/cron-expression


я обнаружил, что diyism имеет отличный ответ, но нашел критическую ошибку.

Если вы вводите время cron, такое как 0 * * * *, он будет работать на 0 минуте, 8-й, минутной и 9-й минуте. Код дает условное 08===0, который возвращает true, потому что PHP интерпретирует числа, начинающиеся с 0 как восьмеричные, а 08 и 09 не являются допустимыми восьмеричными числами, поэтому они интерпретируются как 0. Более подробная информация здесь.

как предотвратить PHP от выполнения восьмеричной математики в условных обозначениях? (почему 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] . '===',
                    // Find if more than or equal lowest and lower or equal than highest
                    '(<=' . $time[$k] . ' and ' . $time[$k] . '<=)',
                    // Use modulus to find if true
                    $time[$k] . '%===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 . ';');
}

на :

заменить $time[$k] С intval($time[$k]) внутри preg_replace строка
сравнить два base10 правильно цифры.


Я написал очень мощный класс PHP под названием CalendarEvent давным-давно:

https://github.com/cubiclesoft/php-misc/

Он поддерживает два разных синтаксиса шаблонов. Обычный cron не может обрабатывать определенные сложные шаблоны, тогда как синтаксис CalendarEvent по умолчанию обрабатывает любой шаблон планирования, который вам может понадобиться. Синтаксическая поддержка шаблона cron на самом деле является резервным вариантом (префиксные строки cron с cron и пробела).

CalendarEvent был написан в основном как класс расчета событий календаря и просто поддерживал механизмы "следующего триггера" стиля cron. Он фактически предназначен для расчета всего расписания в течение нескольких месяцев с целью отображения календаря пользователю (отсюда и имя класса). Я также использовал класс в качестве промежуточного решения для перевода событий между платформами календаря. Это более редкий сценарий - я чаще использовал его для AddSchedule()/NextTrigger () cron-like решения.