While loop referring to time - python

I'm having issues referring to time in a while loop. Currently this is my code
def autoRoutine():
now = datetime.datetime.now().time()
autoStart = now.replace(hour=8, minute=0)
stoptime = datetime.datetime.now().time()
autoStop = stoptime.replace(hour=12, minute=4)
while (now <= autoStop):
print("the lights are starting")
time.sleep (1.0)
if (now > autoStop):
break
print(autoStart.strftime("%H:%M"))
So what I'm trying to do is have the while loop perform between the autoStart time and the autoStop time. If it is AFTER autoStop, I want the while loop to be broken. If it helps, this is being implemented for a light routine in which the lights only operate between 8am (autoStart) and 8pm (autoStop) but for the sake of waiting to see if it works, I'm adjusting autoStop to just one minute ahead of the current time.
I cannot seem to get unstuck from the loop and it is driving me insane because it should be fairly simple. Thanks in advance.

You should use a flag:
flag = False
while flag = False:
if condtion:
flag = True
Also check this file. It's a Django view but it might help you

I solved my own issue using a third time reference to iterate through my while loop
while (keepprint == False):
nowloop = datetime.datetime.now().time()
print (nowloop)
print (autoStop)
print("the lights are starting")
time.sleep (1.0)
if (nowloop >= autoStop):
keepprint = True
That way I can keep track of the current time through each iteration.

Related

I am trying to make a alarm like feature app but it keeps waiting

I am trying to make a alarm like app where I want a list of things to happen when its time. But I am facing a bug. Time keeps waiting for previous time instead of going to next time in list.
t1 = dt.time(hour=17,minute=8)
t2 = dt.time(hour=18,minute=48)
timetable = [t1, t2]
for elt in timetable:
i_time = elt
#i_minute = i.minute
while True:
if i_time == dt.datetime.now().time():
#if i_hour == dt.datetime.now().hour and i_minute == dt.datetime.now().minute:
#current_time = tk.Label(text = dt.datetime.now())
#current_time.pack()
#playsound('media/ClassAlarm.mp3')
print("Its time")
break
The function works fine when it comes to t1 but if t1 is passed and current time is higher that t1 it should go to t2 and ring alarm. But it keeps waiting for t1 which will happen next day. it doesn't read t2 unless t1 is processed.
Ex. Current time 1:30 while t1 is 1:25 and t2 is 1:35. It doesn't ring at t2 but keeps waiting for t1 to happen again which has already happened.
I have tried to execute for loop in different way
for elt in timetable:
time = dt.datetime.now().time()
if time - elt < 0:
break
while(True):
if time == elt:
print("you did it")
I have also tried any() method. Which isn't helping exactly as well
current_hour = dt.datetime.now().hour
current_min = dt.datetime.now().minute
alarm = any(i.hour == current_hour and i.minute == current_min for i in timetable)
print(alarm)
I have tried posting question previously but wasn't able to explain properly. Hope this helps
Using == Operator To Compare Time Is Risky, Logically It Should Work But Somehow It's Better To Use <= Operator Which Eventually Compare If Your Time Is Greater Than The One Recorded In List! This Is Lot Safer Than Equality Which Trigger Only Once And Has No Guarantee To Work For A Split
-->Note: I Believe Those Function Generated Timestamp Of Different Format, Although They Represent Time And Are Useful But Since They Are In Different Format You Ain't Getting Equality Operator To Work (Bcz Even for Same Time And Date, Your Timestamp Gonna Be Different Although They Represent Same). To confirm this behavior you can write print variables of t1 and datetime.now and see if they are same.
Regarding Your Second Question You Can Have if/else statements to check for which time has been occured and most last time which has just been crossed, or you can run loop in reverse and check for timer (assuming late timers are in end of loop)
Sample Code:
for elt in timetable.reverse():
i_time = elt
while True:
if i_time <= dt.datetime.now().time():
print("Its time")
break

Make a loop last once second using datetime?

Bright minds of Stackoverflow, I have a quest for you.
Currently I am running a loop in which calculations and data aquisition happen. These get more and more complicated over time. I want each run of the loop to last exactly one second. Due to the growing time of the calculations a simple "sleep(1)" at the end does not really help.
while True:
#here calculations happen that take more and more time
print 'some of the data'
sleep(1)
I was hoping to use datetime to calculate the seconds/milliseconds before these calculations and after to enter the difference into the sleep command. But i can't quite get my head around it. Can anyone help me out?
a=datetime.now()
#calculations
b=datetime.now()
calctime=(b-a).total_seconds()
sleep(1-calctime)
Try this:
from datetime import datetime
import time
def test():
a = datetime.now()
# calculations
b = datetime.now()
calctime = (b - a).total_seconds()
print("one")
time.sleep((1 - calctime) if (1-calctime)>0.0 else 0) #if your calculation already took 1 or more than 1 second then then make the waiting time 0
print("two")
test()
a=datetime.now()
#calculations
b=datetime.now()
calctime=b-a
ms = calctime.microseconds
if calctime.seconds == 0:
sleep(1-ms/1000000)
Additional info here: Python speed testing - Time Difference - milliseconds

Python: How to compare two hours

I need to call a function, exactly 08:00, 18:00, 22:00 hours. I've created a example to test the comparison between hours. When the current time reaches one of those horary. Put in inside a While loop thinking this example would work as a stopwatch, but I think I'm wrong. How is the best way to compare those values?
currentH= dt.datetime.now().strftime("%H:%M:%S")
h = "16:15:10"
while True:
if(currentH==h):
print 'Ok'
print 'The current Hour is: '+h
import datetime as dt
import time
currentH= dt.datetime.now().replace(microsecond=0).time()
hrs = ['00:02', '12:00']
for i in range(len(hrs)):
h = [int(x) for x in hrs[i].split(':')]
h = dt.datetime.now().replace(hour=h[0], minute=h[1], second=0,microsecond=0).time()
hrs[i] = h
while True:
currentH = dt.datetime.now().replace(microsecond=0).time()
print(currentH)
if currentH in hrs:
print('Time is now',currentH)
time.sleep(1)
The biggest problem with your code is that you never call now() again inside the loop, so you're just spinning forever comparing the initial time to 16:15:10.
While we're at it: Why convert the time to a string for comparison instead of just comparing times?
But there are bigger problems with this design that can't be fixed as easily.
What happens if you check the time at 16:15, then go to sleep, then wake up at 16:25? Then now() never returns 16:15:10.
Also, do you really want to burn 100% CPU for 10 hours?
A better solution is to write a sleep_until function:
def sleep_until(target):
left = target - dt.datetime.now()
if left > dt.timedelta(seconds=0):
time.sleep(left.total_seconds())
(If you're using Python 2.7 or 3.4, it's a bit more complicated, because sleep will wake up early if there's a signal. But to handle that case, you just need to add a while True: loop around the whole thing.)
Now, the only tricky bit is working out the first time you need to sleep until, which isn't all that tricky:
waits = itertools.cycle(dt.timedelta(hours=wait) for wait in (10, 4, 10))
now = dt.datetime.now()
start = dt.datetime.combine(dt.date.today(), dt.time(hour=8))
for wait in waits:
start += wait
if start > now:
break
And now, we just loop over the waits forever, sleeping until each next time:
for wait in waits:
sleep_until(start)
print('Time to make the donuts')
start += wait
Or, of course, you could just grab one of the many scheduling libraries off PyPI.
Or just use your platform's cron/launchd/Scheduled Tasks API to run your script.

Python: Stop at desired time

I have some problem here. I want to stop the print command at desired time. I figured out some codes and it still keep looping. Here the code,
import time
t = time.strftime("%H%M%S")
while ti:
print(time.strftime("%H%M%S"))
time.sleep(1)
if t = ("140000"): #just example of time to stop print
break
Thanks
t = time.strftime("%H%M%S")
is only executed once before the loop, so t's value doesn't ever change.
Your approach is the worst method of checking time difference; python's datetime framework allows for subtraction of timestamps and thus, you can check the time since something else happened easily without doing any string comparisons...
This will work
import time
t = time.strftime("%H%M%S")
while t:
t = time.strftime("%H%M%S")
print(time.strftime("%H%M%S"))
time.sleep(1)
if t == ("140000"): #just example of time to stop print
break
You had some bugs in your code
while ti: -- > while t:
if t = ("140000"): --> if t== ("140000"):
and you were missing this line t = time.strftime("%H%M%S")
time.sleep(1) may sleep less or more than a second therefore t == "140000" is not enough.
To stop a loop at a given local time:
import time
from datetime import datetime
stop_dt = datetime.combine(datetime.now(), datetime.strptime("1400", "%H%M").time())
stop_time = time.mktime(stop_dt.timetuple())
while time.time() < stop_time:
print(time.strftime("%H%M%S"))
time.sleep(max(1, (stop_time - time.time()) // 2))
time.time() returns "seconds since the epoch" -- unlike strings comparison it works across a midnight.
The sleep interval is a half of the remaining time or one second (whatever larger).
time.mktime() may return a wrong result if stop time is during an end-of-DST transition ("fall back") when the local time is ambiguous (the string-based solution may stop twice in this case).
Try this:
import time
while ti:
t = time.strftime("%H%M%S")
print(time.strftime("%H%M%S"))
time.sleep(1)
if t = ("140000"): #just example of time to stop print
break

End a loop when current time is something specific

I have asked a question similar to this before, but this time it is a little different. To me, the following code should work.
import datetime
# run infinitly
while(True):
done = False
while(not done):
#
#main program
#
#stopping condition
if currenttime == '103000':
done = True
#continue with rest of program
However, it doesn't continue with the rest of the program when it hits 10:30:00am.
The following program I KNOW works (on a raspberry pi):
import datetime
done = False
while not done:
currenttime = datetime.datetime.now().strftime('%H%M%S')
if currenttime != '103000':
print currenttime
if currenttime == '103000':
done = True
print 'It is 10:30:00am, the program is done.'
It made logical sense to me what I did in that first example. Does anyone know why it won't exit that loop and continue with the rest?
If the main program takes a long time to run, currenttime could jump from 102958 to 103005. Therefore skipping 103000 entirely.
Maybe you need to set currenttime, before you check? Also, the if statement has to execute exactly at 103000 in order for done = True to execute.
while(True):
done = False
while(not done):
#
#main program
#
# need to set current time
currenttime = datetime.datetime.now().strftime('%H%M%S')
#stopping condition (use >= instead of just ==)
if currenttime >= '103000':
done = True
#continue with rest of program
Note that is not guaranteed that your loop has one iteration in each and every available second. The more load is on your system, the larger the likelihood that the loops skips a second, which potentially would be the termination criterion. There are also cases where seconds may be skipped, e.g. due to time synchronization or daylight saving issues.
Instead of a busy waiting loop, you could pre-compute the timedelta in seconds and then sleep for that many seconds.
Advantages:
You'll save computation power that other processes on your machine could use instead.
It probably increases the lifetime of your hardware.
This will also be more energy efficient.
Example:
import datetime
import time
def wait_until_datetime(target_datetime):
td = target_datetime - datetime.datetime.now()
seconds_to_sleep = td.total_seconds()
if seconds_to_sleep > 0:
time.sleep(seconds_to_sleep)
target_datetime = datetime.datetime(2025, 1, 1)
wait_until_datetime(target_datetime)
print "Happy New Year 2025!"
Note that this may still fail to produce the desired behavior due to arbitrary changes of the systems date and time settings. Probably it would be best to adopt a completely different strategy to execute a specific command at a specific time. Have you considered implementing the desired behavior using a cron job? (You could send a signal to the process and thereby issue it to cancel the loop...)
import datetime
done = False
while True:
currenttime = datetime.datetime.now().strftime('%H%M%S')
if currenttime >= '103000':
break
print currenttime
print 'It is 10:30:00am, the program is done.'
If you can't use break:
import datetime
done = False
while not done:
currenttime = datetime.datetime.now().strftime('%H%M%S')
if currenttime >= '103000':
done = True
else:
print currenttime
print 'It is 10:30:00am, the program is done.'

Categories