Daylight saving on interval trigger
See original GitHub issueHello,
We observed an issue on during the daylight saving clock on Europ/Brussels TZ during the night of 30 March and 31 March. After this time every schedule is executed with 1 hour of delay.
We thing it’s an issue on the interval trigger (the cron trigger is already reported on your website). Mabe it is a behavior expected. But we want to have more information about it.
Test
We did a simple test during in order to tackel the issue:
import pytz
import datetime
from apscheduler.schedulers.background import BackgroundScheduler
def task():
print("TASK EXECUTED")
scheduler = BackgroundScheduler()
scheduler.add_job(task, 'interval',
start_date=datetime.datetime(2019, 3, 26, 16, 0, 0),
days=7
)
scheduler.add_job(task, 'interval',
start_date=datetime.datetime(2019, 4, 2, 17, 0, 0),
days=7
)
scheduler.add_job(task, 'interval',
start_date=datetime.datetime(2019, 4, 2, 20, 0, 0),
days=7
)
scheduler.start()
scheduler.print_jobs()
Expected Behavior
output expected:
Jobstore default:
task (trigger: interval[7 days, 0:00:00], next run at: 2019-04-02 16:00:00 CEST)
task (trigger: interval[7 days, 0:00:00], next run at: 2019-04-02 17:00:00 CEST)
task (trigger: interval[7 days, 0:00:00], next run at: 2019-04-02 20:00:00 CEST)
Where we shedule at 16:00.
Current Behavior
output expected:
Jobstore default:
task (trigger: interval[7 days, 0:00:00], next run at: 2019-04-02 17:00:00 CEST)
task (trigger: interval[7 days, 0:00:00], next run at: 2019-04-02 17:00:00 CEST)
task (trigger: interval[7 days, 0:00:00], next run at: 2019-04-02 20:00:00 CEST)
Where we shedule at 17:00 and we expect 16:00
Solution (path)
The path we made now, it’s changing the method get_next_fire_time
in trigger/interval.py
Adding
next_fire_time = next_fire_time.tzinfo.localize(next_fire_time.replace(tzinfo=None))
and it become like this:
def get_next_fire_time(self, previous_fire_time, now):
if previous_fire_time:
next_fire_time = previous_fire_time + self.interval
elif self.start_date > now:
next_fire_time = self.start_date
else:
timediff_seconds = timedelta_seconds(now - self.start_date)
next_interval_num = int(ceil(timediff_seconds / self.interval_length))
next_fire_time = self.start_date + self.interval * next_interval_num
# PATCH MADE
next_fire_time = next_fire_time.tzinfo.localize(next_fire_time.replace(tzinfo=None))
if self.jitter is not None:
next_fire_time = self._apply_jitter(next_fire_time, self.jitter, now)
if not self.end_date or next_fire_time <= self.end_date:
return self.timezone.normalize(next_fire_time)
So we would like to have your expetise in order to know if this patch is good or we made a mistake ?
Issue Analytics
- State:
- Created 4 years ago
- Comments:9 (4 by maintainers)
Top GitHub Comments
The interval trigger is documented to fire on constant intervals. If you want something else, you will need a different kind of trigger. It sounds like the calendar interval trigger is what you want. I will integrate that in a future version of APScheduler, but for now you can find the base code here. It will need some adaptation on your part to work with APScheduler, but the code passes its test suite in its own repository.
Okay, thank you.