Hi all! A co-worker is trying to schedule a Flow t...
# ask-community
d
Hi all! A co-worker is trying to schedule a Flow to run on the 2nd of every month, at 8:00 AM PT. I pointed him to the
IntervalSchedule
with
pendulum
(since that’s what I’ve used for daily/weekly tasks) but he noticed that the results don’t quite line up with what he was expecting:
Copy code
import pendulum
from prefect.schedules.schedules import IntervalSchedule
from prefect.schedules.clocks import CronClock

# Set our start date.
next_start_date: pendulum.DateTime = (
    pendulum.now(tz="America/Los_Angeles")
    .start_of(unit="month")
    .set(day=2, hour=8, minute=0, second=0)
)

# Set our monthly interval.
monthly: pendulum.Duration = pendulum.duration(months=1)

# Inspect the next few clock emissions.
schedule: IntervalSchedule = IntervalSchedule(start_date=next_start_date, interval=monthly)
print(schedule.next(n=3))
# [
#   DateTime(2022, 1, 1, 8, 0, 0, tzinfo=Timezone('America/Los_Angeles')), 
#   DateTime(2022, 1, 31, 8, 0, 0, tzinfo=Timezone('America/Los_Angeles')), 
#   DateTime(2022, 3, 2, 8, 0, 0, tzinfo=Timezone('America/Los_Angeles'))
# ]
Why does the
IntervalSchedule
not fire on
2022-01-02
,
2022-02-02
,
2022-03-02
, etc? It appears to just be incrementing by 30 days, but that’s not quite what I’d expect. Is this a
pendulum
thing? (Edit: it’s maybe worth noting that in the example above, just doing
next_start_date + monthly
does give you the correct
DateTime(2022, 1, 2, 8, 0, 0, tzinfo=Timezone('America/Los_Angeles'))
. So I think it may actually be a Prefect thing?)
On further inspection, it looks like the problem is that: 1. We pass a
pendulum.Duration
to the
IntervalSchedule
function, which “casts” it as a
datetime.timedelta
before passing to the
IntervalClock
initializer. 2. In
Schedule.next
we call
_get_clock_events
which calls
clocks.events
. 3.
IntervalClock
does some book-keeping but ultimately extracts
days = interval.days
from our input interval. Here,
monthly.days
defaults to 30 since it has no notion of which month we’re referring to. Hence, the
IntervalClock
will always assume that each monthly
pendulum.Duration
is equivalent to 30 days. I’m not exactly sure how to fix that, but maybe it starts with casting
interval
to a
pendulum.Duration
?
a
Using the good old cron, this would be:
Copy code
import pendulum
from prefect.schedules import CronSchedule

schedule = CronSchedule("0 8 2 * *", start_date=pendulum.today(tz="America/Los_Angeles"))

for sched in schedule.next(20):
    print(sched)
but we also support RRule schedules, maybe it can be even easier for you
d
Yeah, I ended up pointing him to CronSchedule which works as expected. This just seems like a bug in the
IntervalScheduler
, so I was wondering if it was known. Would it be helpful to file an issue? I couldn’t find any existing issues referring to this situation 🤔 Regardless, thank you @Anna Geller!
z
this website is a life saver https://crontab.guru
upvote 2