Initial import.

This commit is contained in:
2014-02-19 22:45:10 +00:00
commit 0a41fa3e4d
8 changed files with 92 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
.idea
.pyc
build/
dist/

0
LICENSE Normal file
View File

0
README.md Normal file
View File

View File

@@ -0,0 +1 @@
from .core import calc_business_hours

50
businesshours/core.py Normal file
View File

@@ -0,0 +1,50 @@
from datetime import datetime, timedelta, time
def calc_business_hours(start, end, weekdays=(1, 2, 3, 4, 5), hours=range(8, 18)):
"""Calculates the number of seconds hours between two dates"""
def date_range(start_date, end_date):
"""Converts two datetimes into a list of dates between them"""
if isinstance(start_date, datetime):
start_date = start_date.date()
if isinstance(end_date, datetime):
end_date = end_date.date()
if start_date > end_date:
raise ValueError('You provided a start_date that comes after the end_date.')
while True:
yield start_date
start_date = start_date + timedelta(days=1)
if start_date > end_date:
break
if start.date() == end.date():
if not start.date().isoweekday() in weekdays:
return 0
if start.time().hour in hours:
actual_start = start
else:
if start.time().hour >= hours[-1] + 1:
return 0
actual_start = datetime.combine(start.date(), time(hours[0], 0, 0))
if end.time().hour in hours:
actual_end = end
else:
if end.time().hour <= hours[0]:
return 0
actual_end = datetime.combine(end.date(), time(hours[-1] + 1, 0, 0))
secs = (actual_end - actual_start).total_seconds()
return secs
else:
total_seconds = 0
dates = [dt for dt in date_range(start, end)]
for idx, dt in enumerate(dates):
day_start = datetime.combine(dt, time(0, 0, 0))
day_end = datetime.combine(dt, time(23, 59, 59))
if idx == 0:
day_start = start
if idx == len(dates) - 1:
day_end = end
total_seconds += calc_business_hours(day_start, day_end, weekdays, hours)
return total_seconds

View File

@@ -0,0 +1 @@
__author__ = 'nikdoof'

View File

@@ -0,0 +1,36 @@
from datetime import datetime
import unittest
from businesshours import calc_business_hours
class TestCalcBusinessHours(unittest.TestCase):
def run_tests(self, tests):
for res, dt1, dt2 in tests:
self.assertEqual(calc_business_hours(dt1, dt2,), res)
def test_invalid_arguments(self):
self.assertRaises(ValueError, calc_business_hours, datetime(2014,1,2), datetime(2014,1,1))
def test_simple_day(self):
self.run_tests([
(60, datetime(2013, 8, 1, 9, 0, 0), datetime(2013, 8, 1, 9, 1, 0)),
(600, datetime(2013, 8, 1, 9, 0, 0), datetime(2013, 8, 1, 9, 10, 0)), # Simple multiday
(36000, datetime(2013, 8, 1, 9, 0, 0), datetime(2013, 8, 2, 9, 0, 0)),
(72000, datetime(2013, 8, 5, 9, 0, 0), datetime(2013, 8, 7, 9, 0, 0)),
])
def test_multiday_out_of_hours(self):
self.run_tests([
(68400, datetime(2013, 8, 5, 9, 0, 0), datetime(2013, 8, 7, 0, 1, 0)),
(72000, datetime(2013, 8, 5, 7, 0, 0), datetime(2013, 8, 7, 8, 0, 0)),
(72000, datetime(2013, 8, 5, 6, 0, 0), datetime(2013, 8, 7, 8, 0, 0)),
])
def test_weekend_single_day(self):
self.run_tests([
(0, datetime(2013, 8, 24, 9, 0, 0), datetime(2013, 8, 24, 9, 1, 0)),
(0, datetime(2013, 8, 25, 9, 0, 0), datetime(2013, 8, 25, 9, 10, 0)), # Multiday during weekend
(0, datetime(2013, 8, 3, 7, 0, 0), datetime(2013, 8, 4, 9, 0, 0)),
])

0
setup.py Normal file
View File