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:
commit
e3fd248c77
|
@ -8,6 +8,7 @@ set the first day of the week (0=Monday, 6=Sunday)."""
|
||||||
import sys
|
import sys
|
||||||
import datetime
|
import datetime
|
||||||
import locale as _locale
|
import locale as _locale
|
||||||
|
from itertools import repeat
|
||||||
|
|
||||||
__all__ = ["IllegalMonthError", "IllegalWeekdayError", "setfirstweekday",
|
__all__ = ["IllegalMonthError", "IllegalWeekdayError", "setfirstweekday",
|
||||||
"firstweekday", "isleap", "leapdays", "weekday", "monthrange",
|
"firstweekday", "isleap", "leapdays", "weekday", "monthrange",
|
||||||
|
@ -176,22 +177,20 @@ 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
|
||||||
yield 0
|
yield from repeat(0, days_before)
|
||||||
else:
|
yield from range(1, ndays + 1)
|
||||||
yield date.day
|
days_after = (self.firstweekday - day1 - ndays) % 7
|
||||||
|
yield from repeat(0, days_after)
|
||||||
|
|
||||||
def monthdatescalendar(self, year, month):
|
def monthdatescalendar(self, year, month):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -502,6 +502,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):
|
||||||
|
|
Loading…
Reference in New Issue