Reputation: 155
I'm tinkering with datetimenow()
and I'm wondering how would you go about sort of "scheduling" an execution of a function when there are 2 dates (now and future dates)?
Basically I want to keep the programming running when the date (and time) is not the same, but when it is, call some function.
What I mean is:
from time import sleep
import time
import datetime
timenow = datetime.datetime.now()
future = datetime.datetime(2018, 8, 19, 15,28)
while timenow != future:
sleep(1.0)
if timenow == future:
'''calling some function'''
Running this code only seems to keep looping although the minutes specified in future
equals the minutes of timenow
.
Upvotes: 0
Views: 55
Reputation: 365995
You have two separate problems here, and you need to fix both.
The first problem is that you never update timenow
in your loop. Whatever time it was when your program started, that's the value of timenow
forever.
To fix that, you need to update it each time through the loop:
while timenow != future:
sleep(1.0)
timenow = datetime.datetime.now()
The second problem is that if now
is, say, 2018-08-19 15:27:59.123456
, that isn't equal to 2018-08-19 15:28:00.000000
. And a second later, 2018-08-19 15:28:00.131313
also isn't equal to 2018-08-19 15:28:00.000000
. There's about a 1 in a million chance that you happen to hit that microsecond exactly when you're only checking once per second.
To fix that, just use <
instead of !=
:
while timenow < future:
sleep(1.0)
timenow = datetime.datetime.now()
Now, 2018-08-19 15:27:59.123456
is less than the time you're waiting for—but 2018-08-19 15:28:00.131313
is not. So, you don't miss it.
While we're at it:
There's no need for that if
statement at all. You're just testing the opposite of the while
condition. But the only way you can get here is if the while
condition is false, so the opposite condition will always be true, so why bother checking it?
Also, if the only thing you're using timenow
for is in that check, you don't even need to stick it in a variable; just call now()
directly.
So:
from time import sleep
import datetime
future = datetime.datetime(2018, 8, 19, 15,28)
while datetime.datetime.now() < future:
sleep(1.0)
'''calling some function'''
Meanwhile, there's really no reason to sleep for a second at a time. Why not just sleep once, until future
? In some versions of Python, sleep
can return early, so you still need a while
loop, but you can still do this:
from time import sleep
import datetime
future = datetime.datetime(2018, 8, 19, 15,28)
while datetime.datetime.now() < future:
sleep((future - datetime.datetime.now()).total_seconds())
'''calling some function'''
Most of the time, this will sleep exactly once—occasionally maybe two or three times—instead of over and over again, so it won't, say, stop your laptop from going into low-power mode.
Also, there's a lot less chance that it'll wake up at, say, 2018-08-19 15:28:00.987654
instead of (very close to) on the second. That may not matter for your use, but if it does matter, waking up on the second is surely the one you want.
Upvotes: 3
Reputation: 317
What you will need to do is specify how precise you want that equality to be. To do this you will specify a range of time that is acceptably considered to be "equal". See this SO post on an example of how to do that. You'll end up with something as straight forward as
if min_future_time < timenow and timenow < max_future_time:
# Do something.
Upvotes: 1