Skip to content

Commit

Permalink
just the beginning
Browse files Browse the repository at this point in the history
  • Loading branch information
cadu-leite committed Jun 7, 2020
1 parent a89a09e commit 4ea0477
Show file tree
Hide file tree
Showing 5 changed files with 180 additions and 0 deletions.
Empty file added networkdays/__init__.py
Empty file.
58 changes: 58 additions & 0 deletions networkdays/networkdays.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import datetime


def networkdays(date_start, date_end, holidays=set(), weekdaysoff={6,7}):
'''
NetWorkDays like Excel Networkdays function.
Args:
date_start (datetime.date): initial date
date_end (datetime.date): if none, is the last day of the date_start year.
workdays (set): set (list) of workin days in iso format, Monday is 1 and Sunday is 7.
holidays (set): datetime object set, indicating days off.
weekdaysoff (set): set of weekdays not working, default is saturday and sunday {6,7}.
returns:
set of work days.
ex.:
'''
if len(weekdaysoff) == 0:
weekdaysoff = {6, 7}

date_diff = date_end-date_start
workdays = {
date_start + datetime.timedelta(days=days)
for days in range(0, (date_diff.days+1))
if (date_start + datetime.timedelta(days=days)).isoweekday()
not in weekdaysoff
}

workdays = workdays.difference(holidays)

return workdays


def workdays(duration, workhours, date_start):
'''
list workdays given a number of hours distributed in workdays.
Args:
duration (int/decimal): job duratin on hours
workhours (int/decimal):
date_start
Returns:
set: workday datetime.date list
'''
workdays_number = duration / workhours
r = duration % workhours
if r != 0:
workdays_number += 1

delta = datetime.timedelta(days=workdays_number)
date_end = date_start + delta
workdays = networkdays(date_start, date_end)

return workdays
Empty file added requirements.txt
Empty file.
Empty file added tests/__init__.py
Empty file.
122 changes: 122 additions & 0 deletions tests/test.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import unittest
import datetime

from networkdays.networkdays import networkdays, job_workdays


class TestNetworkDays(unittest.TestCase):

def test_networkdays_calc_days_qtt(self):

number_wds_per_month_2020=[
(datetime.date(2020, 1, 1), datetime.date(2020, 1, 31), 23.00, {}),
(datetime.date(2020, 2, 1), datetime.date(2020, 2, 28), 20.00, {}),
(datetime.date(2020, 3, 1), datetime.date(2020, 3, 31), 22.00, {}),
(datetime.date(2020, 4, 1), datetime.date(2020, 4, 30), 22.00, {}),
(datetime.date(2020, 5, 1), datetime.date(2020, 5, 31), 21.00, {}),
(datetime.date(2020, 6, 1), datetime.date(2020, 6, 30), 22.00, {}),
(datetime.date(2020, 7, 1), datetime.date(2020, 7, 31), 23.00, {}),
(datetime.date(2020, 8, 1), datetime.date(2020, 8, 30), 20.00, {}),
(datetime.date(2020, 9, 1), datetime.date(2020, 9, 30), 22.00, {}),
(datetime.date(2020, 10, 1), datetime.date(2020, 10, 31), 22.00, {}),
(datetime.date(2020, 11, 1), datetime.date(2020, 11, 30), 21.00, {}),
(datetime.date(2020, 12, 1), datetime.date(2020, 12, 31), 23.00, {}),
(datetime.date(2020, 12, 1), datetime.date(2020, 12, 31), 22.00, {
datetime.date(2020, 12, 25), # a holiday
}),
(datetime.date(2020, 8, 1),datetime.date(2020, 8, 30), 19.00, {
datetime.date(2020, 8, 7), datetime.date(2020, 8, 15), # two holidays, but 1 on saturday
}),

]

for date in number_wds_per_month_2020:
with self.subTest(date=date):
workdays = len(networkdays(date[0], date[1], date[3]))
# 2020 Jun, has 22 work days considering no holidays
self.assertEqual(workdays, date[2], msg='fail %s' % (date[0]))

def test_networkdays_calc_days_qtt_workdaysoff(self):
'''
days list with custom days off per week
workdays only sundays + holiday on sunday
November 2020
Mo Tu We Th Fr Sa Su
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
'''
workdays = (
networkdays(
datetime.date(2020, 11, 1),
datetime.date(2020, 11, 30),
[datetime.date(2020, 11, 29), ], {1, 2, 3, 4, 5, 6})
)
self.assertEqual(len(workdays), 4, msg='fail weekdaysoff 1')

def test_job_workdays(self):
'''
November 2020
Mo Tu We Th Fr Sa Su
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
'''
days = job_workdays(8, 8, datetime.date(2020, 11, 1))
duration = len(days)
self.assertEqual(duration, 1, msg='duration 1 fail')

def test_job_workdays_list(self):
'''
A 8 hours workday starting on sunday, but sunday forbidden
'''
day1 = job_workdays(8, 8, datetime.date(2020, 11, 1))
self.assertEqual(day1, {datetime.date(2020, 11, 2)}, msg='day 1')

def test_job_workdays_gt_1(self):
'''
workhours greater then a workday
'''
days = job_workdays(8, 4, datetime.date(2020, 11, 1))
duration = len(days)
self.assertEqual(duration, 2, msg='2 days')

def test_job_workdays_partial_workday(self):
'''
workhours is less then a workday (partial workday)
'''
days = job_workdays(3, 8, datetime.date(2020, 11, 1))
duration = len(days)
self.assertEqual(duration, 1, msg='partial day')

def test_job_workdays_partial_workdays_list(self):
'''
November 2020
Mo Tu We Th Fr Sa Su
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
'''
days = job_workdays(4.5, 1.5, datetime.date(2020, 11, 1))
days_shouldbe = {
datetime.date(2020, 11, 2),
datetime.date(2020, 11, 3),
datetime.date(2020, 11, 4)}
self.assertEqual(
days, days_shouldbe, msg='4.5hs job in 1.5hs workday'
)

def test_job_workdays_partial_workdays_duration(self):
days = job_workdays(8.5, 3.5, datetime.date(2020, 11, 1))
duration = len(days)
self.assertEqual(duration, 3, msg='3 days for 4.5hs job in 1.5hs workday')

0 comments on commit 4ea0477

Please sign in to comment.