Running Python at a Certain Time with Datetime - python

I would like to execute a portion of a script at 8 am each day. I have created a simplified test case that has no syntax error, but does not work properly. I think it may be because my if statement is using the time as a string, but it won't compile any other way. What am I doing wrong?
import datetime
while True:
if datetime.datetime.now().time() == "19:00:00.000000":
print "it's time!"

If you are on a system with cron, then it would be better to set up a cron job. However, your problem is fixable from within Python:
First, as you noted, datetime.datetime.now().time() returns a datetime.time object, not a string:
In [89]: datetime.datetime.now().time()
Out[89]: datetime.time(19, 36, 13, 388625)
Also, although datetime.datetime.now().time() == datetime.time(19, 0) would be
valid Python, the chance that you happen to execute time() at just the right
moment is very slim since datetime.datetime.now() has microsecond
resolution. So it would be better to test if the current time falls within some
range.
However, since you only want to run the function once per day, you could instead measure the total number of seconds between now and when you want to run the function and sleep that number of seconds:
import datetime as DT
import time
while True:
now = DT.datetime.now()
target = DT.datetime.combine(DT.date.today(), DT.time(hour=8))
if target < now:
target += DT.timedelta(days=1)
time.sleep((target-now).total_seconds())
# do something

If you want to keep your code simple, you can use the below code:
import datetime
import time
while True:
time.sleep(1)
if datetime.datetime.now().time().strftime("%H:%M:%S") == '19:00:00':
print ("it's time!")
Sleep is used to generate only 1 row per 1 second (without this you will print thousands of lines. Also it is worth to convert time to string.

Related

Can't get code to execute at certain time

I am trying to get some code to execute at a certain time but I can't figure out what the problem is here. Please help?
import datetime
dt=datetime
set_time=dt.time(12,53)
timenow=dt.datetime.now()
time=False
while not time:
if timenow==set_time:
print("yeeehaaa")
time=True
break
else:
print("naaaaa")
First of all you have to update the time inside the loop or it will always be comparing the same timenow to set_time, then convert all to just an hour/minute string and compare
import datetime
dt=datetime
set_time=str(dt.time(14,19))[0:5]
timenow=dt.datetime.now().time()
time=False
while not time:
timenow=str(dt.datetime.now().time())[0:5]
# print(timenow)
if timenow==set_time:
print("yeeehaaa")
time=True
break
else:
print("naaaaa")
Changing your code to something like this should solve your issue:
import datetime.datetime as dt
set_time=dt.time(12,53)
# the loop waits for the time condition to be met.
# we use the lower than condition in order not to miss the time
# by a few fraction of second.
while (dt.now() < set_time):
time.sleep(0.1) # 100ms delay
# reaching there implies the time condition is met!
print("it is time!")
However there is a much simpler alternative which would consists in get the time delta between the current time and the target time in order to make one single wait with time.sleep(time_delta_s).

How can you update local time from the datetime module?

I am writing a program that uses a while loop to check if it is a certain time, and if it is that certain time, it prints a statement. I have all the if-statements set up, but the time does not update once the program starts (if I start the program at 6 pm, it will always output 6 pm for local time). Is there a way to update the time within the while loop?
I tried to research some additional functions/methods to datetime, but from what I have seen, I have not been able to find any that updates the time while the program is running. Additionally, forums regarding datetime and locale time that I have found on stackoverflow are commonly ones that just explain how to obtain the locale time once (ex, Python datetime module current time in HR:MIN:SEC). Other forums regarding locale times that I have found also tended to be in different languages, particularly C# and PHP. Please correct me if there is another forum that answers my question!
from datetime import date
from datetime import time
from datetime import datetime
import time
import webbrowser
now = datetime.now()
sleep = False
today = date.today()
roundCheck = 0
print("Awaiting time check...")
while sleep != True:
print('Up here...')
if roundCheck != 0:
print('Stuck in time...')
time.sleep(60)
print('Time is done')
if str(now.strftime('%H')) == '20' and str(now.strftime('%M')) == '05':
print('Now the while loop will end')
sleep = True
roundCheck = 1
print('Another round has passed')
print('Outside while loop')
When the time is 20:05, sleep should be set to true and the print statement outside the while loop can be executed. However, when I start the program at an earlier time (20:00, for example), it only uses that time for checking now.strftime().
now never changes. You simply need to put now = datetime.now() in the while loop.

How to use a function when the current time equals another time: Python

I am developing a script that utilizes a function I made to control the relays of an 8 channel relay board on a Raspberry Pi 3. The function works, and calling the function works. I am trying to develop this script so when the current time equals another time, such as Zone 1 start time, the relays turn on/off depending on the status that is received by another part in the code.
I have tested it without this time equals part, and everything works. I seem to be running into some problems when I add this level of complexity. Here is a sample of my code:
while True:
from datetime import datetime
import time
import smbus
ValveStatus='00000001' #0 is closed, 1 is open.
R1_1,R2_1,R3_1,R4_1,R5_1,R6_1,R7_1,R8_1=list(map(int, ValveStatus))
currenttime=datetime.today().strftime('%Y-%m-%d %H:%M:%S')
Z1S_Timestamp='2018-07-09 10:25:11'
if(currenttime==Z1S_Timestamp):
if(R8_1==1):
SetRelayState(BoardOne,8,"ON")
else:
SetRelayState(BoardOne,8,"OFF")
No matter how many times I changed the code, it will never work with this timing method. It never enters the loop and therefore the relay never opens. Is there a better way to do this rather than simply having if equal to statements? I am open to editing it, but the relays still need to open around the time of the start time. I think a margin of 1 or 2 minutes is okay, since timing it exactly equal is not 100% necessary.
Would something like:
currenttime= '2018-07-09 12:53:55' #hard coding just for example purposes
if('2018-07-09 12:52:55' <= currenttime <= '2018-07-09 12:54:55'):
do the things
Be a more valid/correct/pythonically correct method?
Sure - I would do the opposite though - convert all times to datetime() objects and use those for comparison:
TIME_MARGIN = datetime.timedelta(seconds=120) # use a margin of 2 minutes
time_compare = datetime.datetime(2018, 7, 9, 12, 52, 55)
current_time = datetime.datetime.now()
if (time_compare - TIME_MARGIN) < current_time < (time_compare + TIME_MARGIN):
#do something

How to print something at a specific time of the day

Is it possible to have python 2.7 print something at a specific time of the day. For example if I ran the program at 15:06 and coded it to print "Do task now" at 15:07 it prints it. So no matter what time you ran the program once it hit 15:07 it would print "Do task now." In addition is it possible to have it print every week at this time?
I would suggest installing the library schedule, if you're able to.
Use pip install schedule
Your code would look like this if utilizing schedule:
import schedule
import time
def task():
print("Do task now")
schedule.every().day.at("15:07").do(task)
while True:
schedule.run_pending()
time.sleep(1)
You can adjust time.sleep(1) as necessary to sleep for longer if a 1s interval is too long. Here is the schedule library page.
If you're not using cron, then the general solution is to find the time remaining until you need the event to occur, have the program sleep for that duration, then continue execution.
The tricky part is to have the program find the next occurrence of a given time. There are some modules for this, but you could also do it with plain code for a well-defined case where it is only a fixed time of day.
import time
target_time = '15:07:00'
current_epoch = time.time()
# get string of full time and split it
time_parts = time.ctime().split(' ')
# replace the time component to your target
time_parts[3] = target_time
# convert to epoch
future_time = time.mktime(time.strptime(' '.join(time_parts)))
# if not in the future, add a day to make it tomorrow
diff = future_time - current_epoch
if diff < 0:
diff += 86400
time.sleep(diff)
print 'Done waiting, lets get to work'
While python is not ideal to schedule something; there are better tools out there. Yet, if this is desired to be done in python below is a way to implement it:
Prints at scheduled_time of 11AM:
import datetime as dt
scheduled_time = dt.time(11,00,00,0)
while 1==1:
if (scheduled_time < dt.datetime.now().time() and
scheduled_time > (dt.datetime.now()- dt.timedelta(seconds=59)).time() ):
print "Now is the time to print"
break
There are two if conditions with an intent to print within one minute; a shorter duration can be chosen. But the break immediately after print ensures that print is executed only once.
You would need to extrapolate this so that code is run across days.
Refer: datetime Documentation

Python not executing on time.mktime condition in if statement

I have a small script I was going to use to execute a system command at a specified time ("commandTime") and then exit a specified time afterwards ("stopTime"). However, when I run the script it more often than not will never execute the command under the "if" statement. (It will sometimes execute and sometimes won't.)
Assuming I'm not a total idiot (jury is still out on that...) and am setting the time variables reasonably, the script should execute the print command inside the if statement when 'time.mktime(time.localtime())' is equal to or greater than the formatted 'commandTime' variable.
Here is an excerpt of the code in question:
import time
commandTime = time.strptime('2013-03-01 05:00:00', "%Y-%m-%d %H:%M:%S")
stopTime = time.strptime('2013-03-01 05:10:00', "%Y-%m-%d %H:%M:%S")
while (time.mktime(time.localtime()) <= time.mktime(stopTime)):
if (time.mktime(time.localtime()) >= time.mktime(commandTime)):
print "Green team go"
time.sleep(100)
Assuming the stopTime and commandTime variables are set so the following is true when you execute the script:
time.localtime() < commandTime < stopTime
The script should loop through the while statement until time.localtime() is equal to or greater than stopTime, checking the if condition each loop. Once time.localtime() is greater than or equal to commandTime, the print command should execute.
I'm using time.mktime() to convert the datetime object into Unix time (a float I think) in order to make the comparison in both the while loop as well as the if statement.
The while loop works reliably each and every time, it's only the if statement that fails to execute most of the time.
I'm running python 2.7.3 on Debian Squeeze 32-bit.
My question is this: What am I doing wrong in this script that is causing the if statement to not execute when the condition is met?
Thanks!
The way you have it set up currently is making the following true:
commandTime <= time.localtime() <= stopTime
If you want it to be the way you have said you want it (localtime < commandtime < stoptime) you will have to do the following:
import time
commandTime = time.strptime('2013-03-05 21:40:00', "%Y-%m-%d %H:%M:%S")
stopTime = time.strptime('2013-03-05 21:50:00', "%Y-%m-%d %H:%M:%S")
while (time.mktime(time.localtime()) <= time.mktime(stopTime)):
if (time.mktime(time.localtime()) <= time.mktime(commandTime)):
print ("Green team go")
time.sleep(100)
If you just misprinted the way you want it to execute, and you actually want commandTime <= time.localtime() <= stopTime, I tried this way in python 3.2 on Windows (changed print to a function, with my local times inserted) and it works with commandTime and stopTime variables set properly, so it must be something to do with Python 2.7 or Debian Squeeze.
import time
commandTime = time.strptime('2013-03-05 21:40:00', "%Y-%m-%d %H:%M:%S")
stopTime = time.strptime('2013-03-05 21:50:00', "%Y-%m-%d %H:%M:%S")
while (time.mktime(time.localtime()) <= time.mktime(stopTime)):
if (time.mktime(time.localtime()) >= time.mktime(commandTime)):
print ("Green team go")
time.sleep(100)
The code posted in general appears ok. Note that calling time.localtime() will return different results for the while and if loops. If in your real code you have some long-running task between the if and while, and start/stop times are close together, then you may well have the case where the while drops through, but before the if executes time has moved on far enough for the test to fail.
You could rewrite to something like the following. This caches the current time for comparison purposes (nowSec), and avoids costly time conversions on each loop.
import time
commandTime = time.strptime('2013-03-01 05:00:00', "%Y-%m-%d %H:%M:%S")
stopTime = time.strptime('2013-03-01 05:10:00', "%Y-%m-%d %H:%M:%S")
commandTimeSec = time.mktime(commandTime)
stopTimeSec = time.mktime(stopTime)
while True:
nowSec = time.mktime(time.localtime())
if nowSec > stopTimeSec:
break
if nowSec >= commandTimeSec:
print "Green team go"
time.sleep(100)
Turns out the code was fine, the problem was associated with the length of time specified in the sleep statement combined with how close together (in time) the command and stop variables were.
If I set sleep to 100 seconds but then set the time difference between command and stop to less than 100 seconds, it was possible to not trigger the command on an iteration (because it wasn't time yet), wait 100 seconds ("sleeping" through the command time), and then immediately exiting the loop because we had hit or exceeded our stop variable.
Thanks for the help!!
NOTE: If I had a high enough reputation, I would +1 Austin's answer since it was his cleaner loop logic I used to dial-in on the actual issue.

Categories