Build a cron expression
- Dashboard
- Documentation
- API
Why a visual cron builder?
A cron expression fits in five fields, yet remains one of the biggest sources of
bugs in production. How many times has a developer written 0 0 * * 1 thinking "every
Monday", forgetting that 1 can mean Sunday depending on the implementation? How many
times has someone confused */15 and 15? The cron builder
answers that need: visually compose a crontab expression, from common presets or
individual fields, and get the final expression ready to paste into a Linux crontab, a Kubernetes
CronJob or a GitHub Actions schedule.
The tool is the inverse of our cron decoder: where the converter takes an expression and unrolls the next executions, the builder takes human choices and produces the matching cron expression.
How it works
The graphical interface offers two complementary composition modes:
- Preset mode: a frequency selector (every minute, every hour, every day, every week, every month, every year, custom) that immediately generates a valid cron expression.
- Fields mode: five editable fields (minute, hour, day of month, month, day of
the week) where you freely enter
*, an integer, a range1-5, a list1,15,30or a step*/15.
The builder updates the expression in real time and shows a short human reading ("every day at 3am", "every 15 minutes") that acts as a safety net: if the sentence does not match your intent, the expression is probably wrong.
The five cron fields, in plain English
A standard cron expression contains five fields separated by spaces:
minute hour day-of-month month day-of-week
* * * * *
- minute (0 to 59);
- hour (0 to 23);
- day of month (1 to 31);
- month (1 to 12 or abbreviations Jan, Feb, etc.);
- day of week (0 to 7, with 0 and 7 both meaning Sunday in most implementations).
Each field accepts several forms: * (any value), a specific integer
(5), a list (1,3,5), a range (9-17), a step (*/15
every 15 values), or a combination (0-30/5).
Typical use cases
- Developer learning cron: visualise how each field interacts, without risking a wrong expression in production.
- Busy sysadmin: generate a schedule in a few seconds for a Linux cron, a Kubernetes CronJob or an Ansible job without rereading the man page.
- Developer without POSIX experience: produce a valid crontab expression for Symfony Scheduler, Laravel Scheduler or node-cron without knowing the legacy syntax.
- DevOps in review: quickly prototype an expression to propose in a pull request, then validate it with the cron decoder.
- Legacy migration: reformulate a historical cron expression through the builder to make sure the semantics is correct before pushing it elsewhere.
Common presets
Selecting a preset overwrites the individual fields and produces the matching expression:
- Every minute:
* * * * *. Avoid in production unless really needed. - Every hour:
0 * * * *. On every hour start. - Every day:
0 0 * * *. At midnight. - Every week:
0 0 * * 0. Every Sunday at midnight. - Every month:
0 0 1 * *. The 1st of the month at midnight. - Every year:
0 0 1 1 *. January 1st at midnight.
Common patterns to know
| Expression | Human reading |
|---|---|
0 0 * * * |
Every day at midnight |
*/15 * * * * |
Every 15 minutes |
0 9 * * 1-5 |
Every weekday at 9am |
0 0 1 * * |
The 1st of the month at midnight |
0 0 * * 0 |
Every Sunday at midnight |
*/5 9-17 * * 1-5 |
Every 5 minutes during business hours |
0 3 * * * |
Every day at 3am |
30 2 1,15 * * |
The 1st and 15th of the month at 2:30am |
Composing a custom expression
For more specific cases, the assistant exposes the five fields as free-text input. A few useful examples:
- Every day at 3am: minute=
0, hour=3, other fields*. - Every 15 minutes: minute=
*/15, other fields*. - Monday to Friday at 9am: minute=
0, hour=9, day-of-week=1-5. - 1st and 15th of the month at noon: minute=
0, hour=12, day-of-month=1,15. - Every 5 minutes between 9am and 5pm: minute=
*/5, hour=9-17.
How to use the cron builder
- Pick a preset (every minute, every hour, every day, every week, every month, every year) that matches the basis of your need.
- Refine if needed by directly editing the five fields (minute, hour, day of month, month, day of week).
- Read the human sentence generated by the tool to confirm the intent.
- Copy the produced cron expression with the copy button.
- Validate the schedule with our cron decoder which computes the next real execution dates.
- Paste the expression into your Linux crontab, your Kubernetes CronJob, your Symfony Scheduler or your GitHub Actions workflow.
Classic pitfalls
- Day of month and day of week combined: if neither is
*, behaviour differs across implementations. Linux/Vixie cron applies an OR; modern libraries sometimes behave differently. Avoid. - Day 1 = Monday or Sunday?: depending on the country and convention. Most Unix crons consider Sunday=0 and Saturday=6. Check your scheduler.
- Time zone: a Unix cron uses the server's time zone by default. Application schedulers (Symfony Scheduler, Quartz) often allow a dedicated zone to be set.
- Missing minute:
* * * * *runs the job every minute, which is rarely what you want. Remember to set a precise trigger (0) for hourly tasks.
Human reading and output
Alongside the cron expression, the tool offers a short human reading ("every day at midnight", "every 5 minutes"). It is a safety net: if the sentence does not match your intent, the expression is probably wrong. For a complex case, then use our cron decoder to compute the actual next execution dates.
Frequently asked questions
Can I manually edit the expression after using the interface?
Yes. The builder is not an exclusive mode: the five fields remain editable at any time. You can start from a preset, then adjust a field by hand to get a tailor-made crontab expression. The human reading is recomputed immediately.
Does the tool support the 6-field Quartz format (with seconds)?
No: the 5-field format is the Unix standard and the common base of most schedulers
(Linux crontab, Kubernetes CronJob, GitHub Actions, GitLab CI, Symfony Scheduler, Laravel Scheduler).
Quartz (Java) accepts an extra field for seconds and specific symbols
(?, L, W, #), but this need is rare.
How is the time zone handled?
The builder produces a neutral cron expression: it is the engine running the job that applies its
time zone. On a Linux crontab, that is the server TZ. On GitHub Actions, that is UTC. On
Kubernetes 1.27+, you can set spec.timeZone in the manifest. Symfony Scheduler and
Quartz expose a per-task dedicated zone.
How can I validate my expression without running it in production?
Use our cron decoder. It computes the next N executions from the current instant, without starting any job. It is the best way to confirm that a cron expression indeed fires at the planned time before deploying it.
How does this relate to Symfony Scheduler?
Symfony Scheduler accepts 5-field cron expressions via Schedule::cron('0 3 * * *', ...)
. The expression produced by the builder can therefore be pasted as is. Same for Laravel
Scheduler (->cron('...')), node-cron, Hangfire and Airflow.
Should I prefix the command in the system crontab?
Yes, in /etc/crontab you need a user (0 3 * * * www-data /usr/bin/php
...), whereas crontab -e per user omits it. The expression itself stays
the same.
Example request
curl -X POST https://cdrn.fr/api/v1/tools/cron-builder/execute \
-H "Content-Type: application/json" \
-d '{"preset":"none","minute":"*","hour":"*","day_of_month":"*","month":"*","day_of_week":"*"}'
Input schema
| Field | Type | Required | Default |
|---|---|---|---|
preset |
choice (none, every_minute, hourly, daily, weekly, monthly, yearly) | – | none |
minute |
string | – | * |
hour |
string | – | * |
day_of_month |
string | – | * |
month |
string | – | * |
day_of_week |
string | – | * |
Endpoints
GET https://cdrn.fr/api/v1/tools- lists every available toolGET https://cdrn.fr/api/v1/tools/cron-builder- returns the schema for this toolPOST https://cdrn.fr/api/v1/tools/cron-builder/execute- runs this tool with a JSON payload