diff --git a/README.md b/README.md index a1167f4..935ad85 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,10 @@ This project is released under the [Apache License 2.0](http://www.apache.org/li Changelog --------- +**2024-11-18** + +* `W` allowed with ranges or iterators in OTHER list fields + **2024-10-25** * `L` allowed multiple times in day-of-month (DOM) and day-of-week (DOW): Can be used in lists, additionally in DOM alongside W values such as `LW` or `10W`, but not `L-3W` diff --git a/ccronexpr.c b/ccronexpr.c index b0e4e34..da6084a 100644 --- a/ccronexpr.c +++ b/ccronexpr.c @@ -1586,16 +1586,8 @@ static char *w_check(char *field, cron_expr *target, const char **error) { } memset(newField, 0, sizeof(char) * strlen(field)); char *tracking = newField; - // Ensure only 1 day is specified, and W day is not the last in a range or list or iterator of days - if (has_char(field, '/') || has_char(field, '-')) { - *error = "W not allowed in iterators or ranges in 'day of month' field"; - goto return_error; - } // Ensure no specific days are set in day of week - if ((target->days_of_week[0] ^ 0x7f) != 0) { - *error = "Cannot set specific days of week when using 'W' in days of month."; - goto return_error; - } + // Already checked in cron_parse_expr splitField = split_str(field, ',', &len_out); if (!splitField) { *error = "Error splitting 'day of month' field for W detection"; @@ -1603,6 +1595,11 @@ static char *w_check(char *field, cron_expr *target, const char **error) { } for (size_t i = 0; i < len_out; i++) { if ((has_w = strchr(splitField[i], 'W'))) { + // Ensure W day is not the end or beginning of a range or iterator + if (has_char(splitField[i], '/') || has_char(splitField[i], '-')) { + *error = "W not allowed in iterators or ranges in 'day of month' field"; + goto return_error; + } // Ensure nothing follows 'W' if (*(has_w + 1) != '\0') { *error = "If W is used, 'day of month' element needs to end with it"; diff --git a/ccronexpr_test.c b/ccronexpr_test.c index e87dc7d..54e8c56 100644 --- a/ccronexpr_test.c +++ b/ccronexpr_test.c @@ -409,7 +409,10 @@ void test_expr() { assert(check_next("0 0 1 8W,26W * ?", "2022-02-26_00:00:00", "2022-03-08_01:00:00")); assert(check_next("0 0 1 8W,26W * ?", "2022-03-09_00:00:00", "2022-03-25_01:00:00")); assert(check_next("0 0 1 29W * ?", "2022-02-28_00:00:00", "2022-03-29_01:00:00")); - assert(check_next("0 0 1 29W * ?", "2024-02-28_00:00:00", "2024-02-29_01:00:00")); + assert(check_next("0 0 1 29W * ?", "2022-02-28_00:00:00", "2022-03-29_01:00:00")); + assert(check_next("0 0 1 1-3,29W * ?", "2024-02-28_00:00:00", "2024-02-29_01:00:00")); + assert(check_next("0 0 1 1-3,29W * ?", "2024-03-01_00:00:00", "2024-03-01_01:00:00")); + assert(check_next("0 0 1 1-3,29W * ?", "2024-03-03_00:00:00", "2024-03-03_01:00:00")); assert(check_next("0 0 1 31W * ?", "2022-02-28_00:00:00", "2022-03-31_01:00:00")); assert(check_next("0 0 1 31W * ?", "2022-06-17_00:00:00", "2022-07-29_01:00:00")); assert(check_next("0 0 1 31W * ?", "2022-07-30_00:00:00", "2022-08-31_01:00:00")); @@ -425,6 +428,8 @@ void test_expr() { assert(check_next("0 0 1 LW * ?", "2022-10-01_00:00:00", "2022-10-31_01:00:00")); assert(check_next("0 0 1 LW * ?", "2022-07-31_00:00:00", "2022-08-31_01:00:00")); assert(check_next("0 0 1 LW * ?", "2022-07-30_00:00:00", "2022-08-31_01:00:00")); + assert(check_next("0 0 1 LW,L-3 * ?", "2022-07-30_00:00:00", "2022-08-28_01:00:00")); + assert(check_next("0 0 1 LW,L-3 * ?", "2022-08-29_00:00:00", "2022-08-31_01:00:00")); cron_init_hash(7); assert(check_next("H 0 H LW * ?", "2022-10-01_00:00:00", "2022-10-31_14:00:00")); assert(check_next("0 0 1 L * ?", "2022-05-12_00:00:00", "2022-05-31_01:00:00")); @@ -526,6 +531,9 @@ void test_parse() { assert(check_same("0 0 15 1,16,L * *", "0 0 15 1,L,16 * *")); assert(check_expr_valid("0 0 15 1,16,L * *")); assert(check_expr_valid("0 0 15 1,L,16 * *")); + assert(check_expr_valid("0 0 12 LW,L * *")); + assert(check_expr_valid("0 0 12 LW,L-3,L * *")); + assert(check_expr_valid("0 0 12 L-3,LW,L * *")); // check default hash func has valid output cron_init_custom_hash_fn(NULL); assert(check_expr_valid("0 0 1 * * ?"));