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 fixes for date_range boundaries #56156

Closed
wants to merge 9 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions doc/source/whatsnew/v2.2.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -892,6 +892,8 @@ Other
- Bug in :func:`DataFrame.describe` when formatting percentiles in the resulting percentile 99.999% is rounded to 100% (:issue:`55765`)
- Bug in :func:`cut` and :func:`qcut` with ``datetime64`` dtype values with non-nanosecond units incorrectly returning nanosecond-unit bins (:issue:`56101`)
- Bug in :func:`cut` incorrectly allowing cutting of timezone-aware datetimes with timezone-naive bins (:issue:`54964`)
- Bug in :func:`date_range` where a timestamp out of the valid range would be produced with a negative ``freq`` parameter (:issue:`56147`)
- Bug in :func:`date_range` where the last valid timestamp would sometimes not be produced (:issue:`56134`)
- Bug in :func:`infer_freq` and :meth:`DatetimeIndex.inferred_freq` with weekly frequencies and non-nanosecond resolutions (:issue:`55609`)
- Bug in :meth:`DataFrame.apply` where passing ``raw=True`` ignored ``args`` passed to the applied function (:issue:`55009`)
- Bug in :meth:`DataFrame.from_dict` which would always sort the rows of the created :class:`DataFrame`. (:issue:`55683`)
Expand Down
10 changes: 5 additions & 5 deletions pandas/core/arrays/datetimes.py
Original file line number Diff line number Diff line change
Expand Up @@ -2763,12 +2763,12 @@ def _generate_range(
if start and not offset.is_on_offset(start):
# Incompatible types in assignment (expression has type "datetime",
# variable has type "Optional[Timestamp]")
start = offset.rollforward(start) # type: ignore[assignment]

elif end and not offset.is_on_offset(end):
# Incompatible types in assignment (expression has type "datetime",
# variable has type "Optional[Timestamp]")
end = offset.rollback(end) # type: ignore[assignment]
# GH #56147 account for negative direction and range bounds
if offset.n >= 0:
start = offset.rollforward(start) # type: ignore[assignment]
else:
start = offset.rollback(start) # type: ignore[assignment]

# Unsupported operand types for < ("Timestamp" and "None")
if periods is None and end < start and offset.n >= 0: # type: ignore[operator]
Expand Down
30 changes: 30 additions & 0 deletions pandas/tests/indexes/datetimes/test_date_range.py
Original file line number Diff line number Diff line change
Expand Up @@ -1539,6 +1539,21 @@ def test_date_range_year_end(self, unit):
)
tm.assert_index_equal(rng, exp)

def test_date_range_partial_day_year_end(self, unit):
# GH#56134
rng = date_range(
start="2021-12-31 00:00:01",
end="2023-10-31 00:00:00",
freq="YE",
unit=unit,
)
exp = DatetimeIndex(
["2021-12-31 00:00:01", "2022-12-31 00:00:01"],
dtype=f"M8[{unit}]",
freq="YE",
)
tm.assert_index_equal(rng, exp)

def test_date_range_negative_freq_year_end(self, unit):
# GH#11018
rng = date_range("2011-12-31", freq="-2YE", periods=3, unit=unit)
Expand All @@ -1548,6 +1563,21 @@ def test_date_range_negative_freq_year_end(self, unit):
tm.assert_index_equal(rng, exp)
assert rng.freq == "-2YE"

def test_date_range_negative_freq_year_end_inbounds(self, unit):
# GH#56147
rng = date_range(
start="2023-10-31 00:00:00",
end="2021-10-31 00:00:00",
freq="-1YE",
unit=unit,
)
exp = DatetimeIndex(
["2022-12-31 00:00:00", "2021-12-31 00:00:00"],
dtype=f"M8[{unit}]",
freq="-1YE",
)
tm.assert_index_equal(rng, exp)

def test_date_range_business_year_end_year(self, unit):
# see GH#9313
rng = date_range("1/1/2013", "7/1/2017", freq="BYE", unit=unit)
Expand Down
Loading