]> granicus.if.org Git - python/commitdiff
I give up: unless I write my own strftime by hand, datetime just can't
authorTim Peters <tim.peters@gmail.com>
Sun, 22 Dec 2002 20:58:42 +0000 (20:58 +0000)
committerTim Peters <tim.peters@gmail.com>
Sun, 22 Dec 2002 20:58:42 +0000 (20:58 +0000)
be trusted with years before 1900, so now we raise ValueError if a date or
datetime or datetimetz .strftime() method is called with a year before
1900.

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

index ca26872e44abad997c761d1f2237055b00633f9a..6838e4748f1fc45d7c3d52aa38dd43f168ec8502 100644 (file)
@@ -868,6 +868,12 @@ class TestDate(unittest.TestCase):
         self.failUnless(self.theclass.min)
         self.failUnless(self.theclass.max)
 
+    def test_srftime_out_of_range(self):
+        # For nasty technical reasons, we can't handle years before 1900.
+        cls = self.theclass
+        self.assertEqual(cls(1900, 1, 1).strftime("%Y"), "1900")
+        for y in 1, 49, 51, 99, 100, 1000, 1899:
+            self.assertRaises(ValueError, cls(y, 1, 1).strftime, "%Y")
 #############################################################################
 # datetime tests
 
index 28f61bd29db40098a5c30d63a7c54be071144748..a9675d60515f26d1d6487bd2c1fe39aa1248234f 100644 (file)
@@ -940,6 +940,31 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple)
        assert(object && format && timetuple);
        assert(PyString_Check(format));
 
+       /* Give up if the year is before 1900.
+        * Python strftime() plays games with the year, and different
+        * games depending on whether envar PYTHON2K is set.  This makes
+        * years before 1900 a nightmare, even if the platform strftime
+        * supports them (and not all do).
+        * We could get a lot farther here by avoiding Python's strftime
+        * wrapper and calling the C strftime() directly, but that isn't
+        * an option in the Python implementation of this module.
+        */
+       {
+               long year;
+               PyObject *pyyear = PySequence_GetItem(timetuple, 0);
+               if (pyyear == NULL) return NULL;
+               assert(PyInt_Check(pyyear));
+               year = PyInt_AsLong(pyyear);
+               Py_DECREF(pyyear);
+               if (year < 1900) {
+                       PyErr_Format(PyExc_ValueError, "year=%ld is before "
+                                    "1900; the datetime strftime() "
+                                    "methods require year >= 1900",
+                                    year);
+                       return NULL;
+               }
+       }
+
        /* Scan the input format, looking for %z and %Z escapes, building
         * a new format.  Since computing the replacements for those codes
         * is expensive, don't unless they're actually used.