forked from dnel/BusinessHours
-
Notifications
You must be signed in to change notification settings - Fork 0
/
BusinessHours.py
109 lines (101 loc) · 4.46 KB
/
BusinessHours.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import datetime
class BusinessHours:
def __init__(self, datetime1, datetime2, worktiming=[9, 17],
weekends=[6, 7]):
self.weekends = weekends
self.worktiming = worktiming
self.datetime1 = datetime1
self.datetime2 = datetime2
self.day_hours = (self.worktiming[1]-self.worktiming[0])
self.day_minutes = self.day_hours * 60 # minutes in a work day
def getdays(self):
return int(self.getminutes() / self.day_minutes)
def gethours(self):
return int(self.getminutes() / 60)
def getminutes(self):
"""
Return the difference in minutes.
"""
# Set initial default variables
dt_start = self.datetime1 # datetime of start
dt_end = self.datetime2 # datetime of end
worktime_in_seconds = 0
if dt_start.date() == dt_end.date():
# starts and ends on same workday
full_days = 0
if self.is_weekend(dt_start):
return 0
else:
if dt_start.hour < self.worktiming[0]:
# set start time to opening hour
dt_start = datetime.datetime(
year=dt_start.year,
month=dt_start.month,
day=dt_start.day,
hour=self.worktiming[0],
minute=0)
if dt_start.hour >= self.worktiming[1] or \
dt_end.hour < self.worktiming[0]:
return 0
if dt_end.hour >= self.worktiming[1]:
dt_end = datetime.datetime(
year=dt_end.year,
month=dt_end.month,
day=dt_end.day,
hour=self.worktiming[1],
minute=0)
worktime_in_seconds = (dt_end-dt_start).total_seconds()
elif (dt_end-dt_start).days < 0:
# ends before start
return 0
else:
# start and ends on different days
current_day = dt_start # marker for counting workdays
while not current_day.date() == dt_end.date():
if not self.is_weekend(current_day):
if current_day == dt_start:
# increment hours of first day
if current_day.hour < self.worktiming[0]:
# starts before the work day
worktime_in_seconds += self.day_minutes*60 # add 1 full work day
elif current_day.hour >= self.worktiming[1]:
pass # no time on first day
else:
# starts during the working day
dt_currentday_close = datetime.datetime(
year=dt_start.year,
month=dt_start.month,
day=dt_start.day,
hour=self.worktiming[1],
minute=0)
worktime_in_seconds += (dt_currentday_close
- dt_start).total_seconds()
else:
# increment one full day
worktime_in_seconds += self.day_minutes*60
current_day += datetime.timedelta(days=1) # next day
# Time on the last day
if not self.is_weekend(dt_end):
if dt_end.hour >= self.worktiming[1]: # finish after close
# Add a full day
worktime_in_seconds += self.day_minutes*60
elif dt_end.hour < self.worktiming[0]: # close before opening
pass # no time added
else:
# Add time since opening
dt_end_open = datetime.datetime(
year=dt_end.year,
month=dt_end.month,
day=dt_end.day,
hour=self.worktiming[0],
minute=0)
worktime_in_seconds += (dt_end-dt_end_open).total_seconds()
return int(worktime_in_seconds / 60)
def is_weekend(self, datetime):
"""
Returns True if datetime lands on a weekend.
"""
for weekend in self.weekends:
if datetime.isoweekday() == weekend:
return True
return False