Croner 11.0.1 is a maintenance release that tightens up 11.0.0: stricter pattern parsing that rejects malformed input instead of guessing, a new fixedTimeRule option for Vixie-style DST handling of lists and ranges, faster job creation, and a round of fixes to previousRuns(), the interval option and early-year dates, many of them from first-time contributors.
Added
fixedTimeRuleoption, which selects which jobs are fixed-time jobs in DST handling. The
default,"single-value", is unchanged and the same as croner-rust. With"no-wildcard", a job
without a wildcard (*or?) or step in seconds, minutes and hours is a fixed-time job, so
30 2,14 * * *runs at the end of a DST gap and once in a DST overlap, close to Vixie cron,
reported by @sscarduzio in #438.
Changed
previousRuns()without a reference counts from now, including the milliseconds, so called
from inside a callback it returns the run that just started. Before, it returned the run before
that.previousRuns(2)[1]gives the scheduled time of the run before, andpreviousRun()still
gives the time it started. With theintervaloption,previousRuns()returns runs at least
intervalseconds before the reference, so not the run that just started.- Creating a job is 55-64% faster. Each pattern filled its 10,000-entry year array two times, and
each job also parsed a default pattern that only date-based jobs use, by @g4lb in #453.
Fixed
previousRuns()skipped a run in the same second as the reference when the reference had
milliseconds, so* * * * * *from00:00:05.500returned00:00:04instead of00:00:05.
This also applies to a string reference in a named timezone, whose milliseconds were dropped.
Withinterval: 1, the run in the same second is less than a second before the reference and is
not returned, the same as with a longer interval, by @Kernel-Hunter in #454.msToNext()from a string reference in a named timezone, such as"2025-01-02T00:00:05.500Z"
withtimezone: "UTC", dropped the milliseconds of the reference and returned up to 999 ms too
much.- A number in a pattern has to be digits only. What came after a number was ignored, so
3*meant
3,15W5meant15W,5##2and5L#2meant5and5#2, and anLanywhere in
day-of-month was dropped, so5Lmeant the 5th and the last day. These patterns throw now. Valid
patterns are not affected, by @simonkundrik in #451. - A month or day name has to stand alone in a pattern. It was replaced by its number wherever it
was, soSUN6meant6,JANFEBmeant12and*/FRImeant*/5. These patterns throw now.
Valid patterns are not affected, by @simonkundrik in #455. - The docs no longer say that DST handling is the same as Vixie cron for lists and ranges. Vixie
cron treats them as fixed-time jobs, Croner treats them as interval jobs by default, reported by
@sscarduzio in #438. @weeklywithalternativeWeekdays: truethrewRangeError: CronPattern: Invalid value for dayOfWeek: -1. It now runs on Sundays, as without the option and as in croner-rust.- Matching a day past the end of a month no longer skips valid runs when day-of-month and
day-of-week conditions use OR logic, by @mmporong in #437. - Calendar traversal preserves years 1-99 instead of interpreting them as 1901-1999, including
weekday modifiers, leap days, local dates and timezone conversion, by @mayankdhingra02 in #431. - A
catchcallback that returns a rejected promise (anasynccallback that throws) no longer
causes an unhandled rejection. The callback is still not awaited, so a pending callback does not
delaytrigger()or keep aprotected job busy. Thrown errors were ignored since #337, but only
when thrown synchronously, by @jipeng6036-del in #427. previousRuns()no longer skips nearest weekday (W) days that fall after the highest plain
day-of-month in the pattern. With0 0 0 15,30W * *, only the 15th was found when going
backwards into a new month.- The
intervaloption now counts elapsed time, so a DST change in between no longer shortens or
stretches it. Before, the interval was added to the wall clock: after a spring forward the next
run could come minutes after the last one instead ofintervalseconds, in a repeated hour it
ignored the interval, and a 24 hour interval gave 23 or 25 hours, by @simonkundrik in #450. previousRuns()stops at year 1, the first supported year. With a named timezone, a search that
reached year 0 took minutes for a job that runs every second, and without one it returned runs
in year 0.- The
intervaloption near year 1 or year 9999 uses the year in the timezone of the job. The
year in UTC was used, sonextRun()could returnnullin the hours around new year. LWin a day-of-month list, such as1W,15W,LW, throws an error that saysLWcan not be in a
list. The error said thatLhas to be a value of its own.
New Contributors
- @jipeng6036-del made their first contribution in #427
- @mayankdhingra02 made their first contribution in #431
- @sinzbtw made their first contribution in #432
- @mmporong made their first contribution in #437
- @simonkundrik made their first contribution in #451
- @g4lb made their first contribution in #453
- @Kernel-Hunter made their first contribution in #454
Full Changelog: 11.0.0...11.0.1