Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e3fd248

Browse files
committed
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.
2 parents 6703e04 + 957b756 commit e3fd248

2 files changed

Lines changed: 30 additions & 10 deletions

File tree

Lib/calendar.py

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import sys
99
import datetime
1010
import locale as _locale
11+
from itertools import repeat
1112

1213
__all__ = ["IllegalMonthError", "IllegalWeekdayError", "setfirstweekday",
1314
"firstweekday", "isleap", "leapdays", "weekday", "monthrange",
@@ -176,22 +177,20 @@ def itermonthdays2(self, year, month):
176177
Like itermonthdates(), but will yield (day number, weekday number)
177178
tuples. For days outside the specified month the day number is 0.
178179
"""
179-
for date in self.itermonthdates(year, month):
180-
if date.month != month:
181-
yield (0, date.weekday())
182-
else:
183-
yield (date.day, date.weekday())
180+
for i, d in enumerate(self.itermonthdays(year, month), self.firstweekday):
181+
yield d, i % 7
184182

185183
def itermonthdays(self, year, month):
186184
"""
187185
Like itermonthdates(), but will yield day numbers. For days outside
188186
the specified month the day number is 0.
189187
"""
190-
for date in self.itermonthdates(year, month):
191-
if date.month != month:
192-
yield 0
193-
else:
194-
yield date.day
188+
day1, ndays = monthrange(year, month)
189+
days_before = (day1 - self.firstweekday) % 7
190+
yield from repeat(0, days_before)
191+
yield from range(1, ndays + 1)
192+
days_after = (self.firstweekday - day1 - ndays) % 7
193+
yield from repeat(0, days_after)
195194

196195
def monthdatescalendar(self, year, month):
197196
"""

Lib/test/test_calendar.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -502,6 +502,27 @@ def test_itermonthdates(self):
502502
# see #15421
503503
list(calendar.Calendar().itermonthdates(datetime.MAXYEAR, 12))
504504

505+
def test_itermonthdays(self):
506+
for firstweekday in range(7):
507+
cal = calendar.Calendar(firstweekday)
508+
# Test the extremes, see #28253 and #26650
509+
for y, m in [(1, 1), (9999, 12)]:
510+
days = list(cal.itermonthdays(y, m))
511+
self.assertIn(len(days), (35, 42))
512+
# Test a short month
513+
cal = calendar.Calendar(firstweekday=3)
514+
days = list(cal.itermonthdays(2001, 2))
515+
self.assertEqual(days, list(range(1, 29)))
516+
517+
def test_itermonthdays2(self):
518+
for firstweekday in range(7):
519+
cal = calendar.Calendar(firstweekday)
520+
# Test the extremes, see #28253 and #26650
521+
for y, m in [(1, 1), (9999, 12)]:
522+
days = list(cal.itermonthdays2(y, m))
523+
self.assertEqual(days[0][1], firstweekday)
524+
self.assertEqual(days[-1][1], (firstweekday - 1) % 7)
525+
505526

506527
class MonthCalendarTestCase(unittest.TestCase):
507528
def setUp(self):

0 commit comments

Comments
 (0)