]> granicus.if.org Git - python/commitdiff
Issue #28253: Fixed calendar functions for extreme months: 0001-01 and 9999-12.
authorAlexander Belopolsky <alexander.belopolsky@gmail.com>
Wed, 28 Sep 2016 02:45:20 +0000 (22:45 -0400)
committerAlexander Belopolsky <alexander.belopolsky@gmail.com>
Wed, 28 Sep 2016 02:45:20 +0000 (22:45 -0400)
Methods itermonthdays() and itermonthdays2() are reimplemented so that they
don't call itermonthdates() which can cause datetime.date under/overflow.

Lib/calendar.py
Lib/test/test_calendar.py
Misc/NEWS

index 4c95a493474014fd0f6588f8976b6dfa00bb880f..8fcceb7fb76fb7c230d3ac301bbfff94d5f6e7d1 100644 (file)
@@ -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):
         """
index 46c4a6fe3b31f2dbe3ff72be83f258b4cb9b7557..b87b04fd6706bd4737bb389d32401e69c1efc22c 100644 (file)
@@ -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):
index 43999858c98b7a767c51b12fcae9aa7113c5ef07..a8e27b710fc8726ebd493da63198f145238a4b71 100644 (file)
--- 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.