py-business-calendar
py-business-calendar copied to clipboard
bug has been identified.
Hi!
Could you please check why the code below calculates with error:
import business-calendar
cal = Calendar()
date1=datetime.datetime(2017, 1, 20, 14, 43, 45)
date2=datetime.datetime(2017, 1, 28, 14, 40, 45)
print cal.workdaycount(date1, date2)
>>> 0
Hi @lukshap ,
you are right, I've been able to reproduce this error and it affects the busdaycount method too:
import datetime
import business_calendar as bc
cal = bc.Calendar()
date1 = datetime.datetime(2017, 1, 20, 14, 43, 45)
date2 = datetime.datetime(2017, 1, 28, 14, 40, 45)
print(cal.busdaycount(date1, date2))
>>> 0
The issue results from a combination of the facts that
-
date2
is a non-workday (respectively businessday) -
date2
is "ealier" in the day, meaning:date1.hour + 60 * date1.minute + 3600 * date1.second > date2.hour + 60 * date2.minute + 3600 * date2.second
- The following day of
date1
is a non-workday (respectively businessday)
If the following day of date1
would however be a workday (respectively businessday) we would still get an incorrect value as the result would be one less than the correct answer. With the current setup the code subtracts exactly 24 hours from date2
so both days are on a Friday. As we then go mod 7 we get a remainder of 6 for which we then count how often we need to add a workday until both days are the same weekday. However, as both already are fridays this leads to the issue you described.
Anyway, as date1
is observed COB we could simply add
date1 = date1.replace(hour=0, minute=0, second=0)
in the beginning of the _workdaycount
method and would then get:
def _workdaycount(self, date1, date2):`
"""
(PRIVATE) Count work days between two dates, ignoring holidays.
"""
assert date2 >= date1
date1 = date1.replace(hour=0, minute=0, second=0)
date1wd = date1.weekday()
date2wd = date2.weekday()
if not self.weekdaymap[date2wd].isworkday:
date2 += datetime.timedelta(days=self.weekdaymap[date2wd].offsetprev)
date2wd = self.weekdaymap[date2wd].prevworkday
if date2 <= date1:
return 0
nw, nd = divmod((date2 - date1).days, 7)
ndays = nw * len(self.workdays)
if nd > 0:
date1wd = date1.weekday()
date2wd = date2.weekday()
while date1wd != date2wd:
ndays += 1
date1wd = self.weekdaymap[date1wd].nextworkday
return ndays`
This should fix the issue for the _workdaycount
method but I haven't yet come to test this on the busdaycount
method too.
Kind regards