Search code examples
pythonschedule

Python execute task if time now is in array of times


I have an array of times as such:

array_of_times = ['2020-03-20 16:05:30', '2020-03-20 16:20:30', '2020-03-20 16:27:30', '2020-03-20 16:30:30', '2020-03-20 16:40:30', '2020-03-20 16:55:30', '2020-03-20 17:00:30', '2020-03-20 17:04:30', '2020-03-20 17:05:30', '2020-03-20 17:15:30', '2020-03-20 17:30:30', '2020-03-20 17:35:30', '2020-03-20 17:42:30', '2020-03-20 17:45:30', '2020-03-20 17:55:30', '2020-03-20 18:00:30', '2020-03-20 18:15:30', '2020-03-20 18:25:30', '2020-03-20 18:30:30', '2020-03-20 18:45:30', '2020-03-20 18:55:30', '2020-03-20 19:00:30', '2020-03-20 19:15:30', '2020-03-20 19:25:30', '2020-03-20 19:30:30', '2020-03-20 19:45:30', '2020-03-20 19:55:30', '2020-03-20 20:00:30', '2020-03-20 20:15:30', '2020-03-20 20:25:30', '2020-03-20 20:30:30', '2020-03-20 20:45:30', '2020-03-20 21:00:30', '2020-03-20 21:15:30', '2020-03-20 21:45:30', '2020-03-20 22:15:30']

And I was wondering if there was a way in python to check if the current time is in the array, and if it is, complete a task.

However, I want to do this in a way where my server is not over working just waiting for the time to equal a time in the array.

I have tried simple solutions such as:

now = str(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))

while True:
    if now in array_of_times:
        print("Time is in")

However it never evaluated as true for the if statement even if the correct time passed.

I have also tried using:

for z in array_of_times:
    schedule.every().day.at(z).do(execute_task)
#given z was in the correct format

However, still no luck.

Any support is appreciated. Thanks


Solution

  • One solution is to fix the assignment of 'now'. In order to check if your time is in the array, you should update 'now' in the loop.

    while True:
        now = str(datetime.now().strftime("%Y-%m-%d %H:%M:%S"))
        if now in array_of_times:
            print("Time is in")
    

    It takes a relatively long time to find whether the current time is in your array, so it is not a good idea to do something like this with a list of times:

    if now in array_of_times
    

    This is because it will search through every value in the array, one at a time.

    Therefore, a better solution is to have a set of times, as hashing will speed up the time to find whether the time is in the array. Therefore define your array as such:

    set_of_times = set(['2020-03-20 16:05:30', '2020-03-20 16:20:30', '2020-03-20 16:27:30', '2020-03-20 16:30:30', '2020-03-20 16:40:30', '2020-03-20 16:55:30', '2020-03-20 17:00:30', '2020-03-20 17:04:30', '2020-03-20 17:05:30', '2020-03-20 17:15:30', '2020-03-20 17:30:30', '2020-03-20 17:35:30', '2020-03-20 17:42:30', '2020-03-20 17:45:30', '2020-03-20 17:55:30', '2020-03-20 18:00:30', '2020-03-20 18:15:30', '2020-03-20 18:25:30', '2020-03-20 18:30:30', '2020-03-20 18:45:30', '2020-03-20 18:55:30', '2020-03-20 19:00:30', '2020-03-20 19:15:30', '2020-03-20 19:25:30', '2020-03-20 19:30:30', '2020-03-20 19:45:30', '2020-03-20 19:55:30', '2020-03-20 20:00:30', '2020-03-20 20:15:30', '2020-03-20 20:25:30', '2020-03-20 20:30:30', '2020-03-20 20:45:30', '2020-03-20 21:00:30', '2020-03-20 21:15:30', '2020-03-20 21:45:30', '2020-03-20 22:15:30'])
    

    A third alternative solution is, if you would like to minimize the amount of work that the server is doing, to first sort the list of times, look at how long it will take to reach the next time, and use time.sleep to wait. Python's time.sleep doesn't busy wait, so you will free up your CPU.

    from datetime import datetime
    import time
    
    array_of_times = ['2020-03-19 22:34:00']
    array_of_times.sort()
    
    while True:
        if not array_of_times:
            print("No more times in array.")
            break
        next_time_string = array_of_times[0]
        next_time = datetime.strptime(next_time_string, "%Y-%m-%d %H:%M:%S")  # get the datetime from the date
        del array_of_times[0]  # remove the first date
        time.sleep((next_time - datetime.now()).total_seconds())
        # do action
        print("I reached time:", next_time_string)
    

    The output of this code is:

    $ python test2.py
    I reached time: 2020-03-19 22:34:00
    No more times in array.