Closed delphimat closed 1 year ago
I am also seeing this error 30 18 21-31 * */6
This Cron should run the first Saturday of the month at 18:30. https://crontab.guru/#30_18_21-31_*_*/6
But the NextRunDate calculates as date: 2022-07-21 18:30:00.0 Europe/London (+01:00)
which is also a Thursday.
Is there any workaround @dragonmantank ?
$cron = new Cron\CronExpression('10 0 * */3 *');
echo $cron->getNextRunDate('now')->format('Y-m-d H:i:s');
always give the next day (2022-10-08 00:10:00), but */3 is every 3 months.
If I specify a day of month, then it does say January, but if I change the month to any other (/4, /6), it gives a random month, someimes January, sometimes Novmber this year.
tl;dr - Due to the POSIX standard, when Day of Month and Day of Week are both specified they are evaluated as an OR, not an AND. This leads to unexpected results.
Part of this is because of the way Day of Month and Day of Week work when combined. cronie, which is the implementation this most closely follows, treats both values as an OR, not an AND.
Given the following expression:
0 0 1-7,14-21 * Wed
This will evaluate as "Any Day of Month in [1,2,3,4,5,6,7,14,15,16,17,18,19,20,21] OR a Wednesday". For example, "2023-08-02" is valid because it works with both constraints, and "2023-08-03" is valid because it works with the Day of Month constraint. "2023-08-09" would be valid because it is a Wednesday, but "2023-08-10" would be invalid because it is not in the Day of Month range or a Wednesday.
Why is this an OR comparison instead of an AND?
Because that's the POSIX Standard. Granted, no one really knows the original reasoning, but for compatibility I followed the POSIX standard.
always give the next day (2022-10-08 00:10:00), but */3 is every 3 months.
As another important distinction, because once again cron doesn't always do what we expect, X/X
is a step call. It evaluates to "Given this range, start here and step X times to get the next value." It isn't technicaly "every three months" as in like a calendar quarter.
*/3
evaluates as 1-12/3
, so will start at 1 (January). Then step 3 to April (1+3=4, so April). Then step 3 to July (4+3=7). The important part is that it starts at the beginning of the range, not steps before determining a starting point.
So if we expand out '10 0 * */3 *'
, that evaluates as "The 10th minute of the 0th hour, every day of the month for months 1,4,7,10 on every day of the week". January dates would be fully valid. If you want a truly quarterly/financial date run, you are better off setting the month to 3,6,9,12
instead of a step call.
The purpose of this CRON expression is to run every 2 weeks with a specific day. ( on my example i have Wednesday )
Today we are the 18 may 2022.
cronExpressionWeekly = "0 0 1-7,14-21 * Wed"
(new CronExpression($cronExpressionWeekly))->getNextRunDate('now')->format('d.m.Y')
the result return 2022-05-19 00:00:00 which is a Thursday. the cron expression is not respected at all.
I believe the issue is about the range. 1-7,14-21