Closed bellt closed 1 year ago
Resolved with https://github.com/dbader/schedule/pull/583 and released in 1.2.1. I am also adding a test to cover your specific case in #602. Cheers!
Hi There, From my testing, it looks like 1.2.1 has fixed this problem for the example given. However, if I go the other way and fastforward to one week before daylight saving time ends next year, I encounter the problem again. Here is some code which demonstrates this:
import schedule
import datetime
import time
import os
# POSIX TZ string format
TZ_AUCKLAND = "NZST-12NZDT-13,M10.1.0/02:00:00,M3.3.0/03:00:00"
def job():
return True
class mock_datetime:
"""
Monkey-patch datetime for predictable results
"""
def __init__(self, year, month, day, hour, minute, second=0, zone=None):
self.year = year
self.month = month
self.day = day
self.hour = hour
self.minute = minute
self.second = second
self.zone = zone
self.original_datetime = None
self.original_zone = None
def __enter__(self):
class MockDate(datetime.datetime):
@classmethod
def today(cls):
return cls(self.year, self.month, self.day)
@classmethod
def now(cls):
return cls(
self.year,
self.month,
self.day,
self.hour,
self.minute,
self.second,
)
self.original_datetime = datetime.datetime
datetime.datetime = MockDate
self.original_zone = os.environ.get("TZ")
if self.zone:
os.environ["TZ"] = self.zone
time.tzset()
return MockDate(
self.year, self.month, self.day, self.hour, self.minute, self.second
)
def __exit__(self, *args, **kwargs):
datetime.datetime = self.original_datetime
if self.original_zone:
os.environ["TZ"] = self.original_zone
time.tzset()
with mock_datetime(2024, 4, 1, 10, 00, 0, TZ_AUCKLAND):
# We've set the date to 10:00 on Monday 1 April NZDT (which is 21:00 on Sunday 31 March UTC)
# This is the week before daylight saving ends
# Testing correct application of daylight saving
schedule.clear()
next = schedule.every().sunday.at("23:00", "UTC").do(job).next_run
print(
f"Current local time: {datetime.datetime.now()}\n"
f"Next run time: {schedule.jobs[0].next_run} (expected: 2024-04-01 12:00:00)\n"
f"Idle time: {round(schedule.idle_seconds() / 3600)} hours (expected: 2 hours)\n"
)
with mock_datetime(2024, 4, 8, 10, 00, 0, TZ_AUCKLAND):
# We've set the date to 10:00 on Monday 8 April NZST (which is 22:00 on Sunday 7 April UTC)
# This is the week after daylight saving ends
# Testing correct application of daylight saving (or lack of, at this date)
schedule.clear()
next = schedule.every().sunday.at("23:00", "UTC").do(job).next_run
print(
f"Current local time: {datetime.datetime.now()}\n"
f"Next run time: {schedule.jobs[0].next_run} (expected: 2023-04-08 11:00:00)\n"
f"Idle time: {round(schedule.idle_seconds() / 3600)} hours (expected: 1 hours)"
)
The output from this is:
Current local time: 2024-04-01 10:00:00
Next run time: 2024-04-01 11:00:00 (expected: 2024-04-01 12:00:00)
Idle time: 1 hours (expected: 2 hours)
Current local time: 2024-04-08 10:00:00
Next run time: 2024-04-08 11:00:00 (expected: 2023-04-08 11:00:00)
Idle time: 1 hours (expected: 1 hours)
Which as you can see doesn't have the expected next run time or idle time for the first example, which is one week before daylight saving ends.
I have a job I want to schedule every day at a particular time UTC.
Running at 10:59 local time (which is Pacific/Auckland - currently UTC+12) I get the following output:
This shows the bug highlighted in issue #579 with it skipping the closest 00:00UTC.
If I change the schedule to
schedule.every().monday.at("00:00", "Etc/UTC").do(job)
Then I get the following output
As you can see, it is now scheduling the job for 13:00 local time. However it should be 12:00 local time because we are currently UTC+12. This behaviour started yesterday (Sunday). Prior to that it would schedule the job at the correct time. So it looks like somewhere daylight saving time is being incorrectly applied a week early (my local timezone shifts to daylight saving [UTC+13] next Sunday). But this is only happening with schedule.every().weekday and not schedule.every().day