Search code examples
pythonpython-3.xdatetimestrftime

Python 3.7 - How do I execute a loop with a start and stop time using datetime.now().strftime() on the minute?


I'm creating a loop which executes every 5 seconds, starting at the startTime variable and ending at the stopTime variable. However, the code below is disregarding the minutes within my startTime and endTime variables and only executing on the hour. For example, even though my startTime is '1130', the code is executing 11:05, rather than ending the loop. I have the same problem with the endTime variable. If the current time is 12:45, the code still executes even though the endTime variable is '1230'. The code will stop executing at '1300'.

frequency = 5 
startTime = '1130' 
endTime = '1230' 
while True: 
     now = datetime.now().strftime('%H:%M:%S')
     if startTime <= now <= endTime:
         print('Loop is working. Time is: ',now)
         time.sleep(frequency)
     else:
          print('Loop is stopped')
          break

I live in Central Time, so I tried switching to Eastern timezone by modifying the "now" variable to:

now = datetime.now(timezone('US/Eastern')).strftime('%H:%M:%S.%f %Z')

but I still get the same problem when I substitute eastern times with startTime and endTime when using the eastern datetime.now().

Is executing code at a precise minute possible with strftime()?


Solution

  • EDIT: (this is now the answer to the real question (oops))

    If you want to wait till for example 11:30 (which was the real question) you can calculate the time (in seconds) the program should sleep (and let it sleep for that time):

    def wait_till(hour, minute, second=0):
        # get system time (and date)
        now_time = datetime.datetime.now()
        # create time point we are waiting for (this year, this month and this day)
        wait_till_time = datetime.datetime(year=now_time.year, month=now_time.month, day=now_time.day, hour=hour, minute=minute, second=second)
        # calculate time we want to wait for and convert to seconds
        wait_for = (wait_till_time - now_time).total_seconds()
        # check if it's going to be tomorrow (if we would sleep for a negative amount of seconds)
        if wait_for < 0:
            # add one day
            wait_till_time = wait_till_time.replace(day=now_time.day+1)
            # recalculate (not very beautiful, but i don't know a better way)
            wait_for = (wait_till_time - now_time).total_seconds()
    
        # printing this waiting time (in seconds)
        print("waiting for",wait_for,"seconds")
        # sleeping for that time
        time.sleep(wait_for)
        # printing the new now time, so we can see how accurate it is
        print("its now",datetime.datetime.now())
    

    and say for example:

    wait_till(20, 24) # waiting till 20:24 (today)
    

    and get:

    waiting for 15.32297 seconds
    its now 2019-03-11 20:24:00.003857
    

    which is pretty darn close to what we wanted (20:24:00.000000) and this delay is probably only caused by the calculation lag of formatting the string.

    (The old stuff ...)

    if it's not important that it takes 100% 5s (but rather 100.04546642303467% --> it will get off a little bit every time) you can just do

    import time
    
    frequency = 5 #every 5 seconds
    start_time = time.time()
    
    while 1:
        elspsed_time = time.time() - start_time
        print(elspsed_time)
        time.sleep(frequency)
    

    but if you need the 100% you can try this autocorrecting solution:

    import time
    from threading import Timer
    
    frequency = 5 #every 5 seconds
    start_time = time.time()
    
    def what_to_do_after_5s():
        elapsed_time = time.time() - start_time
    
        print(elapsed_time)
    
        # next call
        Timer(5.0 - (elapsed_time - int(elapsed_time)), what_to_do_after_5s, ()).start()
    
    what_to_do_after_5s()
    

    and we can see that it autocorrects:

    0.0
    5.000170707702637
    10.000272989273071
    15.000539064407349
    20.001248836517334
    25.00046443939209
    30.000929355621338
    35.00142860412598
    40.0007688999176
    45.00128436088562
    50.00045442581177
    55.000683069229126
    60.00123882293701
    65.00095415115356
    70.0015127658844