Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Negative idle time when using a time-zone different from host machine #582

Closed
AnezeR opened this issue Apr 26, 2023 · 2 comments
Closed

Comments

@AnezeR
Copy link
Contributor

AnezeR commented Apr 26, 2023

local python version: 3.9.16
docker python: python:3.9-slim-buster

schedule==1.2.0
pytz==2023.3

I have this code, which I run inside a docker container

schedule.every().day.at('07:00', 'Europe/Moscow').do(send_practice_notifications)
schedule.every().day.at('20:00', 'Europe/Moscow').do(send_practice_notifications)

while True:
    n = schedule.idle_seconds()
    print(n)
    if n is None:
        break
    elif n < 0:
        time.sleep(1)
        continue
    elif n > 0:
        time.sleep(n)
    schedule.run_pending()

In this case it outputs negative time and would attempt to run send_practice_notifications, which I want to happen only at specified time, and not every time the program starts.

-7848.127428
-7849.128611
-7850.129724
-7851.130872
-7852.132034
-7853.133061

When run natively, however, it outputs a positive expected value and does not run any functions.
30777.206617
I think this is an error related to time-zones because docker container uses UTC time, and running natively puts it in the Europe/Moscow timezone.
Sure enough, changing the code in docker to

###

schedule.every().day.at('07:00').do(send_practice_notifications)
schedule.every().day.at('20:00').do(send_practice_notifications)

###

Makes the output positive and expected
1709.825228

@AnezeR AnezeR changed the title Negative idle time when using time-zones Negative idle time when using a time-zone different from host machine Apr 27, 2023
@AnezeR
Copy link
Contributor Author

AnezeR commented Apr 27, 2023

I think the issue is in this block

if self.at_time_zone is not None:
# Convert next_run from the expected timezone into the local time
# self.next_run is a naive datetime so after conversion remove tzinfo
self.next_run = (
self.at_time_zone.localize(self.next_run)
.astimezone()
.replace(tzinfo=None)
)
# Make sure we run at the specified time *today* (or *this hour*)
# as well. This accounts for when a job takes so long it finished
# in the next period.
if not self.last_run or (self.next_run - self.last_run) > self.period:
now = datetime.datetime.now()
if (
self.unit == "days"
and self.at_time > now.time()
and self.interval == 1
):
self.next_run = self.next_run - datetime.timedelta(days=1)

It subtracts one day if self.at_time is greater than now():
and self.at_time > now.time()

But, since self.at_time is not updated in
if self.at_time_zone is not None:
# Convert next_run from the expected timezone into the local time
# self.next_run is a naive datetime so after conversion remove tzinfo
self.next_run = (
self.at_time_zone.localize(self.next_run)
.astimezone()
.replace(tzinfo=None)
)

It still executes.
E.G.
If the machine uses UTC time and execution time is 20:00 in UTC+3, self.next_run would change to 17:00 UTC, while self.at_time would stay at 20:00.
Now, if the machine time is 19:00 UTC, it should not subtract a day, since it is already 2 hours past execution time, but, it would see, that 19:00 is less than 20:00 and subtract a day from self.next_run

@SijmenHuizenga
Copy link
Collaborator

Thank you so much for investigating and creating a pr! #583 has been merged and released in 1.2.1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants