How to make simple alarms on Python - python

I'm trying to make a simple alarm using Python but whatever I try it doesn't seem to work. I've just recently made a timer but an alarm would be a little more useful.
I'm also pretty new to Python so I'm not really aware of all the rules and syntax.
import datetime
import os
stop = False
while stop == False:
rn = str(datetime.datetime.now().time())
print(rn)
if rn == "18:00:00.000000":
stop = True
os.system("start BTS_House_Of_Cards.mp3")
When I run the file, it prints the time but goes completely past the time I want the alarm to go off at.

The technical problem here is that if you call datetime.now() over and over again, you can't always call it fast enough to get all of the possible values. So == should instead be >=. However, this still isn't very good.
A much better way to do this is to use time.sleep() instead of looping.
import datetime
import os
import time
now = datetime.datetime.now()
# Choose 6PM today as the time the alarm fires.
# This won't work well if it's after 6PM, though.
alarm_time = datetime.datetime.combine(now.date(), datetime.time(18, 0, 0))
# Think of time.sleep() as having the operating system set an alarm for you,
# and waking you up when the alarm fires.
time.sleep((alarm_time - now).total_seconds())
os.system("start BTS_House_Of_Cards.mp3")

Just replace:
if rn == "18:00:00.000000":
With:
if rn >= "18:00:00.000000":

Use the following to round to the next minute (or adapt for seconds etc)
import datetime as dt
rn = dt.datetime.now()
# round to the next full minute
rn -= dt.timedelta( seconds = rn.second, microseconds = rn.microsecond)
rn += dt.timedelta(minutes=1)
To adapt for seconds remove seconds = rn.second and then change minutes in the next line to seconds
How it works
Removes the seconds and microseconds from the current time and then adds on 1 minute therefore rounding it to the next whole minute.

I Had the same issue for my IoT based project here is a simple tryout code written by me in python to invoke certain function at a given time here goes code
import datetime
from time import sleep
tempdatetimeobj = datetime.datetime.now()
try:
while True:
print("#################")
now = str(datetime.datetime.now().time()) # convert a time in string
print("Time is:- " + str(now))
timestring = now[:5]
# Slice the time for eg time is 17:02:52:23656 it will
slice it to 17:02 only
print("SLICE MAGIC :- "+ timestring)
if timestring == '17:26' : # after slicing operation only you can compare time
print('Triggered')
elif timestring == '17:30' :
print('again triggered')
else :
print('-_-')
sleep(60)
except KeyboardInterrupt:
print('unHandled Exception Occured')

How about using this technique? It's simple and works smoothly.
import datetime
import winsound # exclusively for windows only,
# if you are on any other system you can use 'playsound' or 'simpleaudio' module.
alarm_hour = int(input("Set hour: "))
alarm_minutes = int(input("Set minutes: "))
am_pm = input("am or pm? ")
print(f"Waiting for time: {alarm_hour}:{alarm_minutes} {am_pm}")
# time conversion
# because datetime module returns time in military form i.e. 24 hrs format
if am_pm == 'pm': # to convert pm to military time
alarm_hour += 12
elif alarm_hour == 12 and am_pm == 'am': # to convert 12am to military time
alarm_hour -= 12
else:
pass
while True: # infinite loop starts to make the program running until time matches alarm time
# ringing alarm + execution condition for alarm
if alarm_hour == datetime.datetime.now().hour and alarm_minutes == datetime.datetime.now().minute:
print("\nIt's the time!")
winsound.Beep(1000, 1000)
break
Obviously you can do more with the program by doing data validation for the inputs. Using the 'simpleaudio' module, you can add some interesting functions. And the number of other things you can do to increase the efficiency of the program.

There is another alternative that hasn't been mentioned which might work for you, depending on what your goals are: signal.alarm.
signal.alarm is similar to the alarm(3) library call on Unix where setting a time will result in a SIGALRM signal being sent to a parent process in the future to denote when an asynchronous action should be taken (the default with an uncaught signal is a dead process).
Example:
$ python
Python 2.7.16 (default, Mar 20 2019, 12:15:19)
[GCC 7.4.0] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import signal
>>> signal.alarm(1)
0
>>> Alarm clock
The key points when using signal.alarm(..) is the following:
- The solution is best for a single process application; it should not be used if you need to have per-thread or multi-process timers.
- You will need to setup a signal handler for signal.SIGALRM.
The key point when handling signals is:
- Handle asynchronous
This approach is fairly basic and very OS-centric, but it's a simple, clean approach for doing things. There are other alternatives that could potentially be employed using the kqueue/select module (poll, etc, come to mind), other calls within the signal module, concurrent.futures/multiprocessing (there's a timeout option on some APIs).
Just one potential tool to use in your toolbox of timers.
A complete solution using signal.alarm can be found here (I adjusted the end time so I wouldn't have to wait forever for it to complete).
$ date; python3 play_house_of_cards.py ; date
Wed 10 Jul 2019 04:54:16 PM PDT
would have run `start BTS_House_Of_Cards.mp3`
Wed 10 Jul 2019 04:55:00 PM PDT
$

I would suggest using while loop with True like this:
loop = True
while loop:
rn = str(datetime.datetime.now().time())
if rn >= "18:00:00.00000":
loop = False

this alarm has almost every feature so it might be helpful for you if you want to make a perfect alarm
from pygame import mixer
from os import path
from sys import path as p
from time import sleep,strftime
try:
while True: #it will give you another chance if you fill in letters or symbols
hour=input('hour=')
if hour.isdigit():# if input is digit
if len(hour)==1:#if the input has one digit
hour2='0'+hour #it will add 0 in front of the input because time module gives 01 not 1 so it will convert 1(input) into 01
else:#if the input has two digit
hour2=hour
else:
print('press any key to try again')
min=input('Minute=')
if min.isdigit():
if len(min)==1:
min2='0'+min
else:
min2=min
ap=input('am/pm=')
if ap=='am' or 'pm' or 'AM' or 'PM' or 'Am' or 'Pm' or 'aM' or 'pM':
apm=ap.upper()
break
while True:
x=strftime('%I')
y=strftime('%M')
z=strftime('%p')
if x==hour2 and y==min2 and z==apm :
print("Type 'h' for help")
while True:
mixer.init()
you don't have to write the location of a file(c:\music\alone.mp3) just save the file in the same folder as the .py file
music_=(path.join(p[0],'alone.mp3' ))
mixer.music.load(music_)
mixer.music.play()
stop=input('X=')
if stop=='s' : #it will snooze the alarm for 5 min
time_=strftime('%I')
time2=strftime('%M')
time3=strftime('%S %p')
print('Alarm will sound at ',time_,':',int(time2)+5,':',time3)
mixer.music.stop()
sleep(300 )
elif stop=='h':
print("1.Type 's' for snooze alarm / 2.Press any key except 's' and 'h' for turn off the alarm" )
elif stop!='s' or 'h': #it will stop alarm
mixer.music.stop()
break
break
except:
print('Invalid Input: Please try again')

Related

How would I be able to make python always check for the time?

import time
import tkinter
import win10toast
toaster = win10toast.ToastNotifier()
t = time.localtime()
current_time = time.strftime("%H:%M", t)
workout_times = ['']
workout_time = str(input('What time do you want your reminder to come(Format is Hour:Minute): '))
workout_times.append(workout_time)
while current_time == current_time:
if current_time == workout_time:
print(2)
toaster.show_toast('Reminder', 'DO IT`', duration=10)
break
How would I be able to make python always check for the time? Like for you to input a time, for python to constantly check for the time and when it comes for it to run the if stament.
I agree with the comments above, yet I do think it is worthy to answer the question and show a way for comparing between the current time and a target time (if you do decide to run such a python code, I guess you’d want to run this in the background by calling your python script with pythonw.exe via command line or script). So below is one simple option for monitoring the time and executing a task:
from datetime import datetime
from time import sleep
sleep_period = 60
target_time = datetime(2020, 8, 10, 10, 33) # you can construct the numbers inside from user input
while True:
delta = datetime.today()-target_time
if delta.days == 0 and delta.seconds <= sleep_period:
print('It is time to execute a function')
break # or ask for another input…
sleep(sleep_period)

Problems with python alarm at specified hours

I'm trying to make a "alarm" for my classes and it does that when a certain hour comes it does something (in this case it just prints, and i will change that when the code works) and it repeats until next alarm.The problem here is that when i run the code 1 min before it prints it's time , and then it reaches the alarm time and it still prints the same and not not yet.
I want the code to keep running after the if statements. Here's the code:
from datetime import datetime
import time
now = datetime.now()
current_time = now.strftime("%H:%M")
today = now.strftime("%A")
cn = "22:14"
ing ="21:23"
day = {0:"Monday", 1:"Tuesday", 2:"Wednesday"
, 3:"Thursday", 4:"Friday", 5:"Saturday", 6:"Sunday"}
def mday():
if (today == day[0]) and (current_time == cn):
print("its time")
time.sleep(1)
mday()
else:
print("not yet")
time.sleep(1)
mday()
mday()
The main problem with your code (why it does not work at all), is that you do not update the values of the today and current_time variables. That you sleep for one second in each call to mday() does not affect these variables. You need to update them right at the entry to mday.
The second problem is that you have infinite recursion here. Infinite loops run forever, which is what you want, I guess. Infinite recursion, on the other hand, simply uses up the stack, and crashes you application. You would need to convert the recursive function mday to one with an infinite loop. To do that, place all the if statement from inside mday inside a forever loop: (while True:), and
also remove the two recursive calls from the end of the branches. You can also take the sleep calls out of the if - remove one of them, and place the other after the the content of the else block:
from datetime import datetime
import time
cn = "22:14"
ing ="21:23"
day = {
0:"Monday",
1:"Tuesday",
2:"Wednesday",
3:"Thursday",
4:"Friday",
5:"Saturday",
6:"Sunday"
}
def mday():
while True:
# Update current time values
now = datetime.now()
current_time = now.strftime("%H:%M")
today = now.strftime("%A")
# Print alarm/no-alarm message
if (today == day[0]) and (current_time == cn):
print("its time")
else:
print("not yet")
time.sleep(1)
mday()
There are many ways this code can be optimized, but the above will produce roughly the result you want.

Scheduling a Python program to sleep within a given time period

while True:
now = datetime.datetime.now();
if now.hour >= 22 and now.hour < 3:
print "sleep"
sleep_at = datetime.datetime.combine(datetime.date.today(),datetime.time(3))
sleep_til = (sleep_at - now).seconds
print sleep_til
time.sleep(sleep_til)
print "wake"
else:
print "break"
break
This code should make my entire program to go to sleep at 10 PM and wake up at 3 AM. MY question is.. will this work? I tried running it.. but I cannot change my system/computer Time.. so I cannot check.
Reason why I am posting this question is because my coding is using datetime.date.tday and datetime.datetime which is calling current date..
Once again.. I want my program to run before 10PM and sleep between 10PM to 3AM and rerun after 3AM..
Can someone check if this is the right way to do it?
Consider (extra-verbose for clarity):
import time, datetime
# Create time bounds -- program should run between RUN_LB and RUN_UB
RUN_LB = datetime.time(hour=22) # 10pm
RUN_UB = datetime.time(hour=3) # 3am
# Helper function to determine whether we should be currently running
def should_run():
# Get the current time
ct = datetime.datetime.now().time()
# Compare current time to run bounds
lbok = RUN_LB <= ct
ubok = RUN_UB >= ct
# If the bounds wrap the 24-hour day, use a different check logic
if RUN_LB > RUN_UB:
return lbok or ubok
else:
return lbok and ubok
# Helper function to determine how far from now RUN_LB is
def get_wait_secs():
# Get the current datetime
cd = datetime.datetime.now()
# Create a datetime with *today's* RUN_LB
ld = datetime.datetime.combine(datetime.date.today(), RUN_LB)
# Create a timedelta for the time until *today's* RUN_LB
td = ld - cd
# Ignore td days (may be negative), return td.seconds (always positive)
return td.seconds
while True:
if should_run():
print("--do something--")
else:
wait_secs = get_wait_secs()
print("Sleeping for %d seconds..." % wait_secs)
time.sleep(wait_secs)
But I do agree that sleeping is not the best way to delay your program starting. You may look into the task scheduler on Windows or cron on Linux.

How to execute program at specific times

I have a program that I need to execute at certain intervals. For instance, I may want it to execute it every five minutes. I have several coordinators that communicate with several end nodes devices. The code below is on the coordinators. I need it so that if the interval is set to 5 then it runs and records information at for example: 9:05, 9:10, 9:15, 9:20, 9:25 and etc. The code I have so far is as follows:
if __name__ == '__main__':
while True:
try:
r = json.read(rqst_command())
interval = r.get('intvl')
collect_time = r.get('c_time')
command = r.get('cmd')
send_stats(cmd_nodes(command, collect_time))
time.sleep(interval)
except Exception, e:
print e
print "**Top Level Exception"
pass
The problem is that if I set the interval to 5 minutes it does not record exactly every 5 minutes. The execution time seems to slowly increase that time. So for example the above code may record as 9:05:09, 9:10:19, 9:15:29, 9:20:41, 9:25:50. The time it takes for the program to run depends on how fast the nodes communicate back.
Does anybody have any ideas on how I can change my code so that the program will execute exactly every 5 minutes?
EDIT/UPDATE
I think I have figured out a way to handle my problem. I grab the current datetime and then check to see if it is on the 5 minute mark. If it is then record the datetime and send it to the send_stats function. That way the datetime will always be exactly what I want it to be. If it is not on the 5 minute mark then sleep for awhile and then check again. I have the code mostly completed. However, I am getting the following error when I run the program: 'builtin_function_or_method' object has no attribute 'year'.
What am I doing incorrectly?
Here is my new code:
import os
import json
import datetime
from datetime import datetime
import urllib2
from urllib import urlencode
from socket import *
import time
import zigbee
import select
if __name__ == '__main__':
while True:
try:
r = json.read(rqst_command())
interval = r.get('intvl')
collect_time = r.get('c_time')
command = r.get('cmd')
tempTest = True
while tempTest == True:
start_time = datetime.now
compare_time = datetime(start_time.year, start_time.month, start_time.day, start_time.hour, 0, 0)
difff = int((start_time - compare_time).total_seconds() / 60)
if((difff % interval) == 0):
c_t = datetime(start_time.year, start_time.month, start_time.day, start_time.hour, start_time.minute, 0)
send_stats(cmd_nodes(command, collect_time), c_t)
tempTest = False
else:
time.sleep(30)
except Exception, e:
print e
print "**Top Level Exception"
pass
The below code is what ended up solving my problem. Now no matter what the interval is, it will always use the datetime starting at the beginning of each hour and incrementing by the interval. So, if the interval is 5 then the datetime shows up as for instance: 9:00:00, 9:05:00, 9:10:00, 9:15:00, 9:20:00, 9:25:00, and etc. If the interval is 3 then the datetime shows up as for instance: 5:00:00, 5:03:00, 5:06:00, 5:09:00, 5:12:00, 5:15:00, and etc. The coordinator gets the data from the end nodes and then sends the data to a remote server along with the datetime.
if __name__ == '__main__':
last_minute = -1
while True:
try:
r = json.read(rqst_command())
print r
command = r.get('cmd')
interval = r.get('intvl')
collect_time = r.get('c_time')
tempTest = True
while tempTest == True:
start_time = datetime.now()
s_minute = start_time.minute
if(((s_minute % interval) == 0) and (s_minute != last_minute)):
tempTest = False
c_t = datetime(start_time.year, start_time.month, start_time.day, start_time.hour, start_time.minute, 0)
last_minute = c_t.minute
send_stats(cmd_nodes(command, collect_time), c_t)
time.sleep(1)
else:
time.sleep(1)
except Exception, e:
print e
print "**Top Level Exception"
pass
As others have pointed out, there already are ready-to-use job/task schedulers like cron. You can just use them. But you could also implement your own simple solution in Python, which would be fine. You just have to do it the right way. The fundamental problem in your approach is that you sleep for a certain interval between actions and do not regularly check the system time. In your method, the duration of the action is the error of your time measurement. And this error sums up with each action. You need to have a time reference that is free of this error, which is the system time.
Implementation example:
Consider, for instance, one second precision is good enough for you. Then check the system time each second within a loop. This you can safely realize with a time.sleep(1). If the system time is e.g. 5 minutes later than the last_action_execution_time (which you have obviously stored somewhere), store the current time as last_action_execution_time and execute the action. As long as this action for sure lasts less then 5 minutes, the next execution will happen at last_action_execution_time + 5 min with only a very small error. Most importantly, this error does not grow during runtime with the number of executions.
For a rock-solid Python-based solution you should also look at http://docs.python.org/library/sched.html.
how about:
while true:
try:
start=time.time() # save the beginning time before execution starts
r = json.read(rqst_command())
interval = r.get('intvl')
collect_time = r.get('c_time')
command = r.get('cmd')
start_time = datetime.now()
send_stats(cmd_nodes(command, collect_time))
end_time = datetime.now()
sleepy_time = interval - (end_time - start_time)
while time.time() <= start + sleepy_time*60: #To wait until interval has ended note: I'm assuming sleepy_time is in minutes.
pass
except Exception, e:
print e
print "**Top Level Exception"
pass
If you use Linux, you probably want to set up a cronjob which runs your script in certain intervals.
There are two ways to do this.
The first and best would be to use your OS's task scheduler (Task Scheduler in Windows, cron in Linux). The developers of these tools probably anticipated more issues than you can imagine and code you don't have to do yourself is time and probably bugs saved.
Otherwise, you need to take into account the execution time of your script. The simplest way to do that is instead of sleeping for your interval (which as you saw slowly slides forward), you would compute when is the next time you should execute based on when you last woke up and after execution, sleep only for the interval between now and then.
I'm assuming you want to do this in Python and not rely on any other systems.
You just need to account for when your process starts and when it ends and set your interval accordingly. The code will look something like this.
if __name__ == '__main__':
while True:
try:
r = json.read(rqst_command())
interval = r.get('intvl')
collect_time = r.get('c_time')
command = r.get('cmd')
start_time = datetime.now()
send_stats(cmd_nodes(command, collect_time))
end_time = datetime.now()
sleepy_time = interval - (end_time - start_time)
time.sleep(sleepy_time)
except Exception, e:
print e
print "**Top Level Exception"
pass

In Python, how can I put a thread to sleep until a specific time?

I know that I can cause a thread to sleep for a specific amount of time with:
time.sleep(NUM)
How can I make a thread sleep until 2AM? Do I have to do math to determine the number of seconds until 2AM? Or is there some library function?
( Yes, I know about cron and equivalent systems in Windows, but I want to sleep my thread in python proper and not rely on external stimulus or process signals.)
Here's a half-ass solution that doesn't account for clock jitter or adjustment of the clock. See comments for ways to get rid of that.
import time
import datetime
# if for some reason this script is still running
# after a year, we'll stop after 365 days
for i in xrange(0,365):
# sleep until 2AM
t = datetime.datetime.today()
future = datetime.datetime(t.year,t.month,t.day,2,0)
if t.hour >= 2:
future += datetime.timedelta(days=1)
time.sleep((future-t).total_seconds())
# do 2AM stuff
You can use the pause package, and specifically the pause.until function, for this:
import pause
from datetime import datetime
pause.until(datetime(2015, 8, 12, 2))
Slightly more generalized solution (based off of Ross Rogers') in case you'd like to add minutes as well.
def sleepUntil(self, hour, minute):
t = datetime.datetime.today()
future = datetime.datetime(t.year, t.month, t.day, hour, minute)
if t.timestamp() > future.timestamp():
future += datetime.timedelta(days=1)
time.sleep((future-t).total_seconds())
Another approach, using sleep, decreasing the timeout logarithmically.
def wait_until(end_datetime):
while True:
diff = (end_datetime - datetime.now()).total_seconds()
if diff < 0: return # In case end_datetime was in past to begin with
time.sleep(diff/2)
if diff <= 0.1: return
Building on the answer of #MZA and the comment of #Mads Y
One possible approach is to sleep for an hour. Every hour, check if the time is in the middle of the night. If so, proceed with your operation. If not, sleep for another hour and continue.
If the user were to change their clock in the middle of the day, this approach would reflect that change. While it requires slightly more resources, it should be negligible.
I tried the "pause" pacakage. It does not work for Python 3.x. From the pause package I extracted the code required to wait until a specific datetime and made the following def.
def wait_until(execute_it_now):
while True:
diff = (execute_it_now - datetime.now()).total_seconds()
if diff <= 0:
return
elif diff <= 0.1:
time.sleep(0.001)
elif diff <= 0.5:
time.sleep(0.01)
elif diff <= 1.5:
time.sleep(0.1)
else:
time.sleep(1)
adapt this:
from datetime import datetime, timedelta
from time import sleep
now = datetime.utcnow
to = (now() + timedelta(days = 1)).replace(hour=1, minute=0, second=0)
sleep((to-now()).seconds)
Slightly beside the point of the original question:
Even if you don't want to muck around with crontabs, if you can schedule python scripts to those hosts, you might be interested to schedule anacron tasks? anacron's major differentiator to cron is that it does not rely the computer to run continuously. Depending on system configuration you may need admin rights even for such user-scheduled tasks.
A similar, more modern tool is upstart provided by the Ubuntu folks: http://upstart.ubuntu.com/
This does not yet even have the required features. But scheduling jobs and replacing anacron is a planned feature. It has quite some traction due to its usage as Ubuntu default initd replacement. (I am not affiliated with the project)
Of course, with the already provided answer, you can code the same functionality into your python script and it might suit you better in your case.
Still, for others, anacron or similar existing systems might be a better solution. anacron is preinstalled on many current linux distributions (there are portability issues for windows users).
Wikipedia provides a pointer page: https://en.wikipedia.org/wiki/Anacron
If you do go for a python version I'd look at the asynchronous aspect, and ensure the script works even if the time is changed (daylight savings, etc) as others have commented already. Instead of waiting til a pre-calculated future, I'd always at maximum wait one hour, then re-check the time. The compute cycles invested should be negligible even on mobile, embedded systems.
Asynchronous version of Omrii's solution
import datetime
import asyncio
async def sleep_until(hour: int, minute: int, second: int):
"""Asynchronous wait until specific hour, minute and second
Args:
hour (int): Hour
minute (int): Minute
second (int): Second
"""
t = datetime.datetime.today()
future = datetime.datetime(t.year, t.month, t.day, hour, minute, second)
if t.timestamp() > future.timestamp():
future += datetime.timedelta(days=1)
await asyncio.sleep((future - t).total_seconds())
I know is way late for this, but I wanted to post an answer (inspired on the marked answer) considering systems that might have - incorrect - desired timezone + include how to do this threaded for people wondering how.
It looks big because I'm commenting every step to explain the logic.
import pytz #timezone lib
import datetime
import time
from threading import Thread
# using this as I am, check list of timezone strings at:
## https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
TIMEZONE = pytz.timezone("America/Sao_Paulo")
# function to return desired seconds, even if it's the next day
## check the bkp_time variable (I use this for a bkp thread)
## to edit what time you want to execute your thread
def get_waiting_time_till_two(TIMEZONE):
# get current time and date as our timezone
## later we remove the timezone info just to be sure no errors
now = datetime.datetime.now(tz=TIMEZONE).replace(tzinfo=None)
curr_time = now.time()
curr_date = now.date()
# Make 23h30 string into datetime, adding the same date as current time above
bkp_time = datetime.datetime.strptime("02:00:00","%H:%M:%S").time()
bkp_datetime = datetime.datetime.combine(curr_date, bkp_time)
# extract the difference from both dates and a day in seconds
bkp_minus_curr_seconds = (bkp_datetime - now).total_seconds()
a_day_in_seconds = 60 * 60 * 24
# if the difference is a negative value, we will subtract (- with + = -)
# it from a day in seconds, otherwise it's just the difference
# this means that if the time is the next day, it will adjust accordingly
wait_time = a_day_in_seconds + bkp_minus_curr_seconds if bkp_minus_curr_seconds < 0 else bkp_minus_curr_seconds
return wait_time
# Here will be the function we will call at threading
def function_we_will_thread():
# this will make it infinite during the threading
while True:
seconds = get_waiting_time_till_two(TIMEZONE)
time.sleep(seconds)
# Do your routine
# Now this is the part where it will be threading
thread_auto_update = Thread(target=function_we_will_thread)
thread_auto_update.start()
It takes only one of the very basic libraries.
import time
sleep_until = 'Mon Dec 25 06:00:00 2020' # String format might be locale dependent.
print("Sleeping until {}...".format(sleep_until))
time.sleep(time.mktime(time.strptime(sleep_until)) - time.time())
time.strptime() parses the time from string -> struct_time tuple. The string can be in different format, if you give strptime() parse-format string as a second argument. E.g.
time.strptime("12/25/2020 02:00AM", "%m/%d/%Y %I:%M%p")
time.mktime() turns the struct_time -> epoch time in seconds.
time.time() gives current epoch time in seconds.
Substract the latter from the former and you get the wanted sleep time in seconds.
sleep() the amount.
If you just want to sleep until whatever happens to be the next 2AM, (might be today or tomorrow), you need an if-statement to check if the time has already passed today. And if it has, set the wake up for the next day instead.
import time
sleep_until = "02:00AM" # Sets the time to sleep until.
sleep_until = time.strftime("%m/%d/%Y " + sleep_until, time.localtime()) # Adds todays date to the string sleep_until.
now_epoch = time.time() #Current time in seconds from the epoch time.
alarm_epoch = time.mktime(time.strptime(sleep_until, "%m/%d/%Y %I:%M%p")) # Sleep_until time in seconds from the epoch time.
if now_epoch > alarm_epoch: #If we are already past the alarm time today.
alarm_epoch = alarm_epoch + 86400 # Adds a day worth of seconds to the alarm_epoch, hence setting it to next day instead.
time.sleep(alarm_epoch - now_epoch) # Sleeps until the next time the time is the set time, whether it's today or tomorrow.
What about this handy and simple solution?
from datetime import datetime
import time
pause_until = datetime.fromisoformat('2023-02-11T00:02:00') # or whatever timestamp you gonna need
time.sleep((pause_until - datetime.now()).total_seconds())
from datetime import datetime
import time, operator
time.sleep([i[0]*3600 + i[1]*60 for i in [[H, M]]][0] - [i[0]*3600 + i[1]*60 for i in [map(int, datetime.now().strftime("%H:%M").split(':'))]][0])
Instead of using the wait() function, you can use a while-loop checking if the specified date has been reached yet:
if datetime.datetime.utcnow() > next_friday_10am:
# run thread or whatever action
next_friday_10am = next_friday_10am()
time.sleep(30)
def next_friday_10am():
for i in range(7):
for j in range(24):
for k in range(60):
if (datetime.datetime.utcnow() + datetime.timedelta(days=i)).weekday() == 4:
if (datetime.datetime.utcnow() + datetime.timedelta(days=i, hours=j)).hour == 8:
if (datetime.datetime.utcnow() + datetime.timedelta(days=i, hours=j, minutes=k)).minute == 0:
return datetime.datetime.utcnow() + datetime.timedelta(days=i, hours=j, minutes=k)
Still has the time-checking thread check the condition every after 30 seconds so there is more computing required than in waiting, but it's a way to make it work.

Categories

Resources