Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bug has been identified. #3

Open
lukshap opened this issue Jan 28, 2017 · 1 comment
Open

bug has been identified. #3

lukshap opened this issue Jan 28, 2017 · 1 comment

Comments

@lukshap
Copy link

lukshap commented Jan 28, 2017

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

@sevendaybeard
Copy link

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants