patternpythonMinor
Handling date rollover in same function
Viewed 0 times
handlingsamerolloverfunctiondate
Problem
I have a program that specifies when an alarm should be active (say, 10AM to 8PM). Part of my program then checks if the alarm is active right now. The "is it active" checker needs to deal with alarm ranges that cross the midnight boundary into tomorrow (say, 8PM to 10AM alarm).
I am currently handling this with redundant functions that are identical, except for AND vs OR comparison. What is the better way, please? (Of course, any other review comments are also most welcome.)
I am currently handling this with redundant functions that are identical, except for AND vs OR comparison. What is the better way, please? (Of course, any other review comments are also most welcome.)
import datetime as dt
def check_alarm_bounds_on_same_date(time_now, time_of_day_bounds):
time_start_of_current_day = dt.datetime.combine(time_now.date(), dt.datetime.min.time())
if ( time_now >= (time_start_of_current_day + dt.timedelta(hours=time_of_day_bounds[0])) and #= (time_start_of_current_day + dt.timedelta(hours=time_of_day_bounds[0])) or #<< OR
time_now < (time_start_of_current_day + dt.timedelta(hours=time_of_day_bounds[1])) ):
return True
return False
def is_alarm_live(time_current, time_of_day_bounds):
alarm_start_time = time_of_day_bounds[0]
alarm_end_time = time_of_day_bounds[1]
if alarm_end_time <= alarm_start_time:
return check_alarm_bounds_on_different_dates(time_current, time_of_day_bounds)
else:
return check_alarm_bounds_on_same_date(time_current, time_of_day_bounds)
# specify two alarm periods (#1 @ 10AM-8PM; #2 @ 8PM-10AM next day)
alarms = [(10,20),(20,10)]
for hour in range(0,24):
# test all hours in a sample day, and output which alarm is active
print 'hour %i: ' % hour,
time_test = dt.datetime(2017,01,22,hour,10,30)
for alarm in alarms:
print is_alarm_live(time_test, alarm),
print ''Solution
Very quick review.
-
No docstrings.
-
The code uses
-
Having done that, it would be simpler still if the function took a
-
There's nothing about this code that is specific to alarms (it could be used for appointments, for example), so it would be easier to understand if the functionality were expressed abstractly.
Revised code:
-
No docstrings.
-
The code uses
datetime.datetime.combine to make datetime.datetime objects representing the bounds, and then compares these with time_current. But it would be simpler to make datetime.time objects to represent the bounds, and then compare those with time_current.time.-
Having done that, it would be simpler still if the function took a
datetime.time object as its first argument, leaving it up to the caller to pass time_current.time if that's what's needed.-
There's nothing about this code that is specific to alarms (it could be used for appointments, for example), so it would be easier to understand if the functionality were expressed abstractly.
Revised code:
import datetime
def time_in_range(time, start_hour, end_hour):
"""Return True if time (a datetime.time object) lies between
start_hour and end_hour (inclusive).
>>> time_in_range(datetime.time(hour=12), 10, 14)
True
The range is allowed to span midnight:
>>> time_in_range(datetime.time(hour=0), 22, 2)
True
"""
start = datetime.time(hour=start_hour)
end = datetime.time(hour=end_hour)
if end <= start: # Range spans midnight.
return start <= time or time <= end
else:
return start <= time <= endCode Snippets
import datetime
def time_in_range(time, start_hour, end_hour):
"""Return True if time (a datetime.time object) lies between
start_hour and end_hour (inclusive).
>>> time_in_range(datetime.time(hour=12), 10, 14)
True
The range is allowed to span midnight:
>>> time_in_range(datetime.time(hour=0), 22, 2)
True
"""
start = datetime.time(hour=start_hour)
end = datetime.time(hour=end_hour)
if end <= start: # Range spans midnight.
return start <= time or time <= end
else:
return start <= time <= endContext
StackExchange Code Review Q#153304, answer score: 4
Revisions (0)
No revisions yet.