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.
This commit is contained in:
Alexander Belopolsky 2016-09-27 22:45:20 -04:00
parent 36beb5ec13
commit 8cab419624
3 changed files with 39 additions and 10 deletions

View File

@ -174,22 +174,23 @@ class Calendar(object):
Like itermonthdates(), but will yield (day number, weekday number) Like itermonthdates(), but will yield (day number, weekday number)
tuples. For days outside the specified month the day number is 0. tuples. For days outside the specified month the day number is 0.
""" """
for date in self.itermonthdates(year, month): for i, d in enumerate(self.itermonthdays(year, month), self.firstweekday):
if date.month != month: yield d, i % 7
yield (0, date.weekday())
else:
yield (date.day, date.weekday())
def itermonthdays(self, year, month): def itermonthdays(self, year, month):
""" """
Like itermonthdates(), but will yield day numbers. For days outside Like itermonthdates(), but will yield day numbers. For days outside
the specified month the day number is 0. the specified month the day number is 0.
""" """
for date in self.itermonthdates(year, month): day1, ndays = monthrange(year, month)
if date.month != 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 yield 0
else:
yield date.day
def monthdatescalendar(self, year, month): def monthdatescalendar(self, year, month):
""" """

View File

@ -291,6 +291,27 @@ class CalendarTestCase(unittest.TestCase):
# see #15421 # see #15421
list(calendar.Calendar().itermonthdates(datetime.MAXYEAR, 12)) 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): class MonthCalendarTestCase(unittest.TestCase):
def setUp(self): def setUp(self):

View File

@ -42,6 +42,13 @@ Core and Builtins
Library 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 - Issue #27963: Fixed possible null pointer dereference in
ctypes.set_conversion_mode(). Patch by Xiang Zhang. ctypes.set_conversion_mode(). Patch by Xiang Zhang.