What I want to do in a python script is sleep a number of seconds until the required time is reached. IE: if runAt setting is 15:20 and current time is 10:20, how can I work out how many seconds to sleep? I'm not sure how to convert 15:20 to a time and current date then deduct the actual time to get the seconds.
8 Answers
Think you can also use the following code:
from datetime import datetime, time
from time import sleep
def act(x):
return x+10
def wait_start(runTime, action):
startTime = time(*(map(int, runTime.split(':'))))
while startTime > datetime.today().time(): # you can add here any additional variable to break loop if necessary
sleep(1)# you can change 1 sec interval to any other
return action
wait_start('15:20', lambda: act(100))

- 22,579
- 24
- 131
- 223

- 27,895
- 4
- 34
- 52
-
Thanks. I really appreciate the use of map and *. These answers really help with my python programming. – Martlark Jul 10 '11 at 01:20
-
`act(100)` calls `act` **immediately**. You probably meant `delay_until(to_utc_time(...), act, 100)` instead. `startTime` should be called `end_time` or `deadline` in this case. – jfs Feb 09 '15 at 15:21
-
@J.F.Sebastian thank you, i have updated my code to call act properly. – Artsiom Rudzenka Feb 10 '15 at 05:38
-
Just curious, why the loop? I was thinking it would make more sense subtract 'now' from 'runTime', wait that long, then return. No loop. – Selah Apr 17 '15 at 20:26
-
1@selah one reason would be if you need to wake up at a very precise time, python `sleep` docs say _"the suspension time may be longer than requested by an arbitrary amount because of the scheduling of other activity in the system"_. looking at the `pause` module from @cmangla's answer they use an interesting variant, combining `sleep` with a loop https://github.com/jgillick/python-pause/blob/master/pause/__init__.py#L53 in order to avoid 'busy waiting' but also try and wake up accurately – Anentropic Dec 11 '15 at 16:09
-
What about doing `sleep((startTime-datetime.today()).total_seconds()/2)`? This will logarithmically reduce the sleeping and be quite precise, unless I've overseen something. – Mads Y Feb 08 '16 at 20:42
If you subtract one datetime object from another you get a timedelta object, which has a seconds property, so you can do:
t1 = datetime.datetime.now()
# other stuff here
t2 = datetime.datetime.now()
delta = t2 - t1
if delta.seconds > WAIT:
# do stuff
else:
# sleep for a bit
As an aside, you might want to use cron for tasks that are supposed to run at specific times.

- 8,781
- 2
- 44
- 57
-
If this was unix I would. But, I'm on windows server 2008 with restricted access to the admin accounts. – Martlark Jul 08 '11 at 02:22
-
local time may be ambiguous. Do not use `.now()` as a timer, use `.utcnow()`, `time.time()`, `time.monotonic()`, etc instead. To understand why, see [Find if 24 hrs have passed between datetimes - Python](http://stackoverflow.com/a/26313848/4279) – jfs Feb 09 '15 at 15:12
You could instead use the pause
package ( https://pypi.python.org/pypi/pause ). Taking an example from their documentation -
import pause, datetime
dt = datetime.datetime(2013, 6, 2, 14, 36, 34, 383752)
pause.until(dt)
-
2[it does not work on Windows](https://github.com/jgillick/python-pause/issues/1). – jfs Feb 09 '15 at 15:09
-
1it is a bad practice to use naive datetime objects that represent local time. Local time may be ambiguous and it is non-trivial to convert past/future dates to UTC (or to POSIX time) due to possible changes to the UTC offset of the local timezone. Use UTC time for calculations and convert to local time only if you need to display it. – jfs Feb 09 '15 at 15:25
-
-
1
-
1As of 1/8/17 it works on windows and the pause package has some other nifty features like pause.minutes(1) or pause.seconds(1) ect... – Mark Omo Jan 09 '17 at 06:55
-
The current version of [`pause`](https://pypi.org/project/pause/), v0.3 Oct 2020, works great with Python 3.10. – wisbucky Dec 28 '21 at 17:54
Using timedelta object is the way to go. Below is the example that worked for me and can easily be adjusted to any other time:
import datetime, time
today = datetime.datetime.now()
sleep = (datetime.datetime(today.year, today.month, today.day, 15, 20, 0) - today).seconds
print('Waiting for ' + str(datetime.timedelta(seconds=sleep)))
time.sleep(sleep)
Take into consideration that if 15:20 has already passed, this substraction will still work and will wait till the next occurrence of 15:20, because in such situations timedelta returns a negative number of days. It's 16:15 as I'm running my code:
print(datetime.datetime(today.year, today.month, today.day, 15, 20, 0) - today)
>>>-1 day, 23:05:00.176033

- 503
- 2
- 6
- 14
Instead of using the function sleep(X), you can also use to a Timer
It depends on what you're planning to do.

- 1,041
- 1
- 8
- 23

- 544
- 8
- 19
Here's a solution that uses the Arrow module:
def wait_until(specified_dt: arrow.Arrow) -> None:
"""Stay in a loop until the specified date and time."""
# Initially check every 10 seconds.
refresh = 10
current_dt = arrow.utcnow()
while current_dt < specified_dt:
# Check every millisecond if close to the specified time.
current_dt = arrow.utcnow()
if (specified_dt - current_dt).seconds < 11:
refresh = .001
time.sleep(refresh)

- 3,200
- 6
- 30
- 38
Here is a solution. This is independent of date because the new date-time "end2" has same date as current date-time and at the same time the date-time format is not changed.
from datetime import datetime #this is the way to import a module named datetime...
import time #this module is used to sleep
import pause
a = (datetime.now()) #a = '2017-07-27 00:10:00.107000' #for example
print 'the time is'
print a
end2 = a.replace(hour = 15, minute = 20, second = 00)
delta = end2 - a
print delta # prints: 5:00:00
print delta.total_seconds() # prints: 114605.0
pause.seconds(delta.total_seconds())

- 1
- 2
Using both arrow and pause:
maintenance = arrow.now()
EndAt = maintenance.replace(hour = 17, minute = 6, second = 0)
print(maintenance,': Maintenance in progress. Pausing until :',EndAt)
pause.until(EndAt.naive)

- 1
- 1