Cron Expression to systemd Timer Converter

Free tool to convert a cron expression (minute hour day month weekday) into systemd timer OnCalendar= syntax. Warns about the day-of-month/day-of-week OR-semantics caveat, useful for migrating cron jobs to Docker/Kubernetes environments.

Cron Field to systemd Component Mapping

The 5 fields of a cron expression map to systemd's OnCalendar= syntax as follows.

Position Cron field systemd equivalent
1 Minute Minute of the time part (MM in HH:MM:SS)
2 Hour Hour of the time part (HH in HH:MM:SS)
3 Day of month Day of the date part (day in year-month-day)
4 Month Month of the date part (month in year-month-day)
5 Day of week Weekday prefix (e.g. Mon, Mon..Fri)

Since cron has no seconds field, the systemd seconds component is always "00". When both day-of-month and month are unrestricted (*), the year-month-day part of systemd can be omitted entirely.

Cron Weekday Number to systemd Weekday Abbreviation

Cron represents weekdays as numbers 0-7, while systemd uses English weekday abbreviations.

Cron weekday number systemd weekday abbreviation
0 (7) Sun
1 Mon
2 Tue
3 Wed
4 Thu
5 Fri
6 Sat

Common Conversion Examples

Cron expression OnCalendar= Meaning
* * * * * OnCalendar=*-*-* *:*:00 Runs every minute (equivalent to cron's "* * * * *").
*/15 * * * * OnCalendar=*:00/15:00 Runs every 15 minutes.
0 9 * * 1-5 OnCalendar=Mon..Fri 09:00:00 Runs at 9:00 AM on weekdays (Monday through Friday).
0 0 1 * * OnCalendar=*-*-01 00:00:00 Runs at midnight on the 1st of every month.
0 0 1 1 * OnCalendar=*-01-01 00:00:00 Runs at midnight on January 1st every year.
0 0 1 * 1 OnCalendar=Mon *-*-01 00:00:00 An example specifying both day-of-month (the 1st) and day-of-week (Monday). In cron this is an OR condition (runs if either matches), but in systemd it becomes an AND condition (runs only when both match), so the converted result fires less often than the original cron expression.

A cron expression that restricts both day-of-month and day-of-week (neither is "*") cannot be converted accurately to systemd's OnCalendar syntax, because cron uses OR semantics there while systemd uses AND semantics. Consider splitting such cases into two separate systemd timers.

Tips

  • If you restrict both day-of-month and day-of-week to something other than "*", cron's OR condition cannot be represented exactly by systemd's AND condition. Check the warning in the result and consider splitting into two timers if needed.
  • Some minimal container base images (e.g. Alpine-based Docker images) don't ship a cron daemon at all, making systemd timers a practical replacement when migrating scheduled jobs.
  • You can validate the generated OnCalendar line with the "systemd-analyze calendar" command, which also shows the next scheduled run times.
  • Unlike a single crontab line, a systemd timer is made of two files: a .timer unit (the schedule) and a .service unit (the actual job to run).
  • For simple schedules that don't combine day-of-month and day-of-week (hourly, daily, weekly, etc.), this conversion is always exact.

Frequently Asked Questions

OnCalendar= takes the form "weekday year-month-day hour:minute:second" (the weekday and date parts are optional). "*" means "any value", ".." denotes a range, "/" denotes a step, and "," lists multiple values. For example, "Mon..Fri 09:00:00" means exactly 9:00 AM on weekdays.

systemd timers offer features cron alone doesn't: centralized execution logs via journalctl, waiting for dependent services to start, and configurable automatic retries on failure. Container base images are also increasingly stripped of the cron daemon to stay lightweight, so on systemd-based hosts, timers become the natural replacement.

Under Vixie cron semantics, when both day-of-month and day-of-week are restricted (not "*"), the job runs if either one matches — an OR condition. systemd's OnCalendar syntax, however, always treats the weekday and date parts as an AND condition (both must match). This tool detects that case and shows a warning that the converted result may run less often than the original cron expression.

For simple schedules that don't combine day-of-month and day-of-week, the conversion is exact. If the OR-semantics warning appears, though, the frequency may differ from what you intended, so we recommend checking the next scheduled run times with "systemd-analyze calendar" before deploying it to production.

A standard 5-field cron expression has no seconds field, so the seconds component of the generated OnCalendar line is always "00". systemd's OnCalendar syntax itself does support specifying seconds, but this tool doesn't use that when converting from cron.
ツールくん

Side Note — From Cron to systemd Timers

systemd emerged around 2010 as an init system for managing Linux boot processes and has since become the standard on most distributions. Its timer feature provides periodic execution much like cron, but adds capabilities cron never had: dependency resolution, centralized execution logging via journalctl, and configurable retry behavior on failure.

Meanwhile, container environments like Docker and Kubernetes increasingly ship base images without a cron daemon at all, in order to keep image sizes small. When a periodic job needs to run in such environments, the practical options are to rely on an orchestrator-level mechanism such as a Kubernetes CronJob, or to hand it off to systemd timers if the host itself runs systemd.

The OnCalendar= syntax is more expressive than cron's 5 fields — supporting year-level specificity and second-level precision — but that extra expressiveness means some cron expressions (those restricting both day-of-month and day-of-week as an OR condition) change meaning under a naive conversion. This tool surfaces that warning explicitly so migrations don't trip over a pitfall that's easy to miss.