Repository: peopledoc/workalendar
Pull request #394 (2019-07-29 08:47:22)

Fix duration calculation with starting day included or not

Querdos: @brunobord up ? :)
brunobord: yes, I saw your PR, but I don't have enough time on my hands to review it right now.
Tomorrow, hopefully :o)
Querdos: @brunobord I understand, when it comes to beaches and sun, it's hard to be in front of a computer haha

So I've made the changes, tell me if it's ok :)

Patch:
diff --git a/Changelog.md b/Changelog.md
index 147d934..8654fa2 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -6,6 +6,7 @@
 
 - Global registry now returns plain built-in dicts (#375).
 - Removed `EphemMixin` in favor of astronomical functions (#302).
+- Added first day counting when computing working_days delta (#393)
 
 ## v5.2.3 (2019-07-11)
 
diff --git a/workalendar/core.py b/workalendar/core.py
index 7c67ade..9ceed3f 100644
--- a/workalendar/core.py
+++ b/workalendar/core.py
@@ -314,7 +314,7 @@ class Calendar(object):
         day = day + timedelta(days=day_delta)
         return day
 
-    def get_working_days_delta(self, start, end):
+    def get_working_days_delta(self, start, end, include_start=False):
         """
         Return the number of working day between two given dates.
         The order of the dates provided doesn't matter.
@@ -335,6 +335,21 @@ class Calendar(object):
 
         This method should even work if your ``start`` and ``end`` arguments
         are datetimes.
+
+        By default, if the day after you start is not a working day,
+        the count will start at 0. If include_start is set to true,
+        this day will be taken into account.
+
+        Example:
+
+        >>> cal = France()
+        >>> day1 = parse('09/05/2018 00:01', dayfirst=True)
+        >>> day2 = parse('10/05/2018 19:01', dayfirst=True) # holiday in france
+        >>> cal.get_working_days_delta(day_1, day_2)
+        0
+
+        >>> cal.get_working_days_delta(day_1, day_2, include_start=True)
+        1
         """
         start = cleaned_date(start)
         end = cleaned_date(end)
@@ -344,8 +359,9 @@ class Calendar(object):
 
         if start > end:
             start, end = end, start
+
         # Starting count here
-        count = 0
+        count = 1 if include_start and self.is_working_day(start) else 0
         while start < end:
             start += timedelta(days=1)
             if self.is_working_day(start):


Test patch:
diff --git a/workalendar/tests/test_core.py b/workalendar/tests/test_core.py
index f1442a3..3863832 100644
--- a/workalendar/tests/test_core.py
+++ b/workalendar/tests/test_core.py
@@ -423,6 +423,20 @@ class WorkingDaysDeltatest(TestCase):
         delta = cal.get_working_days_delta(day2, day1)
         self.assertEqual(delta, 2)
 
+    def test_with_including_first_day(self):
+        # linked to #393
+        cal = MockChristianCalendar()
+        day1 = date(2018, 12, 24)  # December 24th: not holiday so working day
+        day2 = date(2018, 12, 25)  # December 25th: Christmas
+
+        # not including the first day, should return 0
+        delta = cal.get_working_days_delta(day1, day2)
+        self.assertEqual(delta, 0)
+
+        # including the first day, should return 1
+        delta = cal.get_working_days_delta(day1, day2, include_start=True)
+        self.assertEqual(delta, 1)
+
 
 class NoDocstring(Calendar):
     pass