diff options
author | Pieter Eendebak <pieter.eendebak@gmail.com> | 2023-03-20 08:59:59 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-03-20 08:59:59 +0100 |
commit | 1cf882248961a5d411c55d75bff190d7f7eb30e2 (patch) | |
tree | e38f6322e7ab3d5c92c4334d8c62a0e2e96165f5 | |
parent | ee12ff3228d0d800dc25004bc57c78814a48df47 (diff) | |
download | numpy-1cf882248961a5d411c55d75bff190d7f7eb30e2.tar.gz |
BUG: Fix busday_count for reversed dates (#23229)
Fixes #23197
-rw-r--r-- | doc/release/upcoming_changes/23229.compatibility.rst | 3 | ||||
-rw-r--r-- | numpy/core/src/multiarray/datetime_busday.c | 5 | ||||
-rw-r--r-- | numpy/core/tests/test_datetime.py | 24 |
3 files changed, 29 insertions, 3 deletions
diff --git a/doc/release/upcoming_changes/23229.compatibility.rst b/doc/release/upcoming_changes/23229.compatibility.rst new file mode 100644 index 000000000..284cc06ab --- /dev/null +++ b/doc/release/upcoming_changes/23229.compatibility.rst @@ -0,0 +1,3 @@ +- The ``busday_count`` method now correctly handles cases where the ``begindates`` is later in time + than the ``enddates``. Previously, the ``enddates`` was included, even though the documentation states + it is always excluded. diff --git a/numpy/core/src/multiarray/datetime_busday.c b/numpy/core/src/multiarray/datetime_busday.c index d3e9e1451..93ed0972e 100644 --- a/numpy/core/src/multiarray/datetime_busday.c +++ b/numpy/core/src/multiarray/datetime_busday.c @@ -365,6 +365,7 @@ apply_business_day_count(npy_datetime date_begin, npy_datetime date_end, npy_datetime *holidays_begin, npy_datetime *holidays_end) { npy_int64 count, whole_weeks; + int day_of_week = 0; int swapped = 0; @@ -386,6 +387,10 @@ apply_business_day_count(npy_datetime date_begin, npy_datetime date_end, date_begin = date_end; date_end = tmp; swapped = 1; + // we swapped date_begin and date_end, so we need to correct for the + // original date_end that should not be included. gh-23197 + date_begin++; + date_end++; } /* Remove any earlier holidays */ diff --git a/numpy/core/tests/test_datetime.py b/numpy/core/tests/test_datetime.py index 2b56d4824..547ebf9d6 100644 --- a/numpy/core/tests/test_datetime.py +++ b/numpy/core/tests/test_datetime.py @@ -2330,16 +2330,23 @@ class TestDateTime: assert_equal(np.busday_count('2011-01-01', dates, busdaycal=bdd), np.arange(366)) # Returns negative value when reversed + # -1 since the '2011-01-01' is not a busday assert_equal(np.busday_count(dates, '2011-01-01', busdaycal=bdd), - -np.arange(366)) + -np.arange(366) - 1) + # 2011-12-31 is a saturday dates = np.busday_offset('2011-12-31', -np.arange(366), roll='forward', busdaycal=bdd) + # only the first generated date is in the future of 2011-12-31 + expected = np.arange(366) + expected[0] = -1 assert_equal(np.busday_count(dates, '2011-12-31', busdaycal=bdd), - np.arange(366)) + expected) # Returns negative value when reversed + expected = -np.arange(366)+1 + expected[0] = 0 assert_equal(np.busday_count('2011-12-31', dates, busdaycal=bdd), - -np.arange(366)) + expected) # Can't supply both a weekmask/holidays and busdaycal assert_raises(ValueError, np.busday_offset, '2012-01-03', '2012-02-03', @@ -2352,6 +2359,17 @@ class TestDateTime: # Returns negative value when reversed assert_equal(np.busday_count('2011-04', '2011-03', weekmask='Mon'), -4) + sunday = np.datetime64('2023-03-05') + monday = sunday + 1 + friday = sunday + 5 + saturday = sunday + 6 + assert_equal(np.busday_count(sunday, monday), 0) + assert_equal(np.busday_count(monday, sunday), -1) + + assert_equal(np.busday_count(friday, saturday), 1) + assert_equal(np.busday_count(saturday, friday), 0) + + def test_datetime_is_busday(self): holidays = ['2011-01-01', '2011-10-10', '2011-11-11', '2011-11-24', '2011-12-25', '2011-05-30', '2011-02-21', '2011-01-17', |