From 83ec82cb5e032ab31e5aae49902cf61be38ddfc2 Mon Sep 17 00:00:00 2001 From: Aleksei Strizhak Date: Tue, 12 Oct 2021 14:58:53 +0500 Subject: [PATCH] Document behavior when time delta addition falls after end of month Document potentially surprising behaviour and add tests to cover these cases. --- AUTHORS.md | 1 + changelog.d/1167.doc.rst | 3 ++ docs/relativedelta.rst | 9 ++++++ tests/test_relativedelta.py | 61 +++++++++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+) create mode 100644 changelog.d/1167.doc.rst diff --git a/AUTHORS.md b/AUTHORS.md index fa9184207..84b92a36f 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -15,6 +15,7 @@ switch, and thus all their contributions are dual-licensed. - Adrien Cossa - Alec Nikolas Reiter - Alec Reiter +- Aleksei Strizhak (gh: @Mifrill) - Alex Chamberlain (gh: @alexchamberlain) **D** - Alex Verdyan - Alex Willmer (gh: @moreati) **R** diff --git a/changelog.d/1167.doc.rst b/changelog.d/1167.doc.rst new file mode 100644 index 000000000..36def3b50 --- /dev/null +++ b/changelog.d/1167.doc.rst @@ -0,0 +1,3 @@ +Added note into docs and tests where relativedelta would return last day of the month +only if the same day on a different month resolves to a date that doesn't exist. +Reported by @hawkEye-01 (gh issue #1167). Fixed by @Mifrill (gh pr #1168) \ No newline at end of file diff --git a/docs/relativedelta.rst b/docs/relativedelta.rst index 0899f34e1..e2994d2c3 100644 --- a/docs/relativedelta.rst +++ b/docs/relativedelta.rst @@ -91,6 +91,15 @@ boundary. The logic for years is the same, even on leap years. +If the result falls on a day after the last one of the month, the last day of the month is used instead. + +.. doctest:: + + >>> date(2003,1,30)+relativedelta(months=+1) + datetime.date(2003, 2, 28) + >>> date(2003,5,31)+relativedelta(months=-1) + datetime.date(2003, 4, 30) + .. doctest:: relativedelta >>> date(2000,2,28)+relativedelta(years=+1) diff --git a/tests/test_relativedelta.py b/tests/test_relativedelta.py index 1e5d17044..5204c293b 100644 --- a/tests/test_relativedelta.py +++ b/tests/test_relativedelta.py @@ -650,6 +650,67 @@ def testHashable(self): except: self.fail("relativedelta() failed to hash!") + def testDayOfMonthPlus(self): + assert [ + date(2021, 1, 28) + relativedelta(months=1), + date(2021, 2, 27) + relativedelta(months=1), + date(2021, 4, 29) + relativedelta(months=1), + date(2021, 5, 30) + relativedelta(months=1), + ] == [ + date(2021, 2, 28), + date(2021, 3, 27), + date(2021, 5, 29), + date(2021, 6, 30), + ] + + def testLastDayOfMonthPlus(self): + assert [ + date(2021, 1, 31) + relativedelta(months=1), + date(2021, 1, 30) + relativedelta(months=1), + date(2021, 1, 29) + relativedelta(months=1), + date(2021, 1, 28) + relativedelta(months=1), + date(2021, 2, 28) + relativedelta(months=1), + date(2021, 4, 30) + relativedelta(months=1), + date(2021, 5, 31) + relativedelta(months=1), + ] == [ + date(2021, 2, 28), + date(2021, 2, 28), + date(2021, 2, 28), + date(2021, 2, 28), + date(2021, 3, 28), + date(2021, 5, 30), + date(2021, 6, 30), + ] + + def testDayOfMonthMinus(self): + assert [ + date(2021, 2, 27) - relativedelta(months=1), + date(2021, 3, 30) - relativedelta(months=1), + date(2021, 3, 29) - relativedelta(months=1), + date(2021, 3, 28) - relativedelta(months=1), + date(2021, 5, 30) - relativedelta(months=1), + date(2021, 6, 29) - relativedelta(months=1), + ] == [ + date(2021, 1, 27), + date(2021, 2, 28), + date(2021, 2, 28), + date(2021, 2, 28), + date(2021, 4, 30), + date(2021, 5, 29), + ] + + def testLastDayOfMonthMinus(self): + assert [ + date(2021, 2, 28) - relativedelta(months=1), + date(2021, 3, 31) - relativedelta(months=1), + date(2021, 5, 31) - relativedelta(months=1), + date(2021, 6, 30) - relativedelta(months=1), + ] == [ + date(2021, 1, 28), + date(2021, 2, 28), + date(2021, 4, 30), + date(2021, 5, 30), + ] class RelativeDeltaWeeksPropertyGetterTest(unittest.TestCase): """Test the weeks property getter"""