Minuteform / Cron syntax comparison
$ diff crontab quartz spring aws github k8s
Cron syntax compared: crontab, Quartz, Spring, AWS, GitHub Actions, Kubernetes
“Cron expression” means at least six different things. Field counts run from five to seven, Sunday can be 0, 1 or 7, and some dialects need ? where others reject it. Every cell below links to the official documentation it comes from.
Minuteform reads standard five-field cron only (minute, hour, day of month, month, day of week), as used by Vixie cron, cronie, GitHub Actions and Kubernetes. It does not accept seconds, years, macros, or Quartz characters such as ? L W #. For Quartz, Spring or AWS, use this page to translate. Then drop the seconds (and year) field to check the minute-level schedule in the tool.
01Property by property
On narrow screens, scroll the table sideways. “Not stated” means the official docs do not say, not that the feature is missing.
| Property | Vixie cron / cronie | Quartz 2.3 | Spring @Scheduled | AWS EventBridge | GitHub Actions | Kubernetes CronJob |
|---|---|---|---|---|---|---|
| Fields and order | 5: min hour dom mon dow, then the command. A system crontab adds a user field. Vixie crontab(5) · cronie crontab(5) |
6 or 7: sec min hour dom mon dow [year] Quartz tutorial |
6: sec min hour dom mon dow CronExpression |
6: cron(min hour dom mon dow year) AWS rules · Scheduler |
5, POSIX cron: min hour dom mon dow GitHub docs |
5: min hour dom mon dow k8s docs |
| Seconds field | No. cron checks entries once a minute. Vixie · cronie cron(8) | Yes, first field, 0–59 CronExpression | Yes, first field, 0–59 CronExpression | No. The finest resolution is one minute. AWS | No GitHub | No k8s |
| Year field | No crontab(5) | Optional 7th field. The tutorial says 1970–2099; the 2.3.0 Javadoc says 1970–2199. tutorial · Javadoc | No CronExpression | Required 6th field, 1970–2199. Use * for every year. AWS |
No GitHub | No k8s |
| Day of month | 1–31. Vixie’s current source also accepts $ for the last day (added 2023, so distribution builds may lack it). Vixie · cronie |
1–31 tutorial | 1–31 CronExpression | 1–31 AWS | 1–31 GitHub | 1–31 k8s |
| Month | 1–12 or jan–dec. cronie allows ranges and lists of names; Vixie says ranges of names are not allowed. cronie · Vixie |
The tutorial says 1–12; the 2.3.0 Javadoc says 0–11. JAN–DEC works in both, so prefer names. tutorial · Javadoc |
1–12 or JAN–DEC CronExpression |
1–12 or JAN–DEC AWS |
1–12 or JAN–DEC GitHub |
1–12. Month names: not stated. k8s |
| Day of week · Sunday is | 0–7, Sunday = 0 or 7, or sun–sat Vixie · cronie |
1–7, Sunday = 1, or SUN–SAT tutorial |
0–7, Sunday = 0 or 7, or MON–SUN. The Javadoc notes that Quartz’s 1–7 deviates from cron. CronExpression |
1–7, Sunday = 1, or SUN–SAT AWS |
0–6, Sunday = 0, or SUN–SAT. 7 is not stated. GitHub |
0–6, Sunday = 0, or sun–sat. 7 is not stated. k8s |
| Special characters | * , - /. cronie adds ~ for a random value in a range. No ? L W #. cronie · Vixie |
* , - / ?, plus L W LW in day of month and L # in day of week tutorial |
* , - / ?, plus L L-n W LW in day of month and dL d#n in day of week CronExpression |
* , - /, plus ? L W in day of month and ? L # in day of week. No / in day of week. AWS |
* , - / only GitHub |
* , - /. ? means the same as *. L W # not stated. k8s |
| Day of month + day of week | If both are restricted, the job runs when either matches (OR) cronie | One of the two must be ? tutorial |
? is optional and works like *. Combined behaviour: not stated. reference |
One of the two must be ? AWS |
Not stated (POSIX cron uses OR) GitHub | Not stated k8s |
| Macros | cronie: @reboot @yearly @annually @monthly @weekly @daily @hourly. Not stated in Vixie’s crontab(5). cronie |
None documented Javadoc | @yearly @annually @monthly @weekly @daily @midnight @hourly CronExpression |
None. Use rate(5 minutes); Scheduler also has one-time at(…). AWS rules · Scheduler |
Not supported, explicitly: @yearly, @daily, @reboot and the rest GitHub |
@yearly @annually @monthly @weekly @daily @midnight @hourly k8s |
| Default time zone | Local time of the cron daemon cronie | The JVM’s default time zone CronTriggerImpl | The scheduler’s time zone @Scheduled.zone | Rules: always UTC. Scheduler: UTC unless a zone is set. rules · Scheduler | UTC GitHub | Local time zone of kube-controller-manager k8s |
| Setting a zone | cronie: CRON_TZ=Europe/Berlin line in the crontab. Vixie: not stated. cronie |
CronScheduleBuilder.inTimeZone(…) or CronExpression.setTimeZone(…) CronScheduleBuilder |
@Scheduled(cron = "…", zone = "Europe/Berlin") reference |
Scheduler only: ScheduleExpressionTimezone. Rules cannot change zone. Scheduler |
Optional timezone: "America/New_York" next to cron: GitHub |
.spec.timeZone: "Etc/UTC", stable since v1.27 (alpha 1.24, beta 1.25). CRON_TZ/TZ inside schedule is rejected. k8s · KEP-3140 |
| Minimum interval | 1 minute, since cron wakes once a minute cron(8) | Not stated; the seconds field allows 1 s schedules Javadoc | Not stated; the seconds field allows 1 s schedules CronExpression | 1 minute. Faster rates are not supported. AWS | 5 minutes. Runs can be delayed at busy times such as the top of the hour. GitHub | Not stated (1 minute by syntax). The controller checks every 10 seconds; a run can be missed or doubled, so make Jobs idempotent. k8s |
02Ten common schedules in every dialect
All times are in the scheduler’s time zone (see above). not expressible means the documented syntax cannot say it. The usual workaround is to schedule more often and test the date inside the job, which is outside cron syntax. Each expression uses only the syntax documented in the sources linked in section 01. Five-field expressions open in Minuteform.
| Schedule | Vixie cron / cronie | Quartz | Spring | AWS EventBridge | GitHub Actions | Kubernetes |
|---|---|---|---|---|---|---|
| Weekdays at 09:30 | 30 9 * * 1-5 | 0 30 9 ? * MON-FRI | 0 30 9 * * MON-FRI | cron(30 9 ? * MON-FRI *) | 30 9 * * 1-5 | 30 9 * * 1-5 |
| Every 15 minutes | */15 * * * * | 0 0/15 * * * ? | 0 */15 * * * * | cron(0/15 * * * ? *) or rate(15 minutes) | */15 * * * * | */15 * * * * |
| Every day at midnight | 0 0 * * * · cronie: @daily | 0 0 0 * * ? | 0 0 0 * * * or @daily | cron(0 0 * * ? *) | 0 0 * * * (no @daily) | 0 0 * * * or @daily |
| Every 2 hours on weekends | 0 */2 * * 0,6 | 0 0 0/2 ? * SAT,SUN | 0 0 */2 * * SAT,SUN | cron(0 0/2 ? * SAT,SUN *) | 0 */2 * * 0,6 | 0 */2 * * 0,6 |
| 1 January at 00:00 | 0 0 1 1 * · cronie: @yearly | 0 0 0 1 JAN ? | 0 0 0 1 1 * or @yearly | cron(0 0 1 1 ? *) | 0 0 1 1 * | 0 0 1 1 * or @yearly |
| Last day of the month at 23:00 | not expressible in cronie. Vixie master only: 0 23 $ * * | 0 0 23 L * ? | 0 0 23 L * * | cron(0 23 L * ? *) | not expressible | not expressible |
| First Monday of the month at 09:00 | not expressible. 0 9 1-7 * 1 means days 1–7 or any Monday. | 0 0 9 ? * 2#1 | 0 0 9 ? * MON#1 | cron(0 9 ? * 2#1 *) | not expressible | not expressible |
| Last Friday of the month at 17:00 | not expressible | 0 0 17 ? * 6L | 0 0 17 ? * 5L (or FRIL) | cron(0 17 ? * 6L *) | not expressible | not expressible |
| Weekday nearest the 15th at 08:00 | not expressible | 0 0 8 15W * ? | 0 0 8 15W * ? | cron(0 8 15W * ? *) | not expressible | not expressible |
| Every 30 seconds | not expressible | 0/30 * * * * ? | */30 * * * * * | not expressible (1 minute minimum) | not expressible (5 minute minimum) | not expressible |
Day-of-week numbers change between dialects: Monday is 1 in crontab, GitHub, Kubernetes and Spring, but 2 in Quartz and AWS, and Friday is 5 versus 6. Names such as MON and FRI avoid the mistake wherever a dialect accepts them.
03Gotchas when moving a schedule between dialects
- Count the fields first. A 6-field Spring expression pasted into crontab is read as minute, hour, day, month, weekday, then a command.
0 30 9 * * *becomes “minute 0 of hour 30”, which is invalid. - Sunday is 0, 1 or 7.
1-5means Monday–Friday in crontab but Sunday–Thursday in Quartz and AWS. ?is required in Quartz and AWS in either day of month or day of week, accepted as*in Spring and Kubernetes, and not documented in GitHub Actions.- Steps restart in each field.
*/45in the minute field runs at :00 and :45, not every 45 minutes. AWS writes the same idea as0/45. - Time zones differ by default. GitHub Actions and AWS rules use UTC; crontab, Quartz, Spring and Kubernetes use the host’s zone unless you set one. Daylight saving then matters: see cron and DST.
- Docs disagree with themselves. Quartz 2.3’s tutorial and Javadoc give different month and year ranges, so use month names there. cronie’s crontab(5) and cron(8) describe DST differently.
04Sources
All opened and checked on 19 October 2026. Vendors update their docs, so follow the links for the current wording.
- Vixie (ISC) cron, crontab.5 (GitHub master, including the 2023
$addition) - cronie crontab(5) and cron(8) on man7.org
- Quartz 2.3.0 CronTrigger tutorial, CronExpression Javadoc, CronScheduleBuilder, CronTriggerImpl
- Spring CronExpression Javadoc (since 5.3), Spring reference: task scheduling, @Scheduled Javadoc
- Amazon EventBridge: schedule patterns for scheduled rules, creating a scheduled rule, EventBridge Scheduler: schedule types
- GitHub Actions: events that trigger workflows, schedule and workflow syntax
- Kubernetes CronJob concepts, CronJob API reference, KEP-3140: CronJob time zone