All changes come from #360
Changelog
- BREAKING CHANGE: Bumped the minimum Node.js version to >= 18 and TypeScript to >= 5.
- BREAKING CHANGE:
interval.fields
(CronExpression.interval
) now returns a readonly instance ofCronFieldsCollection
instead of a regular array. SeeCronFieldsCollection.from
for how to modify the underlying data structure. - BREAKING CHANGE: Moved crontab file parsing from
CronParser
to a standaloneCronFileParser
class (fixes #112). - Refactored the codebase to TypeScript (fixes #190).
- Cleaned up test suites, removed duplicate test cases, and switched from
tap
tojest
. - Improved documentation and introduced documentation generated by
typedoc
(fixes #309, #322, #269). - Added benchmark tooling to help detect future performance regressions.
- Added
CronExpression.includesDate
to evaluate whether a given date matches the pattern (closes #299). - Fixed issues where certain range and repeat field expressions produced invalid intervals (fixes #156).
- Fixed an issue with day-of-month handling when the range is explicitly set and no wildcard is used (fixes #284).
- Improved repeat serialization for stringification (fixes #236).
Performance improvements
While this release won't address the performance issues reported in #287, it will bring some performance improvements of around 20-30% on average, depending on the pattern complexity. The following benchmark results were produced on my 2023 MBP.
┌────────────────────┬────────────┬────────────┬──────────┬─────┐ │ Pattern │ Old Mean │ New Mean │ Change │ │ ├────────────────────┼────────────┼────────────┼──────────┼─────┤ │ * * * * * * │ 73.55ms │ 37.43ms │ 49.10% │ ↑ │ ├────────────────────┼────────────┼────────────┼──────────┼─────┤ │ 0 * * 1,4-10,L * * │ 3504.51ms │ 2338.42ms │ 33.27% │ ↑ │ ├────────────────────┼────────────┼────────────┼──────────┼─────┤ │ 10-30/2 2 12 8 0 │ 3111.18ms │ 2234.32ms │ 28.18% │ ↑ │ ├────────────────────┼────────────┼────────────┼──────────┼─────┤ │ 0 0 0 * * 4,6L │ 9400.33ms │ 6825.61ms │ 27.39% │ ↑ │ ├────────────────────┼────────────┼────────────┼──────────┼─────┤ │ 0 12 */5 6 * │ 7442.68ms │ 5645.95ms │ 24.14% │ ↑ │ ├────────────────────┼────────────┼────────────┼──────────┼─────┤ │ 0 15 */5 5 * │ 6998.87ms │ 5443.22ms │ 22.23% │ ↑ │ ├────────────────────┼────────────┼────────────┼──────────┼─────┤ │ 0 0 6-20/2,L 2 * │ 8832.87ms │ 6947.63ms │ 21.34% │ ↑ │ ├────────────────────┼────────────┼────────────┼──────────┼─────┤ │ 0 0 0 * * 1L,5L │ 15416.07ms │ 12474.12ms │ 19.08% │ ↑ │ ├────────────────────┼────────────┼────────────┼──────────┼─────┤ │ 10 2 12 8 7 │ 7105.79ms │ 5947.91ms │ 16.29% │ ↑ │ └────────────────────┴────────────┴────────────┴──────────┴─────┘
Benchmarks can be run locally by executing the command.:
npm run bench
Individual patterns can be benchmarked by executing bench:pattern
command:
npm run bench:pattern "* * * * * *"