mtdowling / cron-expression

CRON for PHP: Calculate the next or previous run date and determine if a CRON expression is due
http://mtdowling.com/blog/2012/06/03/cron-expressions-in-php/
MIT License
4.9k stars 335 forks source link

impossible cron issue #82

Closed patrioticcow closed 9 years ago

patrioticcow commented 9 years ago

this cron 13 14 3 2 3 throws the impossible cron exception

if i test it ( http://cron.schlitt.info/index.php?cron=13+14+3+2+3&iterations=10&test=Test ), i should get:

2016-02-03 14:13:00
2016-02-10 14:13:00
2016-02-17 14:13:00
2016-02-24 14:13:00
2017-02-01 14:13:00
2017-02-03 14:13:00
2017-02-08 14:13:00
2017-02-15 14:13:00
2017-02-22 14:13:00
2018-02-03 14:13:00
...
mtdowling commented 9 years ago

This site reports the cron expression as invalid: http://www.cronmaker.com/

I wonder if the test site you're using is working correctly.

patrioticcow commented 9 years ago

well, im trying to do a cron: At 14:13 on the 3rd during every February but only if the event takes place on Wednesdays. that seems the right cron..

if i replace the last 3 with * then there is no exception, but i need it every Wednesdays

if i use that website, i get 0 13 14 ? 1/3 WED#3 * but the script gives Invalid CRON field value ? as position 3

swekaj commented 9 years ago

That's also an invalid CRON for this library for two reason: it appears to have a 'seconds' field and it uses ? instead of *

Your original expressions should be valid, but it won't match what you want (as indicated by the CRON tester output). I'm pretty sure you'd have to use 13 14 2 3 3#1 * to match only the first Wednesday, however I can't seem to find a cron tester online that supports (and recognizes) the #1 bit.

@mtdowling I'm pretty sure that http://www.cronmaker.com/ is broken. I tried * * * * * and it said the expression was invalid.

swekaj commented 9 years ago

@patrioticcow, are you sure you're using the most recent version? It works fine for me on 1.0.4:

$ php -a
Interactive mode enabled

php > require(__DIR__.'/vendor/autoload.php');
php > $c = Cron\CronExpression::factory('13 14 3 2 3');
php > print_r($c->getNextRunDate());
DateTime Object
(
    [date] => 2016-02-03 14:13:00.000000
    [timezone_type] => 3
    [timezone] => UTC
)
patrioticcow commented 9 years ago

try tunning

foreach ($cron->getMultipleRunDates(5, 'now') as $date) {
    if($date) var_dump($date);
}
swekaj commented 9 years ago

That threw the exception you reported. If you change it to get each run date individually (instead of all 5 at once), then you can see that there are no more occurrences beyond 2027 that are within the testable range. That limit is imposed by the library to prevent cron schedules that will never be due causing an infinite loop.

That said, you can get around the limit with something like the following:

$dates = array();
for ($i = 0; $i <= 5; $i++) {
    $date = $i === 0 ? null : $dates[$i - 1];
    $dates[] = $cron->getNextRunDate($date, 0);
}
patrioticcow commented 9 years ago

it looks like i have to do lots of testing, when creating the cron to begin with, and make sure the this lib supports it.

Thanks

swekaj commented 9 years ago

The weird dates are because February 3rd only falls on a Wednesday every 5 - 7 years. If you wanted every Wednesday after the third of February, then the cron would be something like 13 14 3-29 2 3