Skip to content

BUG: busday_count returns wrong results with begindates > enddates #23197

Closed
@eltoder

Description

@eltoder

Describe the issue:

According to the documentation, busday_count

Counts the number of valid days between begindates and enddates, not including the day of enddates. If enddates specifies a date value that is earlier than the corresponding begindates date value, the count will be negative.

However, in the implementation, if begindates is greater than enddates, the dates are swapped and the result is negated. This has the effect of including the enddates and excluding begindates, which contradicts the above spec.

Reproduce the code example:

from datetime import date
import numpy as np

d1 = date(1999, 12, 30)
d2 = date(2000, 1, 1)
assert np.busday_count(d1, d2) == 2   # 1999-12-30 and 1999-12-31
assert np.busday_count(d2, d1) == -1  # 1999-12-31 only, end date is excluded

Error message:

Traceback (most recent call last):
  File "/home/elt/code/numpy-test/busday.py", line 8, in <module>
    assert np.busday_count(d2, d1) == -1
AssertionError

Runtime information:

Output from import sys, numpy; print(numpy.__version__); print(sys.version)

1.24.1
3.10.6 (main, Nov 14 2022, 16:10:14) [GCC 11.3.0]

Output from print(numpy.show_runtime())

[{'simd_extensions': {'baseline': ['SSE', 'SSE2', 'SSE3'],
                      'found': ['SSSE3',
                                'SSE41',
                                'POPCNT',
                                'SSE42',
                                'AVX',
                                'F16C',
                                'FMA3',
                                'AVX2'],
                      'not_found': ['AVX512F',
                                    'AVX512CD',
                                    'AVX512_KNL',
                                    'AVX512_KNM',
                                    'AVX512_SKX',
                                    'AVX512_CLX',
                                    'AVX512_CNL',
                                    'AVX512_ICL']}},
 {'architecture': 'Haswell',
  'filepath': '/home/elt/.local/lib/python3.10/site-packages/numpy.libs/libopenblas64_p-r0-15028c96.3.21.so',
  'internal_api': 'openblas',
  'num_threads': 16,
  'prefix': 'libopenblas',
  'threading_layer': 'pthreads',
  'user_api': 'blas',
  'version': '0.3.21'}]

Context for the issue:

This breaks the invariant that

count = numpy.busday_count(d1, d2)
numpy.busday_offset(d1, count, "forward" if count > 0 else "backward") == d2

for every d1 and every valid d2.

Metadata

Metadata

Assignees

No one assigned

    Labels

    00 - BugtriagedIssue/PR that was discussed in a triage meeting

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions