HangfireIO / Cronos

A fully-featured .NET library for working with Cron expressions. Built with time zones in mind and intuitively handles daylight saving time transitions
MIT License
1.01k stars 118 forks source link

Cron job run every three (or n) days? #9

Closed leafduan closed 6 years ago

leafduan commented 6 years ago

I want to run a job every three or five (or n) days from now, and I wrote the expression '0 8 /5 *'.

If now is '2018/05/17',

and I get the occurrences:

0 8 */5 * *
2018/5/21 8:00:00
2018/5/26 8:00:00
2018/5/31 8:00:00
2018/6/1 8:00:00
2018/6/6 8:00:00
2018/6/11 8:00:00
2018/6/16 8:00:00
2018/6/21 8:00:00
2018/6/26 8:00:00
2018/7/1 8:00:00
2018/7/6 8:00:00
2018/7/11 8:00:00
2018/7/16 8:00:00
2018/7/21 8:00:00
2018/7/26 8:00:00
2018/7/31 8:00:00
2018/8/1 8:00:00
2018/8/6 8:00:00

but, which I expected are:

0 8 */5 * *
2018/5/22 8:00:00     -- wrong
2018/5/27 8:00:00     -- wrong
2018/6/1 8:00:00
2018/6/6 8:00:00
2018/6/11 8:00:00
2018/6/16 8:00:00
2018/6/21 8:00:00
2018/6/26 8:00:00
2018/7/1 8:00:00
2018/7/6 8:00:00
2018/7/11 8:00:00
2018/7/16 8:00:00
2018/7/21 8:00:00
2018/7/26 8:00:00
2018/7/31 8:00:00
2018/8/5 8:00:00      -- wrong
2018/8/10 8:00:00     -- wrong

Do the cron expression that I wrote is wrong? Or the Cronos don't support this situation?

Any one help me?

Thanks, Leaf

odinserj commented 6 years ago

Cron expressions are never calculated based on the current time, so May 21, 2018 date will always match the 0 8 */5 * * expression, regardless you are asking to get ones since May 1, May 3, May 13, etc. You can consider Cron expressions as regular expressions, but for date/time values: their output is stable.

Simply speaking, every cron parsing algorithm looks like the following loop:

var data = startDate;
while (date < endDate)
{
    if (IsMatch(date, cronExpression))
    {
        yield return date;
    }

    date = date.AddSeconds(1); // Or minutes
}

And if you need to get occurrences every 3 days or so, the best term is to make your own loop and use the DateTime.AddDays method instead.

leafduan commented 6 years ago

Hi odinserj,

Thank you for your comment.

And I catch the same idea with you, override the get occurrences loop, using DateTime.AddDays instead.