Ответ 1
Вы можете использовать этот класс PHP-Parse-cron-strings-and-compute-schedules
Он также рассчитает последний запланированный прогон
Мне нужно разработать систему задач, которая должна работать на серверах, которые не поддерживают crontab.
Я спрашиваю, существует ли какой-либо существующий код, который может взять строку cron (например, "0 0,12 1 */2 *" и вернуть временную метку следующего запланированного прогона.
Если такой код не найден, то как мне начать с этого?
Вы можете использовать этот класс 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].'===\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 *'));
Вы можете попробовать следующее: http://mtdowling.com/blog/2012/06/03/cron-expressions-in-php/, в которых используется библиотека парсеров PHP Cron-Expression, класс php https://github.com/mtdowling/cron-expression
Я обнаружил, что дийизм имеет отличный ответ, но нашел ключевую ошибку.
Если вы введете время cron, например 0 * * * *
, оно будет работать через 0 минут, 8, минуту и 9 минут. Код дает условный 08===0
, который возвращает true, потому что PHP интерпретирует числа, начинающиеся с 0, как восьмеричные, и 08 и 09 не являются допустимыми восьмеричными числами, поэтому они интерпретируются как 0. Более подробная информация здесь.
Как предотвратить PHP от выполнения восьмеричной математики в условных выражениях? (почему 08 === 0)
Здесь фиксированная и хорошо прокомментированная версия кода дииизма.
// 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 . ';');
}
В функции parse_crontab
:
Замените $time[$k]
на intval($time[$k])
внутри строки preg_replace
для сравнения двух чисел base10
.
Я написал очень мощный PHP-класс, называемый CalendarEvent, давным-давно:
https://github.com/cubiclesoft/php-misc/
Он поддерживает два разных синтаксиса шаблонов. Обычный cron не может обрабатывать определенные сложные шаблоны, тогда как синтаксис CalendarEvent по умолчанию обрабатывает любой шаблон планирования, который вам когда-либо понадобится. Поддержка синтаксиса шаблона cron на самом деле является резервным (префикс cron lines с cron
и пробелом).
CalendarEvent был написан в основном как класс вычисления событий календаря и только что получил поддержку механизмов "следующего триггера" в стиле cron. Он на самом деле предназначен для вычисления всего графика в течение нескольких месяцев с целью отображения календаря пользователю (отсюда и название класса). Я также использовал этот класс в качестве промежуточного решения для перевода событий между платформами календаря. Что более редкий сценарий - я чаще использовал его для решений, связанных с Cron-способом AddSchedule()/NextTrigger().