summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Belopolsky <alexander.belopolsky@gmail.com>2016-09-28 02:45:20 (GMT)
committerAlexander Belopolsky <alexander.belopolsky@gmail.com>2016-09-28 02:45:20 (GMT)
commit8cab419624cba0df59fb2d61261a59230ef4578c (patch)
treee6da7918b064fca89d7c5345ebd1e704fd682f9c
parent36beb5ec135142b1e800577be49238bf767f4a79 (diff)
downloadcpython-8cab419624cba0df59fb2d61261a59230ef4578c.zip
cpython-8cab419624cba0df59fb2d61261a59230ef4578c.tar.gz
cpython-8cab419624cba0df59fb2d61261a59230ef4578c.tar.bz2
Issue #28253: Fixed calendar functions for extreme months: 0001-01 and 9999-12.
Methods itermonthdays() and itermonthdays2() are reimplemented so that they don't call itermonthdates() which can cause datetime.date under/overflow.
-rw-r--r--Lib/calendar.py21
-rw-r--r--Lib/test/test_calendar.py21
-rw-r--r--Misc/NEWS7
3 files changed, 39 insertions, 10 deletions
diff --git a/Lib/calendar.py b/Lib/calendar.py
index 4c95a49..8fcceb7 100644
--- a/Lib/calendar.py
+++ b/Lib/calendar.py
@@ -174,22 +174,23 @@ class Calendar(object):
Like itermonthdates(), but will yield (day number, weekday number)
tuples. For days outside the specified month the day number is 0.
"""
- for date in self.itermonthdates(year, month):
- if date.month != month:
- yield (0, date.weekday())
- else:
- yield (date.day, date.weekday())
+ for i, d in enumerate(self.itermonthdays(year, month), self.firstweekday):
+ yield d, i % 7
def itermonthdays(self, year, month):
"""
Like itermonthdates(), but will yield day numbers. For days outside
the specified month the day number is 0.
"""
- for date in self.itermonthdates(year, month):
- if date.month != month:
- yield 0
- else:
- yield date.day
+ day1, ndays = monthrange(year, month)
+ days_before = (day1 - self.firstweekday) % 7
+ for _ in range(days_before):
+ yield 0
+ for d in range(1, ndays + 1):
+ yield d
+ days_after = (self.firstweekday - day1 - ndays) % 7
+ for _ in range(days_after):
+ yield 0
def monthdatescalendar(self, year, month):
"""
diff --git a/Lib/test/test_calendar.py b/Lib/test/test_calendar.py
index 46c4a6f..b87b04f 100644
--- a/Lib/test/test_calendar.py
+++ b/Lib/test/test_calendar.py
@@ -291,6 +291,27 @@ class CalendarTestCase(unittest.TestCase):
# see #15421
list(calendar.Calendar().itermonthdates(datetime.MAXYEAR, 12))
+ def test_itermonthdays(self):
+ for firstweekday in range(7):
+ cal = calendar.Calendar(firstweekday)
+ # Test the extremes, see #28253 and #26650
+ for y, m in [(1, 1), (9999, 12)]:
+ days = list(cal.itermonthdays(y, m))
+ self.assertIn(len(days), (35, 42))
+ # Test a short month
+ cal = calendar.Calendar(firstweekday=3)
+ days = list(cal.itermonthdays(2001, 2))
+ self.assertEqual(days, list(range(1, 29)))
+
+ def test_itermonthdays2(self):
+ for firstweekday in range(7):
+ cal = calendar.Calendar(firstweekday)
+ # Test the extremes, see #28253 and #26650
+ for y, m in [(1, 1), (9999, 12)]:
+ days = list(cal.itermonthdays2(y, m))
+ self.assertEqual(days[0][1], firstweekday)
+ self.assertEqual(days[-1][1], (firstweekday - 1) % 7)
+
class MonthCalendarTestCase(unittest.TestCase):
def setUp(self):
diff --git a/Misc/NEWS b/Misc/NEWS
index 4399985..a8e27b7 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -42,6 +42,13 @@ Core and Builtins
Library
-------
+- Issue #28253: Fixed calendar functions for extreme months: 0001-01
+ and 9999-12.
+
+ Methods itermonthdays() and itermonthdays2() are reimplemented so
+ that they don't call itermonthdates() which can cause datetime.date
+ under/overflow.
+
- Issue #27963: Fixed possible null pointer dereference in
ctypes.set_conversion_mode(). Patch by Xiang Zhang.