In [ ]:
In [ ]:
#working hours. Nobody works 24x7 so there are two possibilities for non-work hours.
#going to do this the way I've seen it specified elsewhere.
#normal hours worked
work_hours = {'start': '08:00',
'end': '17:00'}
work_days = ['Monday','Tuesday','Wednesday','Thursday','Friday']
#assume that the holiday is all day.
holiday_days = ['2017-05-29', '2017-07-04']
In [ ]:
##some days to test and expected results as tuple (date, expected is_within_workday result)
sample_datetimes = [('2017-05-20 08:00:01', False), ##8am but on a weekend
('2017-05-20 07:59:59', False), ##before 8am but on a weekend
('2017-05-18 08:00:01', True), ##8am on a week day.. yes working hours
('2017-05-18 07:59:59', False), ##before 8am on a working day. not working hours
('2017-05-20 16:59:59', False), ##before 5pm but on a non workday
('2017-05-20 17:00:01', False), ##after 5pm but on a non workday
('2017-05-18 16:59:59', True), ##before 5pm but on a weekday yes working hour
('2017-05-18 17:00:01', False), ##after 5pm on a work day.. no not worktime
('2017-05-29 08:00:01', False), ##after 8 am but on a holiday no not work time
('2017-05-29 07:59:59', False), ##before 8am but on a holiday not work time
('2017-05-18 08:00:00', True), ##at 8am but on a holiday not work time
('2017-05-18 17:00:00', True), ##before 8am but on a holiday not work time
]
In [ ]:
# Python cookbook 3.13 looks useful!
In [ ]:
from datetime import datetime, date, time
class WorkingTimes:
"""
WorkingTimes
Class used to encapsulate the work day, work hours and holiday
details needed for calcuating whether a specific date is or is not within working hours.
Checks are:
Is the datetime on a work day.
Is the datetime between the start of work day and end of work day
Is the datetime on a day that has been identified as a holiday.
"""
DAYLIST = ['Monday','Tuesday','Wednesday','Thursday','Friday', 'Saturday', 'Sunday']
STRDT = '%Y-%m-%d %H:%M:%S'
SDRD = '%Y-%m-%d'
STRHR = '%H:%M'
def __init__(self, work_hours_start, work_hours_end, work_days, holiday_list):
self.whs = work_hours_start
self.whe = work_hours_end
##all workdays should be real days from DAYLIST ['Monday','Friday']
self.wda = work_days
##holiday_list (convert them all to dates)
self.hdl = [datetime.strptime(hd, WorkingTimes.SDRD) for hd in holiday_list]
def __str__(self):
return("work start: {}, end: {}, days {}".format(self.whs, self.whe, self.wda))
def is_within_workday(self, dts = datetime.now()):
dt = datetime.strptime(dts, WorkingTimes.STRDT) if isinstance(dts,str) else dts
work_hours_start_datetime = datetime.combine(dt.date(),
datetime.strptime(self.whs, WorkingTimes.STRHR).time())
work_hours_end_datetime = datetime.combine(dt.date(),
datetime.strptime(self.whe, WorkingTimes.STRHR).time())
is_workday = any( [s for s in self.wda if ( s == WorkingTimes.DAYLIST[dt.weekday()])])
holiday = any([d for d in self.hdl if (d.date() == dt.date())])
return((not holiday) and (is_workday and (dt>=work_hours_start_datetime and dt<= work_hours_end_datetime)))
In [ ]:
foo = WorkingTimes(work_hours['start'], work_hours['end'], work_days, holiday_days)
In [ ]:
print(foo)
In [ ]:
#check all my test cases to see if they are returning as expected.
[e == foo.is_within_workday(dt) for dt,e in sample_datetimes ]