From: Alexander Belopolsky Date: Mon, 2 May 2011 17:14:24 +0000 (-0400) Subject: Issue #11930: Remove year >= 1000 limitation from datetime.strftime. X-Git-Tag: v3.3.0a1~2429 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=89da349b7be56000e4b0efbe11ec4958af691b42;p=python Issue #11930: Remove year >= 1000 limitation from datetime.strftime. Patch by Victor Stinner. --- diff --git a/Doc/library/datetime.rst b/Doc/library/datetime.rst index c637f6a44d..2eb5ea0f1f 100644 --- a/Doc/library/datetime.rst +++ b/Doc/library/datetime.rst @@ -1750,8 +1750,7 @@ format codes. | | decimal number [00,99]. | | +-----------+--------------------------------+-------+ | ``%Y`` | Year with century as a decimal | \(5) | -| | number [0001,9999] (strptime), | | -| | [1000,9999] (strftime). | | +| | number [0001,9999]. | | +-----------+--------------------------------+-------+ | ``%z`` | UTC offset in the form +HHMM | \(6) | | | or -HHMM (empty string if the | | @@ -1785,10 +1784,7 @@ Notes: calculations when the day of the week and the year are specified. (5) - For technical reasons, :meth:`strftime` method does not support - dates before year 1000: ``t.strftime(format)`` will raise a - :exc:`ValueError` when ``t.year < 1000`` even if ``format`` does - not contain ``%Y`` directive. The :meth:`strptime` method can + The :meth:`strptime` method can parse years in the full [1, 9999] range, but years < 1000 must be zero-filled to 4-digit width. diff --git a/Lib/datetime.py b/Lib/datetime.py index 1ae7cb5305..1f8c8f79bd 100644 --- a/Lib/datetime.py +++ b/Lib/datetime.py @@ -172,10 +172,6 @@ def _format_time(hh, mm, ss, us): # Correctly substitute for %z and %Z escapes in strftime formats. def _wrap_strftime(object, format, timetuple): - year = timetuple[0] - if year < 1000: - raise ValueError("year=%d is before 1000; the datetime strftime() " - "methods require year >= 1000" % year) # Don't call utcoffset() or tzname() unless actually needed. freplace = None # the string to use for %f zreplace = None # the string to use for %z diff --git a/Lib/test/datetimetester.py b/Lib/test/datetimetester.py index 38f3b8f19b..4a62bd4a9e 100644 --- a/Lib/test/datetimetester.py +++ b/Lib/test/datetimetester.py @@ -1289,12 +1289,10 @@ class TestDate(HarmlessMixedComparison, unittest.TestCase): self.assertTrue(self.theclass.min) self.assertTrue(self.theclass.max) - def test_strftime_out_of_range(self): - # For nasty technical reasons, we can't handle years before 1000. - cls = self.theclass - self.assertEqual(cls(1000, 1, 1).strftime("%Y"), "1000") - for y in 1, 49, 51, 99, 100, 999: - self.assertRaises(ValueError, cls(y, 1, 1).strftime, "%Y") + def test_strftime_y2k(self): + for y in (1, 49, 70, 99, 100, 999, 1000, 1970): + self.assertEqual(self.theclass(y, 1, 1).strftime("%Y"), + '%04d' % y) def test_replace(self): cls = self.theclass diff --git a/Modules/_datetimemodule.c b/Modules/_datetimemodule.c index a19c0c355b..747be45246 100644 --- a/Modules/_datetimemodule.c +++ b/Modules/_datetimemodule.c @@ -1166,31 +1166,6 @@ wrap_strftime(PyObject *object, PyObject *format, PyObject *timetuple, if (!pin) return NULL; - /* Give up if the year is before 1000. - * Python strftime() plays games with the year, and different - * games depending on whether envar PYTHON2K is set. This makes - * years before 1000 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(PyLong_Check(pyyear)); - year = PyLong_AsLong(pyyear); - Py_DECREF(pyyear); - if (year < 1000) { - PyErr_Format(PyExc_ValueError, "year=%ld is before " - "1000; the datetime strftime() " - "methods require year >= 1000", - year); - return NULL; - } - } - /* Scan the input format, looking for %z/%Z/%f escapes, building * a new format. Since computing the replacements for those codes * is expensive, don't unless they're actually used.