You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fix DST fall-back scheduling gap for high-frequency cron patterns (#344)
* Initial plan
* Fix DST fall-back scheduling gap for per-second and per-minute cron patterns
During DST fall-back transitions, cron jobs with high-frequency patterns
(per-second, per-minute) would experience a ~1 hour scheduling gap. This
was caused by the local time increment skipping over the second occurrence
of the overlap period.
Changes:
- Add afterMs field to CronDate for DST overlap resolution
- Improve fromTZ overlap detection to check both earlier and later times
- Add DST overlap fix in _next() to detect and handle UTC time jumps
- Preserve original UTC time in CronDate.fromDate() for correct round-trips
- Add 3 new test cases for DST fall-back behavior
Co-authored-by: Hexagon <419737+Hexagon@users.noreply.github.com>
* Clarify DST overlap handling for high-frequency vs specific-time patterns in docs
Updated pattern documentation in both README.md and docs/src/usage/pattern.md
to explain that DST overlap behavior differs by pattern type:
- Specific-time patterns (e.g. 0 30 2 * * *): run once at first occurrence
- High-frequency patterns (e.g. * * * * *): continue executing without gaps
Co-authored-by: Hexagon <419737+Hexagon@users.noreply.github.com>
* Bump version to 10.0.2-dev.0
Co-authored-by: Hexagon <419737+Hexagon@users.noreply.github.com>
* Fix fromTZ JSDoc for afterMs edge case and improve test comment clarity
- Clarified afterMs JSDoc to document behavior when both DST occurrences
are before the threshold (returns second/later occurrence as closest option)
- Fixed misleading test comment to use explicit UTC instants (08:59Z → 09:00Z)
Co-authored-by: Hexagon <419737+Hexagon@users.noreply.github.com>
* Copy afterMs in fromCronDate to preserve DST overlap context across CronDate cloning
Co-authored-by: Hexagon <419737+Hexagon@users.noreply.github.com>
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Hexagon <419737+Hexagon@users.noreply.github.com>
Copy file name to clipboardExpand all lines: README.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -199,7 +199,7 @@ Croner uses [Vixie Cron](https://en.wikipedia.org/wiki/Cron#CRON_expression) bas
199
199
***Enhanced logical control**:
200
200
-*+*: Explicit AND logic modifier. Prefix the day-of-week field with `+` to require both day-of-month AND day-of-week to match. Example: `0 12 1 * +MON` only triggers when the 1st is also a Monday.
201
201
-*?*: Wildcard alias (behaves identically to `*`). **Non-portable**: Its use is discouraged in patterns intended for cross-system use. Supported in all fields for compatibility, but primarily meaningful in day-of-month and day-of-week fields.
202
-
- Proper DST handling: Jobs scheduled during DST gaps are skipped; jobs in DST overlaps run once at first occurrence.
202
+
- Proper DST handling: Jobs scheduled during DST gaps are skipped. During DST overlaps (fall-back), specific-time patterns (e.g. `0 30 2 * * *`) run once at the first occurrence; high-frequency patterns (e.g. `* * * * *`) continue executing without gaps.
203
203
204
204
* Croner allows you to pass a JavaScript Date object or an ISO 8601 formatted string as a pattern. The scheduled function will trigger at the specified date/time and only once. If you use a timezone different from the local timezone, you should pass the ISO 8601 local time in the target location and specify the timezone using the options (2nd parameter).
Copy file name to clipboardExpand all lines: docs/src/usage/pattern.md
+3-1Lines changed: 3 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -35,7 +35,9 @@ Croner is fully compliant with the [Open Cron Pattern Specification (OCPS)](http
35
35
***OCPS 1.4**: Enhanced logical control:
36
36
-*+*: Explicit AND logic modifier. Prefix the day-of-week field with `+` to require both day-of-month AND day-of-week to match. Example: `0 12 1 * +MON` only triggers when the 1st is also a Monday.
37
37
-*?*: Wildcard alias (behaves identically to `*`). **Non-portable**: Its use is discouraged in patterns intended for cross-system use. Supported in all fields for compatibility, but primarily meaningful in day-of-month and day-of-week fields.
38
-
- Proper DST handling: Jobs scheduled during DST gaps are skipped; jobs in DST overlaps run once at first occurrence.
38
+
- Proper DST handling: Jobs scheduled during DST gaps are skipped. During DST overlaps (fall-back), behavior depends on the pattern:
39
+
-**Specific-time patterns** (e.g. `0 30 2 * * *`): Run once at the first occurrence of the ambiguous time, per OCPS 1.4 §4.3.1.
40
+
-**High-frequency patterns** (e.g. `* * * * *`, `* * * * * *`): Continue executing through the overlap period without gaps. Each tick advances by the expected interval in UTC, so no executions are skipped or duplicated.
39
41
40
42
* Croner allows you to pass a JavaScript Date object or an ISO 8601 formatted string as a pattern. The scheduled function will trigger at the specified date/time and only once. If you use a timezone different from the local timezone, you should pass the ISO 8601 local time in the target location and specify the timezone using the options (2nd parameter).
0 commit comments