From 49ce9f94e3c45697089ad8b1a8007f96e13b5c91 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 15 Nov 2025 18:57:08 +0000 Subject: [PATCH 1/7] Initial plan From cc1024640ba0a493efd23ddfca02f63dbd08e63e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 15 Nov 2025 19:00:59 +0000 Subject: [PATCH 2/7] Add clarification on W modifier behavior with non-existing days Co-authored-by: Hexagon <419737+Hexagon@users.noreply.github.com> --- increments/OCPS-increment-1.3.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/increments/OCPS-increment-1.3.md b/increments/OCPS-increment-1.3.md index 4bfa940..cb3f5da 100644 --- a/increments/OCPS-increment-1.3.md +++ b/increments/OCPS-increment-1.3.md @@ -62,3 +62,19 @@ The `W` character can be used in the `Day of Month` field to find the closest we * If the 1st is a Saturday, it triggers on **Monday the 3rd**, as moving to the previous month is not allowed. * **Constraint:** The `W` character is a modifier for a single day and cannot be used with ranges or lists. For example, `1-15W` is an invalid pattern. + +#### 4.3.1. Behavior with Non-Existing Days + +When the `W` modifier is used with a day number that does not exist in a particular month (e.g., `31W` in February, or `30W` in February), the pattern **will not match any date in that month**. The job will not be scheduled to run during months where the specified day does not exist. + +This behavior ensures predictable and consistent scheduling across implementations, avoiding ambiguity about whether to fallback to the last day of the month, skip the month entirely, or use other heuristics. + +* **Example (`31W`):** The pattern `0 12 31W * *` will trigger at noon on the weekday closest to the 31st. + * In months with 31 days (January, March, May, July, August, October, December), it will trigger on the 31st if it's a weekday, or the nearest weekday within that month. + * In months with fewer than 31 days (February, April, June, September, November), **the pattern will not match** and the job will not run in those months. + +* **Example (`30W`):** The pattern `0 0 30W * *` will trigger at midnight on the weekday closest to the 30th. + * In months with 30 or 31 days, it will trigger on the 30th if it's a weekday, or the nearest weekday within that month. + * In February (with 28 or 29 days), **the pattern will not match** and the job will not run. + +**Rationale:** This approach is consistent with the behavior observed in widely-used cron implementations including Quartz Scheduler, Spring Framework, Cronos (.NET), dragonmantank/cron-expression (PHP), and croner-rust. It prevents unexpected behavior and maintains the principle that `W` operates only on valid calendar days within the current month. From e486b0f85dafb477fd23000e3759f11a2b4bf005 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 15 Nov 2025 19:48:52 +0000 Subject: [PATCH 3/7] Make W modifier non-existing days section more concise Co-authored-by: Hexagon <419737+Hexagon@users.noreply.github.com> --- increments/OCPS-increment-1.3.md | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/increments/OCPS-increment-1.3.md b/increments/OCPS-increment-1.3.md index cb3f5da..69d5d99 100644 --- a/increments/OCPS-increment-1.3.md +++ b/increments/OCPS-increment-1.3.md @@ -65,16 +65,8 @@ The `W` character can be used in the `Day of Month` field to find the closest we #### 4.3.1. Behavior with Non-Existing Days -When the `W` modifier is used with a day number that does not exist in a particular month (e.g., `31W` in February, or `30W` in February), the pattern **will not match any date in that month**. The job will not be scheduled to run during months where the specified day does not exist. +When the `W` modifier is used with a day number that does not exist in a particular month (e.g., `31W` in February), the pattern **will not match any date in that month**. -This behavior ensures predictable and consistent scheduling across implementations, avoiding ambiguity about whether to fallback to the last day of the month, skip the month entirely, or use other heuristics. +* **Example:** `0 12 31W * *` triggers only in months with 31 days (Jan, Mar, May, Jul, Aug, Oct, Dec). It does not run in months with fewer days (Feb, Apr, Jun, Sep, Nov). -* **Example (`31W`):** The pattern `0 12 31W * *` will trigger at noon on the weekday closest to the 31st. - * In months with 31 days (January, March, May, July, August, October, December), it will trigger on the 31st if it's a weekday, or the nearest weekday within that month. - * In months with fewer than 31 days (February, April, June, September, November), **the pattern will not match** and the job will not run in those months. - -* **Example (`30W`):** The pattern `0 0 30W * *` will trigger at midnight on the weekday closest to the 30th. - * In months with 30 or 31 days, it will trigger on the 30th if it's a weekday, or the nearest weekday within that month. - * In February (with 28 or 29 days), **the pattern will not match** and the job will not run. - -**Rationale:** This approach is consistent with the behavior observed in widely-used cron implementations including Quartz Scheduler, Spring Framework, Cronos (.NET), dragonmantank/cron-expression (PHP), and croner-rust. It prevents unexpected behavior and maintains the principle that `W` operates only on valid calendar days within the current month. +This behavior is consistent with Quartz, Spring, Cronos, and other major implementations. From b3c2669c3424af6753fec92ad846a271c376eeb5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 15 Nov 2025 19:52:40 +0000 Subject: [PATCH 4/7] Make section more expressive and remove implementation references Co-authored-by: Hexagon <419737+Hexagon@users.noreply.github.com> --- increments/OCPS-increment-1.3.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/increments/OCPS-increment-1.3.md b/increments/OCPS-increment-1.3.md index 69d5d99..b587081 100644 --- a/increments/OCPS-increment-1.3.md +++ b/increments/OCPS-increment-1.3.md @@ -65,8 +65,8 @@ The `W` character can be used in the `Day of Month` field to find the closest we #### 4.3.1. Behavior with Non-Existing Days -When the `W` modifier is used with a day number that does not exist in a particular month (e.g., `31W` in February), the pattern **will not match any date in that month**. +When the `W` modifier is used with a day number that does not exist in a particular month (e.g., `31W` in February), the pattern **will not match any date in that month**. The job will simply not be scheduled to run during those months. -* **Example:** `0 12 31W * *` triggers only in months with 31 days (Jan, Mar, May, Jul, Aug, Oct, Dec). It does not run in months with fewer days (Feb, Apr, Jun, Sep, Nov). - -This behavior is consistent with Quartz, Spring, Cronos, and other major implementations. +* **Example:** `0 12 31W * *` triggers at noon on the nearest weekday to the 31st. + * In months with 31 days (Jan, Mar, May, Jul, Aug, Oct, Dec), it triggers as expected. + * In months with fewer days (Feb, Apr, Jun, Sep, Nov), the pattern does not match and the job does not run. From 6acbcb06053aa56f82aae5d74f45615233e2d37e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 17 Nov 2025 21:21:45 +0000 Subject: [PATCH 5/7] Add LW combination for last weekday of month Co-authored-by: Hexagon <419737+Hexagon@users.noreply.github.com> --- increments/OCPS-increment-1.3.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/increments/OCPS-increment-1.3.md b/increments/OCPS-increment-1.3.md index b587081..8f99934 100644 --- a/increments/OCPS-increment-1.3.md +++ b/increments/OCPS-increment-1.3.md @@ -70,3 +70,9 @@ When the `W` modifier is used with a day number that does not exist in a particu * **Example:** `0 12 31W * *` triggers at noon on the nearest weekday to the 31st. * In months with 31 days (Jan, Mar, May, Jul, Aug, Oct, Dec), it triggers as expected. * In months with fewer days (Feb, Apr, Jun, Sep, Nov), the pattern does not match and the job does not run. + +To schedule on the last weekday of every month regardless of month length, combine `L` and `W` as `LW`: + +* **Example:** `0 12 LW * *` triggers at noon on the last weekday of the month. + * If the last day is a weekday, it triggers on that day. + * If the last day is a weekend, it triggers on the preceding Friday. From 66b121792e360b8d795248ee9f7d53a0ca6e5ffe Mon Sep 17 00:00:00 2001 From: Hexagon Date: Mon, 2 Mar 2026 00:14:05 +0100 Subject: [PATCH 6/7] Update increments/OCPS-increment-1.3.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- increments/OCPS-increment-1.3.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/increments/OCPS-increment-1.3.md b/increments/OCPS-increment-1.3.md index 3f6acf3..382b775 100644 --- a/increments/OCPS-increment-1.3.md +++ b/increments/OCPS-increment-1.3.md @@ -68,7 +68,10 @@ The `W` character can be used in the `Day of Month` field to find the closest we When the `W` modifier is used with a day number that does not exist in a particular month (e.g., `31W` in February), the pattern **will not match any date in that month**. The job will simply not be scheduled to run during those months. * **Example:** `0 12 31W * *` triggers at noon on the nearest weekday to the 31st. - * In months with 31 days (Jan, Mar, May, Jul, Aug, Oct, Dec), it triggers as expected. + * In months with 31 days (Jan, Mar, May, Jul, Aug, Oct, Dec), it triggers on the closest weekday **within that month**: + * If the 31st is a weekday (Mon–Fri), it triggers on the 31st. + * If the 31st is a Saturday, it triggers on Friday the 30th. + * If the 31st is a Sunday, it **cannot** move to Monday the 1st (next month), so it triggers on Friday the 29th. * In months with fewer days (Feb, Apr, Jun, Sep, Nov), the pattern does not match and the job does not run. To schedule on the last weekday of every month regardless of month length, combine `L` and `W` as `LW`: From f01929c1950781c58ff0c3889a80c3d8e58cc0f5 Mon Sep 17 00:00:00 2001 From: Hexagon Date: Mon, 2 Mar 2026 00:15:41 +0100 Subject: [PATCH 7/7] Update increments/OCPS-increment-1.3.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- increments/OCPS-increment-1.3.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/increments/OCPS-increment-1.3.md b/increments/OCPS-increment-1.3.md index 382b775..2265bd3 100644 --- a/increments/OCPS-increment-1.3.md +++ b/increments/OCPS-increment-1.3.md @@ -76,6 +76,8 @@ When the `W` modifier is used with a day number that does not exist in a particu To schedule on the last weekday of every month regardless of month length, combine `L` and `W` as `LW`: +* **Token form (`LW`):** In the `Day of Month` field, `LW` is a single, reserved token that means "the last weekday of the month." It is not interpreted as `L` applied to a `W`-modified day number. * **Example:** `0 12 LW * *` triggers at noon on the last weekday of the month. * If the last day is a weekday, it triggers on that day. * If the last day is a weekend, it triggers on the preceding Friday. +* **Invalid combinations:** Other `L`/`W` combinations in the `Day of Month` field (such as `1LW`, `L1W`, `LLW`, ranges involving `LW` like `L-LW`, or lists such as `LW,15W`) are INVALID and **MUST NOT** be accepted by compliant parsers. Only the bare `LW` token and numeric-`W` forms (e.g., `15W`) are valid.