Repository: peopledoc/workalendar
Pull request #640 (2021-03-12 16:31:25)

Bugfix: `get_working_days_delta` method to integrate the `extra_holidays` and `extra_working_days` args
refs #631
- [x] Tests with a significant number of years to be tested for your calendar.
- [x] Changelog amended with a mention describing your changes. **Note** *Please do NOT change the version number here. It's the project maintainers' duty.*



Patch:
diff --git a/Changelog.md b/Changelog.md
index ff8eff4..f90cd97 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -3,6 +3,7 @@
 ## master (unreleased)
 
 - Bugfix: Bulgaria holidays are now computed using the Orthodox calendar, include shifting rules for holidays that fall on a week-end (#596).
+- Bugfix: `get_working_days_delta` method to integrate the `extra_holidays` and `extra_working_days` args (#631).
 
 ## v15.0.2 (2021-03-05)
 
diff --git a/workalendar/core.py b/workalendar/core.py
index 2dd6d4e..b8bd480 100644
--- a/workalendar/core.py
+++ b/workalendar/core.py
@@ -812,7 +812,8 @@ class CoreCalendar:
         day = day + timedelta(days=day_delta)
         return day
 
-    def get_working_days_delta(self, start, end, include_start=False):
+    def get_working_days_delta(self, start, end, include_start=False,
+                               extra_working_days=None, extra_holidays=None):
         """
         Return the number of working day between two given dates.
         The order of the dates provided doesn't matter.
@@ -840,14 +841,18 @@ class CoreCalendar:
 
         Example:
 
+        >>> from dateutil.parser import parse
         >>> 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)
+        >>> cal.get_working_days_delta(day1, day2)
         0
 
-        >>> cal.get_working_days_delta(day_1, day_2, include_start=True)
+        >>> cal.get_working_days_delta(day1, day2, include_start=True)
         1
+
+        As in many other methods, you can use the ``extra_holidays`` and
+        ``extra_working_days`` to exclude
         """
         start = cleaned_date(start)
         end = cleaned_date(end)
@@ -859,10 +864,20 @@ class CoreCalendar:
             start, end = end, start
 
         # Starting count here
-        count = 1 if include_start and self.is_working_day(start) else 0
+        is_working_day = self.is_working_day(
+            start,
+            extra_working_days=extra_working_days,
+            extra_holidays=extra_holidays
+        )
+        count = 1 if include_start and is_working_day else 0
         while start < end:
             start += timedelta(days=1)
-            if self.is_working_day(start):
+            is_working_day = self.is_working_day(
+                start,
+                extra_working_days=extra_working_days,
+                extra_holidays=extra_holidays
+            )
+            if is_working_day:
                 count += 1
         return count
 


Test patch:
diff --git a/workalendar/tests/test_core.py b/workalendar/tests/test_core.py
index 3094902..1066c29 100644
--- a/workalendar/tests/test_core.py
+++ b/workalendar/tests/test_core.py
@@ -516,6 +516,61 @@ class WorkingDaysDeltatest(TestCase):
         delta = cal.get_working_days_delta(day1, day2, include_start=True)
         self.assertEqual(delta, 1)
 
+    def test_use_extra_working_days(self):
+        cal = MockChristianCalendar()
+        day1 = date(2018, 12, 21)
+        day2 = date(2018, 12, 26)
+        delta = cal.get_working_days_delta(
+            day1, day2,
+            extra_working_days=[date(2018, 12, 25)]
+        )
+        # there are 3 days, because of the week-end
+        # and Christmas Day is a working day
+        self.assertEqual(delta, 3)
+
+        # No difference if you swap the two dates
+        delta = cal.get_working_days_delta(
+            day2, day1,
+            extra_working_days=[date(2018, 12, 25)])
+        self.assertEqual(delta, 3)
+
+    def test_use_extra_holidays(self):
+        cal = MockChristianCalendar()
+        day1 = date(2018, 12, 21)
+        day2 = date(2018, 12, 26)
+        delta = cal.get_working_days_delta(
+            day1, day2,
+            extra_holidays=[date(2018, 12, 24)]
+        )
+        # Only 1 day, because of the week-end + XMas + XMas Eve
+        self.assertEqual(delta, 1)
+
+        # No difference if you swap the two dates
+        delta = cal.get_working_days_delta(
+            day2, day1,
+            extra_holidays=[date(2018, 12, 24)])
+        self.assertEqual(delta, 1)
+
+    def test_use_both_extra(self):
+        cal = MockChristianCalendar()
+        day1 = date(2018, 12, 21)
+        day2 = date(2018, 12, 26)
+        delta = cal.get_working_days_delta(
+            day1, day2,
+            extra_working_days=[date(2018, 12, 25)],
+            extra_holidays=[date(2018, 12, 24)]
+        )
+        # Only 1 day, because of the week-end + XMas Eve
+        # And Christmas is a working day
+        self.assertEqual(delta, 2)
+
+        # No difference if you swap the two dates
+        delta = cal.get_working_days_delta(
+            day2, day1,
+            extra_working_days=[date(2018, 12, 25)],
+            extra_holidays=[date(2018, 12, 24)])
+        self.assertEqual(delta, 2)
+
 
 class NoDocstring(Calendar):
     pass