Possible to add a way to schedule maintenance every first Monday, Tuesday, etc...? #2204

Open
opened 2026-02-28 02:46:29 -05:00 by deekerman · 11 comments
Owner

Originally created by @b-a0 on GitHub (May 22, 2023).

⚠️ Please verify that this feature request has NOT been suggested before.

  • I checked and didn't find similar feature request

🏷️ Feature Request Type

Other

🔖 Feature description

The maintenance scheduler allows scheduling with cron. While cron on Debian allows one to schedule something on the first Monday (or Tuesday) of a month, the used cron library croner does not.

However, croner does offer a legacy mode that would check the date of month and day of week conditions with an AND operator instead of the default OR operator.

✔️ Solution

By adding a checkmark next to the cron expression that would toggle croner legacy mode, you could create a cron expression:

0 18 1-7 * MON

Without the legacy box unchecked (as it is now) this would be:

Schedule: At 06:00 PM, between day 1 and 7 of the month, and on Monday

With the legacy box checked:

Schedule: At 06:00 PM, between day 1 and 7 of the month only if a Monday

Alternatives

I have tried different cron expressions listed in this Superuser post. Unfortunately none of them work with the croner library.

📝 Additional Context

I only have a very rough understanding of JS, but to me it seems that a change would be needed in /server/model/maintenance.js#L264. Something like this fake code:

// Create Cron
this.beanMeta.job = new Cron(this.cron, {
    timezone: await this.getTimezone(),
}, { legacyMode: this.cronLegacy }, startEvent);

and in the UI around /src/pages/EditMaintenance.vue#L94.

Originally created by @b-a0 on GitHub (May 22, 2023). ### ⚠️ Please verify that this feature request has NOT been suggested before. - [X] I checked and didn't find similar feature request ### 🏷️ Feature Request Type Other ### 🔖 Feature description The maintenance scheduler allows scheduling with cron. While cron on Debian [allows](https://superuser.com/a/1347480) one to schedule something on the first Monday (or Tuesday) of a month, the used cron library [`croner`](https://www.npmjs.com/package/croner) does not. However, `croner` [does offer a legacy mode](https://github.com/Hexagon/croner/issues/53) that would check the date of month and day of week conditions with an `AND` operator instead of the default `OR` operator. ### ✔️ Solution By adding a checkmark next to the cron expression that would toggle `croner` legacy mode, you could create a cron expression: ``` 0 18 1-7 * MON ``` Without the legacy box unchecked (as it is now) this would be: > Schedule: At 06:00 PM, between day 1 and 7 of the month, and on Monday With the legacy box checked: > Schedule: At 06:00 PM, between day 1 and 7 of the month only if a Monday ### ❓ Alternatives I have tried different cron expressions listed in [this Superuser post](https://superuser.com/q/428807). Unfortunately none of them work with the `croner` library. ### 📝 Additional Context I only have a very rough understanding of JS, but to me it seems that a change would be needed in [`/server/model/maintenance.js#L264`](https://github.com/louislam/uptime-kuma/blob/0d1b5321ad96687dfaa337e995b2b7ffcc98924e/server/model/maintenance.js#L264). Something like this fake code: ```js // Create Cron this.beanMeta.job = new Cron(this.cron, { timezone: await this.getTimezone(), }, { legacyMode: this.cronLegacy }, startEvent); ``` and in the UI around [`/src/pages/EditMaintenance.vue#L94`](https://github.com/louislam/uptime-kuma/blob/0d1b5321ad96687dfaa337e995b2b7ffcc98924e/src/pages/EditMaintenance.vue#L94).
Author
Owner

@CommanderStorm commented on GitHub (May 23, 2023):

I would not like to add this additional feature.
Any variable prefixed with legacy is something, that I would expect will not be there forever. => this would likely unexpectedly break in the future.

Would 0 0 0 * * L1 work for you?

@CommanderStorm commented on GitHub (May 23, 2023): I would not like to add this additional feature. Any variable prefixed with `legacy` is something, that I would expect will not be there forever. => this would likely unexpectedly break in the future. Would [`0 0 0 * * L1`](https://victornpb.github.io/cron/#0_0_0_*_*_L1&legacyMode:false) work for you?
Author
Owner

@b-a0 commented on GitHub (May 23, 2023):

Thanks for the suggestion. My understanding is that the L parameter schedules something on the last specified weekday of the month. I am looking to schedule something on the first Wednesday of the month, not the last, i.e. 0 18 1-7 * 3 { legacyMode: false }.

Is it possible to do that as well in the current version of Uptime Kuma?

I am not sure "legacy" refers to this being ready to deprecate in this case. Note also that it is set to true by default. I will check in the linked croner issue what their intentions are with this parameter.

@b-a0 commented on GitHub (May 23, 2023): Thanks for the suggestion. My understanding is that the `L` parameter schedules something on the last specified weekday of the month. I am looking to schedule something on the *first* Wednesday of the month, not the last, i.e. [`0 18 1-7 * 3 { legacyMode: false }`](https://victornpb.github.io/cron/#0_18_1-7_*_3&legacyMode:false). Is it possible to do that as well in the current version of Uptime Kuma? I am not sure "legacy" refers to this being ready to deprecate in this case. Note also that it is set to `true` [by default](https://github.com/Hexagon/croner#options). I will check in the linked croner issue what their intentions are with this parameter.
Author
Owner

@Hexagon commented on GitHub (May 23, 2023):

Setting legacyMode to false is perfectly safe and a permanent feature of croner.

The default will always be legacyMode: true, which makes croner work like legacy cron parsers, which is expected behaviour, even though it's not optimal.

Confusing - yes! Need to worry - no 😄

@Hexagon commented on GitHub (May 23, 2023): Setting legacyMode to false is perfectly safe and a permanent feature of croner. The default will always be legacyMode: true, which makes croner work like legacy cron parsers, which is expected behaviour, even though it's not optimal. Confusing - yes! Need to worry - no 😄
Author
Owner

@CommanderStorm commented on GitHub (May 25, 2023):

@b-a0

Would adding such a toggle in the settings also solve #2621?

What do you think would be a good UI for this? (what kind of help text + what input element)

@CommanderStorm commented on GitHub (May 25, 2023): @b-a0 Would adding such a toggle in the settings also solve #2621? What do you think would be a good UI for this? (what kind of help text + what input element)
Author
Owner

@b-a0 commented on GitHub (May 25, 2023):

Would adding such a toggle in the settings also solve https://github.com/louislam/uptime-kuma/issues/2621?

I think so, it seems to work for second and third $dayOfWeek.
Here are a few croner examples (all with legacyMode: false) which I've double checked with Excel for 2023 (marked with a ✔️ if it was the same):

First Monday: 0 18 1-7 * 1 ✔️
First Wednesday: 0 18 1-7 * 3 ✔️
Second Tuesday: 0 18 8-14 * 2 ✔️
Second Friday: 0 18 8-14 * 5 ✔️
Third Monday: 0 18 15-21 * 1 ✔️
Third Sunday: 0 18 15-21 * 7 ✔️

What do you think would be a good UI for this? (what kind of help text + what input element)

I'm not well versed in web-design, but as a user I think a checkbox (that is unchecked by default) next to the cron textbox would make sense:

image

Checking the checkbox would set legacyMode: false.

Regarding the helptext, something similar to the Cloudflare settings page would probably be clear in terms of formatting:

image

The text (in light gray) could say something like:

There are different modes of restricting the day on which the maintenance is scheduled. When the checkbox is unchecked, the default cron behaviour is used. The checkbox enables non-standard behaviour that enables you to restrict to the Nth weekday within a month. For more info see this link: https://github.com/Hexagon/croner/issues/53

Instead of the croner issue, it could also link to the current issue.

Hope this helps? Let me know if I can provide anything else.

@b-a0 commented on GitHub (May 25, 2023): > Would adding such a toggle in the settings also solve https://github.com/louislam/uptime-kuma/issues/2621? I think so, it seems to work for second and third $dayOfWeek. Here are a few `croner` examples (all with `legacyMode: false`) which I've double checked with [Excel](https://stackoverflow.com/a/25170627) for 2023 (marked with a ✔️ if it was the same): First Monday: [`0 18 1-7 * 1`](https://victornpb.github.io/cron/#0_18_1-7_*_1&legacyMode:false) ✔️ First Wednesday: [`0 18 1-7 * 3`](https://victornpb.github.io/cron/#0_18_1-7_*_3&legacyMode:false) ✔️ Second Tuesday: [`0 18 8-14 * 2`](https://victornpb.github.io/cron/#0_18_8-14_*_2&legacyMode:false) ✔️ Second Friday: [`0 18 8-14 * 5`](https://victornpb.github.io/cron/#0_18_8-14_*_5&legacyMode:false) ✔️ Third Monday: [`0 18 15-21 * 1`](https://victornpb.github.io/cron/#0_18_15-21_*_1&legacyMode:false) ✔️ Third Sunday: [`0 18 15-21 * 7`](https://victornpb.github.io/cron/#0_18_15-21_*_7&legacyMode:false) ✔️ > What do you think would be a good UI for this? (what kind of help text + what input element) I'm not well versed in web-design, but as a user I think a checkbox (that is unchecked by default) next to the cron textbox would make sense: ![image](https://github.com/louislam/uptime-kuma/assets/25707742/d45af100-e7cd-4165-b95b-a1151cbf39a6) Checking the checkbox would set `legacyMode: false`. Regarding the helptext, something similar to the Cloudflare settings page would probably be clear in terms of formatting: ![image](https://github.com/louislam/uptime-kuma/assets/25707742/d790a1fa-adcb-49a1-b3ce-66df38c243ca) The text (in light gray) could say something like: > There are different modes of restricting the day on which the maintenance is scheduled. When the checkbox is unchecked, the [default cron behaviour](https://man.openbsd.org/crontab.5#either) is used. The checkbox enables non-standard behaviour that enables you to restrict to the N<sup>th</sup> weekday within a month. For more info see this link: https://github.com/Hexagon/croner/issues/53 Instead of the croner issue, it could also link to the current issue. Hope this helps? Let me know if I can provide anything else.
Author
Owner

@louislam commented on GitHub (May 26, 2023):

The checkbox should be easy to be implemented.

But the cron description (This message: Schedule: At 06:00 PM, between day 1 and 7 of the month only if a Monday) maybe a bit hard to implement, because it is actually generated by another library called crontrue.

@louislam commented on GitHub (May 26, 2023): The checkbox should be easy to be implemented. But the cron description (This message: `Schedule: At 06:00 PM, between day 1 and 7 of the month only if a Monday`) maybe a bit hard to implement, because it is actually generated by another library called [crontrue](https://www.npmjs.com/package/cronstrue).
Author
Owner

@b-a0 commented on GitHub (May 29, 2023):

bit hard to implement, because it is actually generated by another library called crontrue.

That is tricky indeed. I see two options, both are less than elegent unfortunately:

  1. When the checkbox is checked (i.e. legacyMode: false) the text returned by crontrue is slightly alterend. A few examples:
    • First Monday: 0 18 1-7 * 1, instead of: "At 06:00 PM, between day 1 and 7 of the month, and on Monday", replace the last "and" with "only": "At 06:00 PM, between day 1 and 7 of the month, only on Monday".
    • Similarly works for other days: 0 18 15-21 * 7 would result in "At 06:00 PM, between day 15 and 21 of the month, only on Sunday"
    • Multiple days should work fine as well: 0 18 15-21 * 1,2,3,4 would result in "At 06:00 PM, between day 15 and 21 of the month, only on Monday, Tuesday, Wednesday, and Thursday"
    • Day ranges are a bit harder though: 0 18 15-21 * 1-5 currenly returns "At 06:00 PM, between day 15 and 21 of the month, Monday through Friday". You would need to somehow add "only" between the comma and "Monday".
      This does not take into account internationalisation with i18n...
  2. When the checkbox is checked (i.e. legacyMode: false) reparse the provided cron expression and use the # symbol in the day-of-week field to indicate the Nth day (which is supported by cronstrue, but not by croner). Some examples:
    • 0 18 1-7 * 1 -> 0 18 1-7 * 1#1: "At 06:00 PM, between day 1 and 7 of the month, on the first Monday of the month"
    • 0 18 1-7 * 1,2 -> 0 18 1-7 * 1#1,2#1: "At 06:00 PM, between day 1 and 7 of the month, on the first Monday and first Tuesday of the month"
    • 0 18 8-14 * 1-4 -> 0 18 8-14 * 1#2-4#2: "At 06:00 PM, between day 8 and 14 of the month, second Monday through second Thursday"

In the second option there is a bit of redundancy there as it specifies both "between day X and Y of the month" and "Nth day of the week".

@b-a0 commented on GitHub (May 29, 2023): > bit hard to implement, because it is actually generated by another library called [crontrue](https://www.npmjs.com/package/cronstrue). That is tricky indeed. I see two options, both are less than elegent unfortunately: 1. When the checkbox is checked (i.e. `legacyMode: false`) the text returned by `crontrue` is slightly alterend. A few examples: - First Monday: `0 18 1-7 * 1`, instead of: "At 06:00 PM, between day 1 and 7 of the month, and on Monday", replace the last "and" with "only": "At 06:00 PM, between day 1 and 7 of the month, **only** on Monday". - Similarly works for other days: `0 18 15-21 * 7` would result in "At 06:00 PM, between day 15 and 21 of the month, **only** on Sunday" - Multiple days should work fine as well: `0 18 15-21 * 1,2,3,4` would result in "At 06:00 PM, between day 15 and 21 of the month, **only** on Monday, Tuesday, Wednesday, and Thursday" - Day ranges are a bit harder though: `0 18 15-21 * 1-5` currenly returns "At 06:00 PM, between day 15 and 21 of the month, Monday through Friday". You would need to somehow add "only" between the comma and "Monday". This does not take into account internationalisation with i18n... 2. When the checkbox is checked (i.e. `legacyMode: false`) reparse the provided cron expression and use the `#` symbol in the day-of-week field [to indicate the N<sup>th</sup> day](https://www.netiq.com/documentation/cloud-manager-2-5/ncm-reference/data/bexyssf.html#beykonj) (which is supported by `cronstrue`, but not by `croner`). Some examples: - `0 18 1-7 * 1` -> `0 18 1-7 * 1#1`: "At 06:00 PM, between day 1 and 7 of the month, on the first Monday of the month" - `0 18 1-7 * 1,2` -> `0 18 1-7 * 1#1,2#1`: "At 06:00 PM, between day 1 and 7 of the month, on the first Monday and first Tuesday of the month" - `0 18 8-14 * 1-4` -> `0 18 8-14 * 1#2-4#2`: "At 06:00 PM, between day 8 and 14 of the month, second Monday through second Thursday" In the second option there is a bit of redundancy there as it specifies both "between day X and Y of the month" and "Nth day of the week".
Author
Owner

@CommanderStorm commented on GitHub (May 29, 2023):

I thought about this a bit more:
Maybe a global toggle for this would not be super intuitive. I think adding nth-week of the month here would be more elegant (and most importantly, less confusing):
image

I don't fully know how specifically, though.

  • adding a new strategy
  • adding this to the form I opened (maybe Restrict to-selector with ["1st Week of the month","2nd Week of the month","3rd Week of the month", "last occurrance in month"])

Both sound like a messy idea, though.

On the other hand, adding a toggle box (with an appropriate tooltip, explaining how n-th day of the week could work) here could also make sense Connect Days of the week and Dates using -> AND/OR, OR being the default:
image

@CommanderStorm commented on GitHub (May 29, 2023): I thought about this a bit more: Maybe a global toggle for this would not be super intuitive. I think adding `nth-week of the month` here would be more elegant (and most importantly, less confusing): ![image](https://github.com/louislam/uptime-kuma/assets/26258709/f0307af6-e0a5-4a09-b88a-22ff28ad3937) I don't fully know how specifically, though. - adding a new `strategy` - adding this to the form I opened (maybe `Restrict to`-selector with `["1st Week of the month","2nd Week of the month","3rd Week of the month", "last occurrance in month"]`) Both sound like a messy idea, though. On the other hand, adding a toggle box (with an appropriate tooltip, explaining how n-th day of the week could work) here could also make sense `Connect Days of the week and Dates using` -> `AND`/`OR`, `OR` being the default: ![image](https://github.com/louislam/uptime-kuma/assets/26258709/724f40fe-fefe-41e2-8901-1dfe0886af60)
Author
Owner

@Hexagon commented on GitHub (Aug 8, 2023):

Proper support for nth weekday of month through # specifier is now released in the dev-channel of croner. Progress tracked at https://github.com/Hexagon/croner/issues/198 and will be released in 7.0.0 within a week.

This will enable patterns such as 0 0 0 * * FRI#2 or 0 0 0 * * 5#2 for second friday of month, and it will be possible to combine with other features, such as names, ranges and L to make more complex constructs - such as 0 0 0 * * MON-FRI#L for every last weekday of the month.

@Hexagon commented on GitHub (Aug 8, 2023): Proper support for nth weekday of month through `#` specifier is now released in the dev-channel of croner. Progress tracked at <https://github.com/Hexagon/croner/issues/198> and will be released in `7.0.0` within a week. This will enable patterns such as `0 0 0 * * FRI#2` or `0 0 0 * * 5#2` for second friday of month, and it will be possible to combine with other features, such as names, ranges and `L` to make more complex constructs - such as `0 0 0 * * MON-FRI#L` for every last weekday of the month.
Author
Owner

@NoeMeinhardt commented on GitHub (Feb 14, 2024):

Any progress on this? The data center we use performs scheduled maintenance every third Saturday and Sunday of the month. I would love to use 0 0 0 * * 6#2 with a duration of 2879 minutes, but it says it "contains illegal characters".

@NoeMeinhardt commented on GitHub (Feb 14, 2024): Any progress on this? The data center we use performs scheduled maintenance every third Saturday and Sunday of the month. I would love to use `0 0 0 * * 6#2` with a duration of 2879 minutes, but it says it "contains illegal characters".
Author
Owner

@CommanderStorm commented on GitHub (Feb 14, 2024):

The reason why this is not avaliable is that we have not found the time to migrate croner to v7. See
github.com/louislam/uptime-kuma@cf2d603e27/package.json (L92)

This change either needs calling out or a migration:

Note

Compared to previous versions, there's a change in the way L functions in the day-of-week field. In version 6.x, L had flexibility in its positioning: both LSUN and SUNL were valid expressions to denote the last Sunday of the month. However, starting from version 7.x, L must be used in a more standardized way, in conjunction with the nth weekday specifier #, like so: SUN#L.

Here is our contribution guide: https://github.com/louislam/uptime-kuma/blob/master/CONTRIBUTING.md

@CommanderStorm commented on GitHub (Feb 14, 2024): The reason why this is not avaliable is that we have not found the time to migrate croner to v7. See https://github.com/louislam/uptime-kuma/blob/cf2d603e277d18e96906ac36743ec4e7d58b8aad/package.json#L92 This change either needs calling out or a migration: > [!NOTE] > Compared to previous versions, there's a change in the way `L` functions in the day-of-week field. In version `6.x`, `L` had flexibility in its positioning: both `LSUN` and `SUNL` were valid expressions to denote the last Sunday of the month. However, starting from version `7.x`, `L` must be used in a more standardized way, in conjunction with the nth weekday specifier `#`, like so: `SUN#L`. Here is our contribution guide: https://github.com/louislam/uptime-kuma/blob/master/CONTRIBUTING.md
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/uptime-kuma#2204
No description provided.