Calculate Your CRON Occurrences with Ease

Jakub Miziński
3 min readDec 29, 2023

--

Hello! I want to introduce you to a new tool for determining your CRON job occurrences. For a given CRON string, you can check occurrences in a specific period, regardless of whether it is in the future or the past. It is not an essential tool, but after the second time I needed it, combined with the motivation to give back to the Open Source community, I decided to share it. As the Poles say, “bake two roasts on one fire.”

It ain’t much but it’s honest work

I assume that you are familiar with CRON; if not, check this Wiki page: https://en.wikipedia.org/wiki/Cron.

“Users who set up and maintain software environments use cron to schedule jobs(commands or shell scripts), also known as cron jobs, to run periodically at fixed times, dates, or intervals.”

Each line of a crontab file represents a job, and looks like this:

# ┌───────────── minute (0–59)
# │ ┌───────────── hour (0–23)
# │ │ ┌───────────── day of the month (1–31)
# │ │ │ ┌───────────── month (1–12)
# │ │ │ │ ┌───────────── day of the week (0–6) (Sunday to Saturday;
# │ │ │ │ │ 7 is also Sunday on some systems)
# │ │ │ │ │
# │ │ │ │ │
# * * * * * <command to execute>

Let’s say you are planning a holiday and need to check how many times some mysterious script will run by crontab on your server while you are away. It’s easy with CronCalc!

CronCalc.new('0 0 * * SUN').in(Time.new(2023,12,23)..Time.new(2024,1,7)).count
#=> 3

period = Time.new(2023,12,23)..Time.new(2024,1,7)
CronCalc.new('0 0 * * SUN').in(period)
#=> [2023-12-24 00:00:00 +0100, 2023-12-31 00:00:00 +0100, 2024-01-07 00:00:00 +0100]

Now you know! Well, maybe it’s easy when the CRON expression isn’t complicated and the calendar is next to you, but imagine it’s not. And you need to determine the next two occurrences after your visit to the endocrinologist you’ve just scheduled in two years. Here’s how:

CronCalc.new('5 5 */2 8-12 SAT').next(2, after: Time.new(2025, 9, 5))
#=> [2025-09-13 05:05:00 +0200, 2025-09-27 05:05:00 +0200]

# And when will the next occurrence be? Hmmm...
CronCalc.new('5 5 */2 8-12 SAT').next
#=> [2024-08-03 05:05:00 +0200]

Seems handy. Now, visualize that something bad happened, and you suspect it is related to your mysterious CRON job. We need to discover exactly when this CRON job occurred, but before a certain date.

Let’s use CronCalc!

cron_calc = CronCalc.new('0 8 * FEB-MAY MON,WED,FRI')
cron_calc.last(before: Time.new(2022,4,1))
#=> [2022-03-30 08:00:00 +0200]

# What about the last three occurrences?
cron_calc.last(3)
#=> [2023-05-31 08:00:00 +0200, 2023-05-29 08:00:00 +0200, 2023-05-26 08:00:00 +0200]

Great! Now I know everything! Let’s finally check quickly when the next unofficial holiday in Poland occurs: Ice Cream Wednesday.

CronCalc.new('0 23 * * WED').next
# => [2024-01-03 23:00:00 +0100]

OK, maybe that one was easy. But I hope someone finds this tool useful. The gem is called cron_calc, and you can find it here: https://github.com/mizinsky/cron_calc. If you have any ideas on how to improve it, let me know! I am happy to do so.

--

--