The problem
You have a periodic task in Celery defined with a crontab(...)
schedule, and you want to calculate the next time it's supposed to run.
Example: you want to find out when crontab(hour=12, minute=0)
will trigger next after now.
Simple, right? There’s croniter library, which seems to be designed to solve this exact problem. Just use it, right?
Well.
First mistake: trying croniter with crontab
So my first instinct was to use croniter
like this:
from celery.schedules import crontab
from croniter import croniter
from datetime import datetime
schedule = crontab(hour=12, minute=0)
cron = croniter(schedule, datetime.now())
next_run = cron.get_next(datetime)
Boom 💥 doesn’t work. Because Celery’s crontab
is not a string and croniter
expects a string like "0 12 * * *"
:
AttributeError: 'crontab' object has no attribute 'lower'
And no, crontab()
does not have a nice .as_cron_string()
method either.
So now you’re stuck parsing crontab
's internal fields (._orig_minute
, ._orig_hour
, etc) just to reconstruct a string - and it starts to smell like overengineering for something that should be simple.
The right way (which I learned too late)
Turns out Celery’s crontab
(and all schedules derived from celery.schedules.BaseSchedule
) already has a method for this:
from datetime import datetime
from celery.schedules import crontab
schedule = crontab(hour=12, minute=0)
now = datetime.now()
# `now` is datetime.datetime(2025, 6, 11, 0, 16, 58, 484085)
next_run = now + schedule.remaining_delta(now)[1]
# `next_run` is datetime.datetime(2025, 6, 11, 12, 0)
That’s it. You don’t need croniter
at all. Celery knows how to calculate the delta to the next run. It just doesn’t shout about it in the docs.
Summary
- don’t reinvent Celery’s scheduling logic - it already has what you need;
-
crontab
is not a cron string, don’t try to treat it like one; - use
.remaining_delta(last_run)
to calculate when the next run will happen.
Hope this saves someone the 2 hours I wasted trying to do it the wrong way.
Top comments (0)
Some comments may only be visible to logged-in visitors. Sign in to view all comments. Some comments have been hidden by the post's author - find out more