datetime module not matching int comparison to int - python

I'm currently making an Alarm Clock as a tool to further learn python3 and I have come across a problem.
def clockCheck():
#get the hour and time from setAlarm
splitTime = re.compile(r'(\d+?)(:)(\d+)')
timeRe = splitTime.search(setAlarm())
alarmHour = timeRe.group(1)
alarmMinute = timeRe.group(3)
#get the live time
now = datetime.datetime.now()
currentHour = now.hour
currentMinute = now.minute
currentSecond = now.second
print(currentHour)
print(alarmHour)
while True:
if currentHour != alarmHour:
print("check1")
time.sleep(60-currentSecond) #if this isn't done, the alarm could be off by a couple seconds. Line's up things
time.sleep((60*60) - (60*currentMinute)) #this sleeps the program until the next hour is hit and reruns a check
elif currentMinute != alarmMinute:
print("check2")
time.sleep(60-currentSecond) #sleep until the next minute and rerun the check
#play sound
#break out of program, it's done
In this code snippet, when currentHour is compared to alarmHour (the first if statement), even when those two variables are the same, the code executes the if statement in which they do not equal each other.
In other words, if currentHour = 1 and alarmHour = 1, the code will execute as if currentHour != alarmHour and will run that if statements code.
Obviously that doesn't make sense and I don't know why that is happening when clearly 1==1. I have posted the full code, feel free to play with it. All these modules are built into python3.6
Here is my full code
'''
alarmclock.
ask user for what time to blare off
compare current time to set alarm time
if they do not equal the same then sleep the program for x time and ` rerun the check where it checks if current time is equal alarm time yet. loop until currenttime equals alarm time. then play soun`d
'''
import time
import datetime
import re
def setAlarm():
print("Hello, what time would you like the alarm to sound? Please input in this format\ne.g. 7:45pm\n")
time = input("Time: ")
splitTime = re.compile(r'(\d+?)(:)(\d+?)(pm|am)') #split up time inputted for manipulation
timeRe = splitTime.search(time)
hour = int(timeRe.group(1))
minutes = int(timeRe.group(3))
dayOfTime = timeRe.group(4).lower() #set pm or am to lowercase for ease
#errorChecking for proper time format
if hour > 12 or hour < 1:
print("Please input your time properly, in 12 hour time")
setAlarm()
if minutes > 59 or minutes < 0:
print("Please input your time properly")
setAlarm()
#if time of day is pm, then reassign all values from 1pm - 11:59pm as 13, 14, 15, etc 24 hour bullshit.
if dayOfTime == "pm" and hour != 12:
convertedHour = hour + 12
else:
convertedHour = hour
if dayOfTime == "am" and hour == 12:
convertedHour = 24
finalTime = str(convertedHour) + ":" + str(minutes)
print(finalTime)
return finalTime
def clockCheck():
#get the hour and time from setAlarm
splitTime = re.compile(r'(\d+?)(:)(\d+)')
timeRe = splitTime.search(setAlarm())
alarmHour = timeRe.group(1)
alarmMinute = timeRe.group(3)
#get the live time
now = datetime.datetime.now()
currentHour = now.hour
currentMinute = now.minute
currentSecond = now.second
print(currentHour)
print(alarmHour)
while True:
if currentHour != alarmHour:
print("check1")
time.sleep(60-currentSecond) #if this isn't done, the alarm could be off by a couple seconds. Line's up things
time.sleep((60*60) - (60*currentMinute)) #this sleeps the program until the next hour is hit and reruns a check
elif currentMinute != alarmMinute:
print("check2")
time.sleep(60-currentSecond) #sleep until the next minute and rerun the check
#play sound
#break out of program, it's done
def main():
clockCheck()
main()

Related

How to make program sleep until next day

I need my code to stop and wait until the next day. The time does not matter, I just need it to continue when the date changes.
currentDate = datetime.datetime.now()
future = datetime.datetime(currentDate.year, currentDate.month,
(currentDate.day + 1))
time.sleep((future-currentDate).total_seconds())
The code pauses but does not continue after
Two options here with comments.
First do imports
import datetime
import time
one uses a while loop - probably not a good solution but highlights one way to wait for a condition to be met.
def loop_until_tomorrow():
""" Will use a while loop to iterate until tomorrow """
#get current date
currentDate = datetime.datetime.now().date()
# loop attempts
times = 0
# this will loop infiniatly if condition is never met
while True:
# increment by one each iteration
times += 1
#get date now
now = datetime.datetime.now().date()
if currentDate != now:
# return when condition met
print("\nDay has changed")
return
else:
# print attempts and sleep here to avoid program hanging
print(f"Attempt: {times}".ljust(13) + " - Not tomorrow yet!", end="\r")
time.sleep(5)
the other - sleeps for the amount of seconds from now till tomorrow
def sleep_until_tomorrow():
"""wait till tomorrow using time.sleep"""
#get date now
now = datetime.datetime.now()
#get tomorrows date
tomorrow_date = now.date() + datetime.timedelta(days=1)
#set to datetime
tomorrow_datetime = datetime.datetime(year=tomorrow_date.year, month=tomorrow_date.month, day=tomorrow_date.day, hour=0, minute=0, second=0)
#get seconds
seconds_til_tomorrow = (tomorrow_datetime-now).total_seconds()
#sleep
time.sleep(seconds_til_tomorrow)
You can use schedule for that purpose, which will give you the flexibility to refactore the code when needed without having to write a chunck of code.
from schedule import every, repeat, run_pending
import time
#just to give you the idea on how to implement the module.
#repeat(every().day.at("7:15"))
def remind_me_its_a_new_day():
print("Hey there it's a new day! ")
while True:
run_pending()
time.sleep(1)

User input to stop while loop

I'm currently making a stopwatch function, where the user has to input 1 to start and 2 to stop the stopwatch. I'm wondering how to implement the stop function when the while loop is going on as whatever I tried didn't work.
This is the stopwatch code I'm working on:
second = 0
minute = 0
hour = 0
millisecond = 0
start = input("Press 1 to start and 2 to stop: ")
while True:
if start == "2":
break
else:
print("%02d : %02d : %02d "%(hour, minute, second,))
time.sleep(1)
second += 1
if second == 60:
minute += 1
second -= 60
if minute == 60:
hour += 1
minute -= 60
input is blocking until the user types something (and hit enters).
So if you put it in your while loop, the user will get asked repeatedly if he wants to stop, each time pausing the clock, it is not what is expected.
But if you put the input outside the loop (it is strange that you do that), then the user is never asked to type something until the loop ends (which is never).
It means that in your case, input is not a solution.
There is a very similar question which has an accepted answer (slightly adapted to your case) :
try:
while True:
print("%02d : %02d : %02d "%(hour, minute, second,))
...
except KeyboardInterrupt:
# here the loop has definitely stopped
...
which works with Ctrl+C, being a standard way to signal the program to stop something.
If you want to use something other than Ctrl+C, there are other questions here on StackOverflow that could fit your needs :
detecting any keypress in a terminal : How to break this loop in Python by detecting key press
How to kill a while loop with a keystroke?
Your question is thus a duplicate of one of these.
Here's a threading example that does what you describe.
import time
import threading
thread_live = False
def countdown():
seconds = 0;
while thread_live:
hour = seconds // 3600
minute = (seconds // 60) % 60
second = seconds % 60
print("%02d:%02d:%02d "%(hour, minute, second))
seconds += 1
time.sleep(1)
print("exiting")
while True:
start = input("Press 1 to start and 2 to stop, 3 to exit: ")
if start == "1" and not thread_live:
cd = threading.Thread(target=countdown)
thread_live = True
cd.start()
elif start == "2" and thread_live:
thread_live = False
cd.join()
elif start == "3":
break
Here's a version that uses a timedelta to store and format the time:
import time
import datetime
import threading
thread_live = False
def countdown():
t = datetime.timedelta(0)
one = datetime.timedelta(seconds=1)
while thread_live:
print(str(t))
t += one
time.sleep(1)
print("exiting")
while True:
start = input("Press 1 to start and 2 to stop, 3 to exit: ")
if start == "1" and not thread_live:
cd = threading.Thread(target=countdown)
thread_live = True
cd.start()
elif start == "2" and thread_live:
thread_live = False
cd.join()
elif start == "3":
break

I am trying to execute an alarm function in tkinter but it is not working properly

I am trying to Execute the function in tkinter as I want function to run in background I have done following code. Also I am trying to execute it inside a while loop but its not looping through.
t1 = dt.time(hour = 13, minute= 24)
t2 = dt.time(hour= 13, minute= 4)
timetable = [t1, t2]
root = Tk()
def Alarm():
current_time = now_time.strftime("%H:%M:%S")
print(current_time)
print(timetable[0])
while True:
if timetable[0] <= dt.datetime.now().time():
print("Its time")
break
Alarm()
root.mainloop()
print statements are only for testing. The logic I am using in alarm clock is also not executing properly as it tells ""Its time" even after time has passed. I have tried following methods before.
method 1:
for i in reversed(timetable):
i_time = i
#print (i_time)
#print(now_time.strftime("%H:%M"))
while True:
if dt.datetime.now().time() < i_time:
#if i_time <= dt.datetime.now().time():
print("Its Time")
break
method 2:
for i in timetable:
current_time = dt.datetime.now().time()
alarm_time = i
while True:
if current_time < alarm_time:
if current_time <= alarm_time:
print("its time", alarm_time)
Using for loop was my first goal but for loop isn't executing properly. It only gets 1st element and doesn't go to 2nd element even if first element has passed so I have decided to go with if,elif,else statement
You can use the after method to run a function after a certain amount of time has elapsed. You should use it rather than creating a loop.
You simply need to convert the alarm time to a number of milliseconds, then use that to ring the alarm at the given time. For example, to ring an alarm in one hour you would do this:
def ring_alarm():
print("Its time")
delay = 60 * 60 * 1000 # 60 min/hour, 60 secs/min, 1000ms/sec
root.after(delay, ring_alarm)
I am going with if..else response for executing alarm as
current_time = dt.datetime.now().time()
if timetable[0] == current_time:
print("Its time")
break
I was breaking While loop in wrong place as well an typo from my end.

I Need a More Precise Current-Time, Count down clock in Python

The countdown timer I have made counts down to a specified time of the day, not accounting for which day of what month in what year, I am just looking for it to countdown to the time of day.
The clock works to the second, but for my use, I need it to work to the 100th of a millisecond; Python has 6 digits accounting for the millisecond, yet my clock, no matter what, always ends on a second rather than if I specify a millisecond to land on.
I wanted the clock to end at 9:41, 55 seconds, and 500000 ms, but it instead just rounded my milliseconds to seconds for the desired time to break the loop
user_input = input("Enter time...example: 17:21:15:550000: ")
import datetime
stop = False
while stop == False:
rn = str(datetime.datetime.now().time())
print(rn)
if rn >= str(user_input):
stop = True
print("Ended at wanted time...")
You could try to do this:
from datetime import datetime, timedelta
user_input = input("Enter time...example: '17:21:15:550000' :")
now = datetime.now()
stop_time = datetime.strptime(user_input, "%H:%M:%S:%f")
stop_time = stop_time.replace(year=now.year, month=now.month, day=now.day)
if stop_time < now:
stop_time += timedelta(days=1)
while True:
now = datetime.now()
print(now)
if stop_time < now:
print("Ended at wanted time...")
break;
Let me know if everything works as expected

Repeat a sound/action every certain time

I'm trying to write a Python program that reproduces a sound every certain hour, but it doesn't really work. When I test the code and the specified time comes, it will keep repeating the sound forever.
Here is the code:
import os
from datetime import datetime
now = datetime.now()
currentHour = now.hour
currentMin = now.minute
#I also tested with if but it didn't work
while currentHour==15 and currentMin==33:
os.system("aplay /home/pi/sound.wav") #Plays the sound thru aplay
Your logic is wrong.
First of all, the while loop will most likely end in the first iteration and you want the program to continue till you tell it to.
In addition to that, you don't update the now variable inside the loop, which is basically a bad idea.
For example, this code will continue running and when it is 15:33, a sound will be played only once.
myHour = 15
myMin = 33
is_played = False
while True:
now = datetime.now()
currentHour = now.hour
currentMin = now.minute
if currentHour == myHour and currentMin == myMin and not is_played:
is_played = True
os.system("aplay /home/pi/sound.wav")
if currentHour != myHour or currentMin != myMin:
is_played = False
Xiaotian Pei suggested a great idea, to efficiently use your CPU resource, lets use the Timer module:
def to_play_sound(hour, min):
now = datetime.now()
currentHour = now.hour
currentMin = now.minute
if currentHour == hour and currentMin == min and not is_played:
is_played = True
os.system("aplay /home/pi/sound.wav")
if currentHour != myHour or currentMin != myMin:
is_played = False
while True:
t = Timer(30.0, to_play_sound, [15, 33])
t.start()
J.F. Sebastian has also suggested a great idea:
import datetime
import subprocess
while True:
now = datetime.now()
# compute `deadline`
while True:
deadline = now.replace(hour=hour, minute=min)
if deadline > now:
break
else:
deadline += datetime.timedelta(1)
sleep_until(deadline) # sleep
subprocess.check_call(['aplay', '/home/pi/sound.wav']) # play the sound!
Read how sleep_until was implemented here.
It's a complement to #bshuster13 's answer.
What you need is actually a timer. Using a busy loop and detect if it's the right time to do something is not a good idea. Take a look at Timer in python. I think you will come up with a better solution.

Categories

Resources