diff --git a/doc/source/whatsnew/v0.22.0.txt b/doc/source/whatsnew/v0.22.0.txt index ae272282040b8..fd23f0b4335b6 100644 --- a/doc/source/whatsnew/v0.22.0.txt +++ b/doc/source/whatsnew/v0.22.0.txt @@ -264,3 +264,5 @@ Other - Fixed a bug where creating a Series from an array that contains both tz-naive and tz-aware values will result in a Series whose dtype is tz-aware instead of object (:issue:`16406`) - Fixed construction of a :class:`Series` from a ``dict`` containing ``NaN`` as key (:issue:`18480`) - Adding a ``Period`` object to a ``datetime`` or ``Timestamp`` object will now correctly raise a ``TypeError`` (:issue:`17983`) +- Fixed a bug where ``FY5253`` date offsets could incorrectly raise an ``AssertionError`` in arithmetic operatons (:issue:`14774`) +- diff --git a/pandas/tests/tseries/offsets/test_fiscal.py b/pandas/tests/tseries/offsets/test_fiscal.py index 45f12c6931fd9..2dd061dcc6f9e 100644 --- a/pandas/tests/tseries/offsets/test_fiscal.py +++ b/pandas/tests/tseries/offsets/test_fiscal.py @@ -9,6 +9,7 @@ import pandas.util.testing as tm +from pandas import Timestamp from pandas.tseries.frequencies import get_offset, _INVALID_FREQ_ERROR from pandas.tseries.offsets import FY5253Quarter, FY5253 from pandas._libs.tslibs.offsets import WeekDay @@ -604,3 +605,23 @@ def test_offset(self): assert_offset_equal(offset2, datetime(2013, 1, 15), datetime(2013, 3, 30)) + + +def test_bunched_yearends(): + # GH#14774 cases with two fiscal year-ends in the same calendar-year + fy = FY5253(n=1, weekday=5, startingMonth=12, variation='nearest') + dt = Timestamp('2004-01-01') + assert fy.rollback(dt) == Timestamp('2002-12-28') + assert (-fy).apply(dt) == Timestamp('2002-12-28') + assert dt - fy == Timestamp('2002-12-28') + + assert fy.rollforward(dt) == Timestamp('2004-01-03') + assert fy.apply(dt) == Timestamp('2004-01-03') + assert fy + dt == Timestamp('2004-01-03') + assert dt + fy == Timestamp('2004-01-03') + + # Same thing, but starting from a Timestamp in the previous year. + dt = Timestamp('2003-12-31') + assert fy.rollback(dt) == Timestamp('2002-12-28') + assert (-fy).apply(dt) == Timestamp('2002-12-28') + assert dt - fy == Timestamp('2002-12-28') diff --git a/pandas/tseries/offsets.py b/pandas/tseries/offsets.py index 4dae59d11f66f..dd5f01a36a43e 100644 --- a/pandas/tseries/offsets.py +++ b/pandas/tseries/offsets.py @@ -1831,21 +1831,26 @@ def apply(self, other): elif n > 0: if other < prev_year: n -= 2 - # TODO: Not hit in tests - elif other < cur_year: + elif prev_year < other < cur_year: n -= 1 - elif other < next_year: + elif cur_year < other < next_year: pass else: assert False else: - if other > next_year: + if next_year < other: n += 2 - # TODO: Not hit in tests - elif other > cur_year: + # TODO: Not hit in tests; UPDATE: looks impossible + elif cur_year < other < next_year: n += 1 - elif other > prev_year: + elif prev_year < other < cur_year: pass + elif (other.year == prev_year.year and other < prev_year and + prev_year - other <= timedelta(6)): + # GH#14774, error when next_year.year == cur_year.year + # e.g. prev_year == datetime(2004, 1, 3), + # other == datetime(2004, 1, 1) + n -= 1 else: assert False