I need to write an regular expression that matches Cron time expressions, like these ones:
It is a wildcard for every part of the cron schedule expression. So * * * * * means every minute of every hour of every day of every month and every day of the week .
To validate cron expressions in general, it'll depend greatly on the specific implementation you're using
In general, most adhere to the the following format:
Field name | Mandatory? | Allowed values | Special characters |
---|---|---|---|
Seconds | No* | 0-59 | * / , - |
Minutes | Yes | 0-59 | * / , - |
Hours | Yes | 0-23 | * / , - |
Day of month | Yes | 1-31 | * / , - L W |
Month | Yes | 1-12 or JAN-DEC | * / , - |
Day of week | Yes | 0-6 or SUN-SAT | * / , - L # |
Year | No* | 1970–2099 | * / , - |
*where seconds and years are non-standard and sometimes not included
Some flavors allow predefined time periods like this:
Entry | Equivalent to |
---|---|
@annually | 0 0 0 1 1 * * |
@yearly | 0 0 0 1 1 * * |
@monthly | 0 0 0 1 * * * |
@weekly | 0 0 0 * * 0 * |
@daily | 0 0 0 * * * * |
@hourly | 0 0 * * * * * |
@reboot |
Some flavors allow using the @every <duration>
syntax with the following timespan units:
Unit | Definition |
---|---|
ns |
nanosecond |
us , µs
|
microsecond |
ms |
millisecond |
s |
second |
m |
minute |
h |
hour |
To validate predefined macros, you can use the following regex:
/@(annually|yearly|monthly|weekly|daily|hourly|reboot)/
Which will pass the following test cases:
@daily
@hourly
@every
RegexTo validate @every
durations, you can use the following regex:
/@every (\d+(ns|us|µs|ms|s|m|h))+/
Which will pass the following test cases:
@every 5s
@every 20h30m
Validating cron terms in the regular expression is a little trickier since there are so many variations.
Just focusing in on a single term, the following are all valid:
,
/
or -
*
To validate a single term, we can use the following regex:
/(\d+,)+\d+|(\d+(\/|-)\d+)|\d+|\*/
where \d+
just guarantees you have 1 or more numeric digits
Which will pass the following test cases:
1,2,3
1,2
1/2
1-2
1
*
To check the full expression, we can just make sure we have {5,7}
terms with the following regex:
/(((\d+,)+\d+|(\d+(\/|-)\d+)|\d+|\*) ?){5,7}/
If we wanted to distinguish between each term, we'd need to validate numbers within a certain range:
Allowed values | Regex |
---|---|
0-59 | [1-5]?[0-9] |
0-23 | 2[0-3]|1[0-9]|[0-9] |
1-31 | 3[01]|[12][0-9]|[1-9] |
1-12 | 1[0-2]|[1-9] |
0-6 | [0-6] |
1970–2099 | 19[7-9][0-9]|20[0-9][0-9] |
If however, we just want to make sure something looks like a regex expression without worrying about which term is days vs. hours, the expression stays a lot cleaner, so that's what I'll go with for simplicity
By combining the above statements, we can have a relatively simple sanity check that the term looks regex-y with the following expression:
/(@(annually|yearly|monthly|weekly|daily|hourly|reboot))|(@every (\d+(ns|us|µs|ms|s|m|h))+)|((((\d+,)+\d+|(\d+(\/|-)\d+)|\d+|\*) ?){5,7})/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With