dbader / schedule

Python job scheduling for humans.
https://schedule.readthedocs.io/
MIT License
11.77k stars 961 forks source link

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

Closed AnezeR closed 1 year ago

AnezeR commented 1 year ago

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 commented 1 year ago

I think the issue is in this block https://github.com/dbader/schedule/blob/a3c2074dcd8f39168525f0fc2b009bc7119f0796/schedule/__init__.py#L752-L771 It subtracts one day if self.at_time is greater than now(): https://github.com/dbader/schedule/blob/a3c2074dcd8f39168525f0fc2b009bc7119f0796/schedule/__init__.py#L768 But, since self.at_time is not updated in https://github.com/dbader/schedule/blob/a3c2074dcd8f39168525f0fc2b009bc7119f0796/schedule/__init__.py#L752-L759 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 commented 1 year ago

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