— Developer Tools

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.

— Samples
Valid
Live

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.

1

Copy the OnCalendar Value

Take everything after OnCalendar= in your .timer file, such as Mon..Fri *-*-* 09:00:00, or a shorthand like daily.

2

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.

3

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.

4

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.

Worked Examples

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.

REF_001Shorthand

“daily”

REF_002Weekday range

“Mon..Fri 9:00”

REF_003Every 15 minutes

“*-*-* *:00/15:00”

REF_004Last day of the month

“*-*~01 18:00”

REF_005Last Friday

“Fri *-*~07/1 17:00”

REF_006Quarterly

“quarterly”

REF_007Named time zone

“*-*-* 09:00 Europe/Berlin”

REF_008One date

“2026-12-25 08:30”

REF_009A date that never comes

“*-02-30”

REF_010Hour out of range

“Mon..Fri 25:00”

Syntax

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.

01 / SHORTHANDS

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?”

02 / WEEKDAYS

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?”

03 / MISSING

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?”

04 / MISSING

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?”

05 / SECONDS

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?”

06 / TWO

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?”

07 / A

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?”

08 / A

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?”

09 / COMMAS

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?”

10 / A

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.

Tip 01

Using a Dash for Ranges

Mon-Fri doesn’t parse, because dashes separate date fields. Write Mon..Fri.

Tip 02

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.

Tip 03

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.

Tip 04

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.

Tip 05

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.

Tip 06

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.

Tip 07

Editing Without Reloading

After changing a .timer file, run systemctl daemon-reload and restart the timer, or the old schedule stays active.

Tip 08

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.

Tip 01

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.

Tip 02

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.

Tip 03

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.

Tip 04

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.

Tip 05

Unit=

Names the service the timer starts. By default a timer called backup.timer starts backup.service.

Tip 06

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.

Frequently Asked Questions