Natural language schedules
cronpad understands schedules written in plain English, like every 15 minutes, every weekday at 6:30pm or second tuesday of every month at 9am. The parser is deterministic (no AI involved): the same text always means the same thing. It is converted to an RRULE, which is stored as the job’s canonical schedule and shown back to you in plain English.
Examples
Intervals
Days and times
Days of the month
Limits
One-off
Grammar
Words are case-insensitive. Clauses after the frequency may appear in any order. Filler words (the, of, on, at, each, and, commas) are accepted wherever they read naturally.
schedule := oneshot | recurring
oneshot := "in" duration | "at"? datetime | relday "at" time
recurring := frequency dayclause? timeclause? window? bound?
frequency := "every" [N] unit | hourly | daily | weekly | monthly | quarterly | yearly
unit := second(s) | minute(s) | hour(s) | day(s) | week(s) | month(s) | year(s)
dayclause := weekday-list | ordinal weekday ["of" "every"? "month"] | ordinal "day" | monthday-list
| "weekday" | "weekend"
timeclause := "at" time ("and" time)*
window := "between" time "and" time | "from" time "to" time
bound := N "times" | "until" date | "for" duration
ordinal := first | 1st | second | 2nd | third | 3rd | fourth | 4th | fifth | 5th | last | second to last
time := 9am | 9:30am | 09:30 | 21:00 | noon | midnight
relday := today | tomorrow | weekday-name
Defaults
- No time given for a day-based schedule →
00:00 in the job’s timezone.
every N days/weeks/months counts from the job’s start time (starts_at, or when you created it).
- A month that doesn’t have the requested day (the 31st in April, the 5th Friday) is skipped, as in RRULE. Use
last day of every month for month-end.
When parsing fails
The error points at the word it didn’t understand and, when it can, suggests a correction (tuesdy → tuesday). If a schedule is too unusual for the grammar, write it as cron, Quartz or RRULE.
Expressions are limited to 4096 UTF-8 bytes, recurrence intervals to 1,000,000
units, and occurrence counts to 100,000. These parser bounds keep invalid input
and finite-count checks bounded. Relative durations accept positive decimal
numbers with seconds, minutes, hours, days, or weeks; a day is 24 elapsed hours.
Time windows include their endpoints and must not end before their start on
the same day. Multiple times with different minute/second values, and partial-hour
windows, compile to a union of RRULE lines so they do not introduce unintended
cross-products of hours and minutes.