]> granicus.if.org Git - python/commitdiff
Merged revisions 81568 via svnmerge from
authorAlexander Belopolsky <alexander.belopolsky@gmail.com>
Thu, 27 May 2010 22:03:53 +0000 (22:03 +0000)
committerAlexander Belopolsky <alexander.belopolsky@gmail.com>
Thu, 27 May 2010 22:03:53 +0000 (22:03 +0000)
svn+ssh://pythondev@svn.python.org/python/branches/py3k

................
  r81568 | alexander.belopolsky | 2010-05-27 17:42:58 -0400 (Thu, 27 May 2010) | 10 lines

  Merged revisions 81566 via svnmerge from
  svn+ssh://pythondev@svn.python.org/python/trunk

  ........
    r81566 | alexander.belopolsky | 2010-05-27 16:55:27 -0400 (Thu, 27 May 2010) | 3 lines

    Issue #7150: Raise OverflowError if the result of adding or subtracting
    timedelta from date or datetime falls outside of the MINYEAR:MAXYEAR range.
  ........
................

Lib/test/test_datetime.py
Misc/NEWS
Modules/datetimemodule.c

index 8bf8420929c94dab84bb523f116bf3fed13c9222..ead8d704d570dd1251c20e554ce2e524fb0b78f0 100644 (file)
@@ -700,15 +700,16 @@ class TestDate(HarmlessMixedComparison, unittest.TestCase):
     def test_overflow(self):
         tiny = self.theclass.resolution
 
-        dt = self.theclass.min + tiny
-        dt -= tiny  # no problem
-        self.assertRaises(OverflowError, dt.__sub__, tiny)
-        self.assertRaises(OverflowError, dt.__add__, -tiny)
-
-        dt = self.theclass.max - tiny
-        dt += tiny  # no problem
-        self.assertRaises(OverflowError, dt.__add__, tiny)
-        self.assertRaises(OverflowError, dt.__sub__, -tiny)
+        for delta in [tiny, timedelta(1), timedelta(2)]:
+            dt = self.theclass.min + delta
+            dt -= delta  # no problem
+            self.assertRaises(OverflowError, dt.__sub__, delta)
+            self.assertRaises(OverflowError, dt.__add__, -delta)
+
+            dt = self.theclass.max - delta
+            dt += delta  # no problem
+            self.assertRaises(OverflowError, dt.__add__, delta)
+            self.assertRaises(OverflowError, dt.__sub__, -delta)
 
     def test_fromtimestamp(self):
         import time
index 5de0ca369582b1d6759a626297efac8e09ba1e8b..3c4aa768662f5c9b78d23c4d3a6233b19417c246 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -54,6 +54,9 @@ C-API
 Library
 -------
 
+- Issue #7150: Raise OverflowError if the result of adding or subtracting
+  timedelta from date or datetime falls outside of the MINYEAR:MAXYEAR range.
+
 - Issue #4769: Fix main() function of the base64 module, use sys.stdin.buffer
   and sys.stdout.buffer (instead of sys.stdin and sys.stdout) to use the bytes
   API
index 6235d6e9729973db06fabbcfe648adc5cd226ba2..419eb7b6d58b16cfcbb29fd47a7ae9bec3b1ceb8 100644 (file)
@@ -30,6 +30,7 @@
 
 #define MINYEAR 1
 #define MAXYEAR 9999
+#define MAXORDINAL 3652059 /* date(9999,12,31).toordinal() */
 
 /* Nine decimal digits is easy to communicate, and leaves enough room
  * so that two delta days can be added w/o fear of overflowing a signed
@@ -480,7 +481,7 @@ normalize_d_s_us(int *d, int *s, int *us)
  * The input values must be such that the internals don't overflow.
  * The way this routine is used, we don't get close.
  */
-static void
+static int
 normalize_y_m_d(int *y, int *m, int *d)
 {
     int dim;            /* # of days in month */
@@ -534,11 +535,23 @@ normalize_y_m_d(int *y, int *m, int *d)
         else {
             int ordinal = ymd_to_ord(*y, *m, 1) +
                                       *d - 1;
-            ord_to_ymd(ordinal, y, m, d);
+            if (ordinal < 1 || ordinal > MAXORDINAL) {
+                goto error;
+            } else {
+                ord_to_ymd(ordinal, y, m, d);
+                return 0;
+            }
         }
     }
     assert(*m > 0);
     assert(*d > 0);
+    if (MINYEAR <= *y && *y <= MAXYEAR)
+        return 0;
+ error:
+    PyErr_SetString(PyExc_OverflowError,
+            "date value out of range");
+    return -1;
+
 }
 
 /* Fiddle out-of-bounds months and days so that the result makes some kind
@@ -548,17 +561,7 @@ normalize_y_m_d(int *y, int *m, int *d)
 static int
 normalize_date(int *year, int *month, int *day)
 {
-    int result;
-
-    normalize_y_m_d(year, month, day);
-    if (MINYEAR <= *year && *year <= MAXYEAR)
-        result = 0;
-    else {
-        PyErr_SetString(PyExc_OverflowError,
-                        "date value out of range");
-        result = -1;
-    }
-    return result;
+    return normalize_y_m_d(year, month, day);
 }
 
 /* Force all the datetime fields into range.  The parameters are both