Python - Working out if time now is between two times
Solution 1
Your code is a bit chaotic. I would do something like this:
import datetime
DAY, NIGHT = 1, 2
def check_time(time_to_check, on_time, off_time):
if on_time > off_time:
if time_to_check > on_time or time_to_check < off_time:
return NIGHT, True
elif on_time < off_time:
if time_to_check > on_time and time_to_check < off_time:
return DAY, True
elif time_to_check == on_time:
return None, True
return None, False
on_time = datetime.time(23,30)
off_time = datetime.time(4,15)
timenow = datetime.datetime.now().time()
current_time = datetime.datetime.now().time()
when, matching = check_time(current_time, on_time, off_time)
if matching:
if when == NIGHT:
print("Night Time detected.")
elif when == DAY:
print("Day Time detected.")
Solution 2
To find out whether a given time (no date) is in between given start, end times (the end is not included):
def in_between(now, start, end):
if start <= end:
return start <= now < end
else: # over midnight e.g., 23:30-04:15
return start <= now or now < end
Example:
from datetime import datetime, time
print("night" if in_between(datetime.now().time(), time(23), time(4)) else "day")
Solution 3
def is_hour_between(start, end, now):
is_between = False
is_between |= start <= now <= end
is_between |= end < start and (start <= now or now <= end)
return is_between
test with:
assert is_hour_between(6, 10, 6)
assert not is_hour_between(6, 10, 4)
assert is_hour_between(17, 20, 17)
assert not is_hour_between(17, 20, 16)
Solution 4
Kevron's post actually helped solve my issue. My requirement was slightly different where I was passing strings. My version looks like this:
def is_hour_between(start, end):
# Time Now
now = datetime.datetime.now().time()
# Format the datetime string
time_format = '%Y-%m-%d %H:%M:%S'
# Convert the start and end datetime to just time
start = datetime.datetime.strptime(start, time_format).time()
end = datetime.datetime.strptime(end, time_format).time()
is_between = False
is_between |= start <= now <= end
is_between |= end <= start and (start <= now or now <= end)
return is_between
check = is_hour_between('2021-04-07 08:30:00', '2021-04-07 04:29:00') #spans to the next day
print("time check", check) # result = True
Hope this helps someone struggling with string times.
dalgibbard
Updated on July 09, 2022Comments
-
dalgibbard almost 2 years
I'm trying to find the cleanest/most pythonic way of evaluating if "now" is between two times; However; the Start/End times may, or may not, fall across a day boundary- for example (just using simple examples):
onhour=23 onmin=30 offhour=4 offmin=15 timenow = datetime.datetime.now().time()
Doing a straight
if START < NOW < END
scenario won't work for this!What I have currently is some code which evaluates if it's currently "NightTime", which looks like this:
def check_time(timenow, onhour, onmin, offhour, offmin, verbose): now = datetime.datetime.now() now_time = now.time() # If we're actually scheduling at night: if int(offhour) < int(onhour): # Check to see if we're in daylight times (ie. off schedule) if datetime.time(int(offhour),int(offmin)) <= now_time <= datetime.time(int(onhour),int(onmin)): if verbose == True: print("Day Time detected.") return False else: if verbose == True: print("Night Time detected.") return True else: if datetime.time(int(onhour),int(onmin)) <= now_time <= datetime.time(int(offhour),int(offmin)): if verbose == True: print("Night Time detected.") return True else: if verbose == True: print("Day Time detected.") return False
Apologies if the title doesn't sound like anything new, but having reviewed a few existing answers for similar problems such as:
I noticed that these don't seem to account for instances where the Start and End times occur over a day boundary.
In addition to this; any ideas surrounding adding Day based scheduling would be quite useful too! ie. "for Mon - Fri, turn on at 23:00, off a 04:00" - but managing on and off for a day either side (else; something will be turned on, on Friday, but not be turned off on the Saturday-- and yet, including Saturday means it gets turned back on again at 23!...)
I've considered doing a simple "Turn on at X, sleep for Y" to get around this... but if the script is started up during an "On" cycle, it won't be initiated until the next run... But it seems like the simplest option! :)
I'm hoping there's some sort of awesome module that does all this... :D
Compatibility of Python2.7 - 3.2 is pretty important to me too!
-
leeladam over 10 yearsHow do you know which day your ontime and offtime refers to? For example, if "now" is on 11 Dec, how can you decide in your example if the interval is from 10 Dec 23:30 to 11 Dec 4:15 OR from 11 Dec 23:30 to 12 Dec 4:15?
-
Simeon Visser over 10 yearsThe problem seems to be that you only have hours and minutes, you don't have dates. If you have three dates then
date1 <= date2 <= date3
works fine. -
jonrsharpe over 10 yearsHave you looked into the Advanced Python Scheduler?
-
John La Rooy over 10 yearsFirst write test cases for all the variations you want...
-
dalgibbard over 10 years@SimeonVisser - I agree, definite room for improvement; but i couldn't wrap my head around how to evaluate if say,
offhour
should be assigned to today or tomorrow... I guess evaluating iftime.now()
is greater thanoffhour
, or similar, would likely be sufficient... -
dalgibbard over 10 years@jonrsharpe - I had a quick look at Advanced Python Scheduler, and it seems good for starting jobs, but i didn't see much in the way of defining a "Stop" based on date/time (just a "duration" equivilent)? Maybe I missed the example in the docs though?
-
-
dalgibbard over 10 yearsCould that be simplified by using ">=" for the "if time_to_check" statements, thereby removing the need for the last "elif"?
-
smeso over 10 yearsThe last elif is there to manage the case where on_time and off_time are exactly the same time (and time_to_check is in this "interval"). In this case you cannot tell if it is a "night" or "day" interval, unless you choose some fixed interval for "night" and "day" based on sunset/sunrise time in the geographical area of interest.
-
rouble almost 8 yearswhat if start is 2AM, and end is 2AM, and now is 4AM, wouldn't this fail? - shouldn't the first if read, if start < end?
-
jfs almost 8 years@rouble
[2AM, 2AM)
is an empty range ("the end is not included" — as it says explicitly in the answer) i.e., the code behaves as documented. If desired; the requirements and the could be changed. Though there are benefits, to specify a range without the right border in many cases (that is whyrange(2,2)
is empty too in Python). -
rouble almost 8 yearsI see your point. And your answer is the better answer (hence the upvote). I do think that when we trying to find out if a time lies within a time period of a day, we should allow a complete 24 hour time range.