Description
When a cronjob uses numeric day-of-week values (e.g. 0 7 * * 1-5), openab
fires on the wrong day. The docs promise POSIX semantics (Sun=0/7, Mon=1, ..., Sat=6),
so 1-5 should mean Mon–Fri. In practice it fires Sun–Thu — every numeric
day-of-week value is shifted by one day.
The timezone handling itself is correct. The bug is purely in how numeric
day-of-week values are interpreted.
Steps to Reproduce
- Configure a cronjob:
[[jobs]]
schedule = "0 7 * * 1-5"
timezone = "Asia/Taipei"
channel = "<redacted>"
message = "weekday job"
enabled = true
- Wait for the next Sunday 07:00 in
Asia/Taipei (= Saturday 23:00 UTC).
- Observe: the job fires, even though Sunday is not in
1-5.
Real trigger observed on 2026-05-10 (Sunday):
2026-05-09T23:00:01Z INFO openab::cron: 🔔 cronjob fired
schedule=0 7 * * 1-5 channel=<redacted> platform=discord
message=<redacted> sender=openab-cron
UTC 23:00 on 2026-05-09 = Taipei 07:00 on 2026-05-10 (Sunday). Should not have fired.
Expected Behavior
Per docs/cronjob.md, which says:
Standard 5-field POSIX cron, same as Linux crontab, K8s CronJob, and GitHub Actions
day of week (0-7, 0 and 7 = Sunday)
| 0 9 * * 1-5 | Weekdays at 09:00 |
1-5 should fire Mon–Fri only.
Actual Behavior
1-5 fires Sun–Thu (entire weekday range shifted by one). Every numeric
day-of-week value is off by one:
| User writes (POSIX intent) |
Actually fires on |
0 (Sun) |
out-of-range — invalid |
1 (Mon) |
Sun |
5 (Fri) |
Thu |
6 (Sat) |
Fri |
7 (Sun) |
Sat |
1-5 (Mon–Fri) |
Sun–Thu |
Root Cause
openab uses the cron crate (v0.16.0), which
does not follow POSIX day-of-week numbering. From
cron-0.16.0/src/time_unit/days_of_week.rs:
static DAY_OF_WEEK_MAP: phf::Map<&'static str, Ordinal> = phf_map! {
"sun" => 1,
"mon" => 2,
"tue" => 3,
"wed" => 4,
"thu" => 5,
"fri" => 6,
"sat" => 7,
};
// inclusive_min = 1, inclusive_max = 7
And in schedule.rs,
the weekday match uses chrono's number_from_sunday() (Sun=1, Mon=2, ..., Sat=7),
which matches the map above but not POSIX.
So 1-5 passed to the cron crate means Sun–Thu, not Mon–Fri.
Note: the timezone handling in should_fire is correct. Utc::now().with_timezone(&tz)
and the weekday check both use the same local DateTime<Tz>. This is not a timezone bug.
Proposed Fix
Translate numeric day-of-week tokens in the 5th field before handing the
expression to cron::Schedule. This keeps docs/cronjob.md's POSIX promise
intact and is a localized change to parse_cron_expr:
0 or 7 → 1 (Sunday in cron crate)
n (1..=6) → n + 1
- Applies to each numeric token inside ranges (
1-5 → 2-6), lists (1,3,5 → 2,4,6),
and step bases (*/2 unchanged; 1-5/2 → 2-6/2).
- Name tokens (
Mon, Sun, Mon-Fri, ...) pass through unchanged — the cron crate's
name → ordinal map is already internally consistent.
Alternative considered: switching to a POSIX-compliant crate (e.g. saffron,
croner-rust). Larger surface area; can be re-evaluated if the translation
approach proves insufficient.
Workaround (for existing users)
Use name-based day-of-week:
schedule = "0 7 * * Mon-Fri"
This works correctly because the cron crate's name→ordinal map is internally
consistent; only the numeric interface diverges from POSIX.
Environment
- openab: 0.8.2
- cron crate: 0.16.0
- Platform: Discord adapter, via usercron (
~/.openab/usercron.toml)
Issue filed by my agent (OpenAB w/ Kiro CLI) under my account; content reviewed by me.
Description
When a cronjob uses numeric day-of-week values (e.g.
0 7 * * 1-5), openabfires on the wrong day. The docs promise POSIX semantics (Sun=0/7, Mon=1, ..., Sat=6),
so
1-5should mean Mon–Fri. In practice it fires Sun–Thu — every numericday-of-week value is shifted by one day.
The timezone handling itself is correct. The bug is purely in how numeric
day-of-week values are interpreted.
Steps to Reproduce
Asia/Taipei(= Saturday 23:00 UTC).1-5.Real trigger observed on 2026-05-10 (Sunday):
UTC 23:00 on 2026-05-09 = Taipei 07:00 on 2026-05-10 (Sunday). Should not have fired.
Expected Behavior
Per
docs/cronjob.md, which says:1-5should fire Mon–Fri only.Actual Behavior
1-5fires Sun–Thu (entire weekday range shifted by one). Every numericday-of-week value is off by one:
0(Sun)1(Mon)5(Fri)6(Sat)7(Sun)1-5(Mon–Fri)Root Cause
openab uses the
croncrate (v0.16.0), whichdoes not follow POSIX day-of-week numbering. From
cron-0.16.0/src/time_unit/days_of_week.rs:And in
schedule.rs,the weekday match uses chrono's
number_from_sunday()(Sun=1, Mon=2, ..., Sat=7),which matches the map above but not POSIX.
So
1-5passed to thecroncrate means Sun–Thu, not Mon–Fri.Note: the timezone handling in
should_fireis correct.Utc::now().with_timezone(&tz)and the weekday check both use the same local
DateTime<Tz>. This is not a timezone bug.Proposed Fix
Translate numeric day-of-week tokens in the 5th field before handing the
expression to
cron::Schedule. This keepsdocs/cronjob.md's POSIX promiseintact and is a localized change to
parse_cron_expr:0or7→1(Sunday in cron crate)n(1..=6) →n + 11-5→2-6), lists (1,3,5→2,4,6),and step bases (
*/2unchanged;1-5/2→2-6/2).Mon,Sun,Mon-Fri, ...) pass through unchanged — thecroncrate'sname → ordinal map is already internally consistent.
Alternative considered: switching to a POSIX-compliant crate (e.g.
saffron,croner-rust). Larger surface area; can be re-evaluated if the translationapproach proves insufficient.
Workaround (for existing users)
Use name-based day-of-week:
This works correctly because the
croncrate's name→ordinal map is internallyconsistent; only the numeric interface diverges from POSIX.
Environment
~/.openab/usercron.toml)Issue filed by my agent (OpenAB w/ Kiro CLI) under my account; content reviewed by me.