Reputation: 580
I have a program that has functions that run in an interval (example: default is every hour but you can set it from seconds to every 23 hours). This is user settable in a config file. I'm attempting to change the code so that if you input "0" as the interval, it reads the next line of the config file which is a setting poll_times
, wherein the user can input a list of times that he wishes a "poll" to be done in full hours. For example, if I set poll_times
in the configuration file as such:
poll_times = 16,17,19,20,22,23
The poll would be done at 4pm, 5pm, 7pm, 8pm, 10pm and 11pm every day.
I've nearly got everything down except when it comes to skipping to the next day. Currently the function in question is performing flawlessly if I start the program at anytime before the first poll and it'll run through all the polls until it gets to the last one. Once it hits the last one of the list on any day it'll simply try to keep setting the next_poll
to that same hour of that same day, instead of skipping to the next_poll of the next day.
Here's my code:
def set_next_poll_time(self):
now = datetime.datetime.now()
next_poll = datetime.datetime(year=now.year, month=now.month, day=now.day)
next_poll_time = self.next_poll_time
if self.poll_frequency is 0:
poll_times = self.poll_times
LOGGER.info("Poll Times: {0}".format(self.poll_times))
# Determine what the next poll_time should be
for hour in poll_times:
next_poll = datetime.datetime(year=now.year, month=now.month, day=now.day, hour=hour)
if next_poll == now: # This is the last time in the sequence, so the next_poll should be tomorrow at the first entry in poll_times
tomorrow = datetime.datetime.now() + datetime.timedelta(days=1)
next_poll = datetime.datetime(year=tomorrow.year, month=tomorrow.month, day=tomorrow.day, hour=poll_times[0])
break
elif next_poll > now:
break # Done, return
else:
continue
next_poll_time = time.mktime(next_poll.timetuple())
LOGGER.info("Next poll: {0}".format(next_poll))
else:
poll_minutes = self.poll_frequency / 60
while next_poll <= now:
next_poll += datetime.timedelta(minutes=poll_minutes)
next_poll_time = time.mktime(next_poll.timetuple())
LOGGER.info("{0} -> {1} {2}".format(self.next_poll_time, next_poll_time, next_poll))
self.next_poll_time = next_poll_time
this is all in a class so here are some values that are set as part of the class init:
self.next_poll_time = 0
self.poll_times # directly set from what the user enters in the config file
self.poll_frequency # directly set from config file
What this function should do:
next_poll_time
based on the list of poll_times
. This is working as it should until the last time of the daypoll_times
list, then skip to the
next day and get the first poll_time for the new day and set next_poll_time
to that value.What this function does is get to the end of the list and keeps setting the next_poll_time to the last poll_time of that same day, not the next day as I need it to (and from what I see it is programmed to).
The debug lines give the following outputs. SKIPPING past due poll
is the output from the part of the program that calls this function (hence why it just calls the function again and again):
[02-20-2019 21:01:05] INFO, MainThread, - SKIPPING past due poll 1550696400.0.
[02-20-2019 21:01:05] INFO, MainThread, - Poll Times: [16, 17, 19, 20, 21]
[02-20-2019 21:01:05] INFO, MainThread, - Next poll: 2019-02-20 21:00:00
[02-20-2019 21:01:05] INFO, MainThread, - 1550696400.0 -> 1550696400.0 2019-02-20 21:00:00
[02-20-2019 21:01:07] INFO, MainThread, - SKIPPING past due poll 1550696400.0.
[02-20-2019 21:01:07] INFO, MainThread, - Poll Times: [16, 17, 19, 20, 21]
[02-20-2019 21:01:07] INFO, MainThread, - Next poll: 2019-02-20 21:00:00
[02-20-2019 21:01:07] INFO, MainThread, - 1550696400.0 -> 1550696400.0 2019-02-20 21:00:00
[02-20-2019 21:01:08] INFO, MainThread, - SKIPPING past due poll 1550696400.0.
[02-20-2019 21:01:08] INFO, MainThread, - Poll Times: [16, 17, 19, 20, 21]
[02-20-2019 21:01:08] INFO, MainThread, - Next poll: 2019-02-20 21:00:00
[02-20-2019 21:01:08] INFO, MainThread, - 1550696400.0 -> 1550696400.0 2019-02-20 21:00:00
[02-20-2019 21:01:09] INFO, MainThread, - SKIPPING past due poll 1550696400.0.
[02-20-2019 21:01:09] INFO, MainThread, - Poll Times: [16, 17, 19, 20, 21]
[02-20-2019 21:01:09] INFO, MainThread, - Next poll: 2019-02-20 21:00:00
[02-20-2019 21:01:09] INFO, MainThread, - 1550696400.0 -> 1550696400.0 2019-02-20 21:00:00
Thanks for any guidance you can provide.
Upvotes: 1
Views: 120
Reputation: 580
With @ferrix's advice I was able to solve this myself. I just needed to tell the code when the hour was the last in the list and put the code to find tomorrow under that. So the for block changes to this:
for hour in poll_times:
next_poll = datetime.datetime(year=now.year, month=now.month, day=now.day, hour=hour)
if next_poll <= now:
if hour == poll_times[-1]: # This is the last time in the sequence and it still isn't greater than, so skip to next day
tomorrow = datetime.datetime.now() + datetime.timedelta(days=1)
next_poll = datetime.datetime(year=tomorrow.year, month=tomorrow.month, day=tomorrow.day, hour=poll_times[0])
else:
continue
elif next_poll > now:
break # Done, return
else:
continue
Upvotes: 0
Reputation: 761
It seems to me that next_poll == now
is not the only condition when tomorrow would have to be considered. Also, datetime
accounts for seconds even if you do not set them, so next_poll == now
will be True
at a very specific second of the day.
Upvotes: 1