Free systemd OnCalendar Tester
Paste the OnCalendar line from a .timer unit to see how systemd normalizes it and the next five times it will fire.
What is a systemd OnCalendar Tester?
systemd timers replace cron on most modern Linux systems, and their OnCalendar= line says when a timer fires. This tester reads an OnCalendar expression, shows the normalized form systemd would use, and lists its next five elapse times.
Parsing follows the calendar event rules in systemd.time(7): weekday lists and ranges, dates and times with stars, lists, ranges and repetitions, the tilde for counting back from a month’s end, and an optional time zone. The output is laid out like systemd-analyze calendar --iterations=5.
Key Features
Normalized Form, as systemd Shows It
Shorthands like daily and weekly are expanded, missing parts are filled in, and numbers are padded. Comparing the normalized form with what you meant catches most mistakes.
Five Real Elapse Times
See the next five times the timer fires, with weekday names, so a schedule that only runs on the 31st or in February stands out.
Month-End Rules Handled
The tilde counts back from the last day, so *-*~01 is the last day of every month and Fri *-*~07/1 is the last Friday.
Any Time Zone
Evaluate in UTC or your browser’s zone, or end the expression with a zone like Europe/Berlin, as systemd 235 and later allow.
No Linux Box Needed
Test timers from a Mac, Windows or a phone, in the browser, without uploading your unit files.
Perfect for everyone
- Linux administrators moving jobs from cron to systemd timers
- Developers writing .timer units
- SREs checking when maintenance timers will fire
How to Use the systemd OnCalendar Tester
Paste the expression, choose a time zone, and compare the normalized form with what you meant.
Copy the OnCalendar Value
Take everything after OnCalendar= in your .timer file, such as Mon..Fri *-*-* 09:00:00, or a shorthand like daily.
Choose UTC or Your Time Zone
systemd evaluates expressions without a zone in the machine’s local time. Pick the zone that matches the server, or add one to the expression.
Check the Normalized Form
This is the fully spelled-out expression. Missing seconds become :00 and a missing date becomes *-*-*, so you can see exactly what will match.
Read the Next Elapses
The first line is the next elapse and the rest follow in order. If they’re not what you expected, adjust and watch them change.
OnCalendar Expressions, Evaluated
Each answer is this tester’s output in UTC mode, computed from Sunday 25 October 2026 at 00:00 UTC, in the layout of systemd-analyze calendar. Predict the next elapse first.
“daily”
“Mon..Fri 9:00”
“*-*-* *:00/15:00”
“*-*~01 18:00”
“Fri *-*~07/1 17:00”
“quarterly”
“*-*-* 09:00 Europe/Berlin”
“2026-12-25 08:30”
“*-02-30”
“Mon..Fri 25:00”
How a systemd Calendar Event Is Written
The full form is DayOfWeek Year-Month-Day Hour:Minute:Second TimeZone, and almost every part is optional. These ten rules are the ones that matter.
Shorthands
minutely, hourly, daily, weekly, monthly, quarterly, semiannually and yearly each expand to a full expression. weekly means Monday at midnight.
“What does weekly expand to?”
Weekdays Are Optional and Filter
A weekday list or range at the start limits the matching days. Mon..Fri is Monday to Friday, and Sat,Sun is the weekend.
“How do you write weekdays only?”
Missing Date Means Every Day
If you leave the date out, systemd uses *-*-*, every day. 9:00 alone runs daily at nine.
“What date does 09:00 imply?”
Missing Time Means Midnight
A date with no time runs at 00:00:00. *-*-01 fires at midnight on the first of every month.
“When does *-*-01 fire?”
Seconds Default to Zero
09:30 is the same as 09:30:00. Add seconds only when a timer must fire at a specific second.
“Is 09:30 the same as 09:30:00?”
Two Dots Make a Range
systemd writes ranges with two dots, not a dash, because dashes separate the date. 01..03 in the month field is January to March.
“How do you write hours 9 to 17?”
A Slash Repeats
start/step repeats from the start value, so *:00/15 fires at 00, 15, 30 and 45 minutes past every hour.
“How do you run every 20 minutes?”
A Tilde Counts From the Month’s End
Replacing the dash before the day with a tilde counts backwards: ~01 is the last day, ~02 the one before. ~07/1 covers the last seven days.
“How do you write the last day of every month?”
Commas List Values
Any field takes a comma-separated list, such as 08,20 for 8 a.m. and 8 p.m. Lists and ranges can be mixed.
“How do you fire at 08:00 and 20:00?”
A Time Zone Comes Last
Since systemd 235, an IANA zone or UTC can end the expression, and the timer follows that zone instead of the machine’s.
“How do you pin a timer to Berlin time?”
Coming From Cron
OnCalendar covers everything cron does, with different spelling. These are the usual translations.
Every Five Minutes
Cron’s */5 * * * * becomes *:00/5 in OnCalendar. Add Persistent=true if missed runs should catch up after downtime.
Nightly at 2:30
Cron’s 30 2 * * * becomes *-*-* 02:30:00, or simply 02:30.
Weekdays at Nine
Cron’s 0 9 * * 1-5 becomes Mon..Fri 09:00. Note the two-dot range.
First of the Month
Cron’s 0 0 1 * * becomes monthly, or *-*-01 00:00:00 written out.
Day AND Weekday
Cron runs when the day of month or the weekday matches, while OnCalendar requires both. Fri *-*-13 is genuinely Friday the 13th.
Last Day of the Month
Standard cron can’t express it, but OnCalendar writes *-*~01. Combine it with a weekday for the last Monday or Friday.
OnCalendar Mistakes
These are the usual reasons a timer fires at the wrong time or not at all.
Using a Dash for Ranges
Mon-Fri doesn’t parse, because dashes separate date fields. Write Mon..Fri.
Forgetting the Machine’s Time Zone
Without a zone, systemd uses the system clock’s local time. A cloud VM in UTC fires 09:00 at 09:00 UTC.
Expecting Missed Runs to Catch Up
By default a timer that was off when it should have fired just waits for the next elapse. Set Persistent=true in the [Timer] section to run once on boot.
Forgetting the Randomized Delay
RandomizedDelaySec adds a random delay to each elapse, so the job runs later than the times shown here. It spreads load across many machines.
Dates That Never Occur
*-02-30 never elapses, and a fixed date in the past fires nothing. The tester reports both instead of an empty list.
Mixing Up Repetition and Lists
*:00/30 fires at :00 and :30, while *:30 fires only at :30. Check the elapse list to be sure.
Editing Without Reloading
After changing a .timer file, run systemctl daemon-reload and restart the timer, or the old schedule stays active.
Assuming AccuracySec Is Exact
Timers fire within a one-minute window by default to save power. Set AccuracySec=1s for jobs that must start on the second.
Timer Settings That Change When a Job Runs
OnCalendar sets the schedule, and these [Timer] options adjust how systemd acts on it.
Persistent=true
Records the last run on disk and fires once at boot if an elapse was missed while the machine was off. Laptops and VMs that sleep need it.
RandomizedDelaySec=
Adds a random delay up to the given time to every elapse. Use it on fleets so thousands of machines don’t hit a server at the same second.
AccuracySec=
Lets systemd fire anywhere within this window, one minute by default, so it can batch wakeups. Lower it for jobs that must start precisely.
OnBootSec= and OnUnitActiveSec=
These are monotonic timers that count from boot or from the last activation instead of the calendar. They suit intervals that don’t need to line up with the clock.
Unit=
Names the service the timer starts. By default a timer called backup.timer starts backup.service.
Several OnCalendar Lines
A timer can hold more than one OnCalendar= line, and it fires whenever any of them elapses. Test each line here separately.
When to Preview a Timer
Before enabling a timer, and whenever one fires unexpectedly.
Migrating a Crontab to systemd
Rewrite each cron line as an OnCalendar expression and compare the elapse lists before switching over.
Writing a Backup Timer
Confirm that a nightly backup fires once a day, at the hour you expect, in the server’s zone.
Scheduling Month-End Jobs
Check that billing or reporting timers built with the tilde land on the last day of each month, including February.
Reviewing a Colleague’s Unit File
Paste the OnCalendar line from a pull request and read the normalized form before approving it.
Testing Without a Linux Machine
Check a schedule from your laptop when you can’t run systemd-analyze on the server itself.
Planning Across Time Zones
Add a zone like America/New_York to see when a timer fires for users there, including clock changes.
Learning the Syntax
Try ranges, steps and the tilde one at a time and watch the normalized form and elapses change.