Issue #11930: Remove year >= 1000 limitation from datetime.strftime.
Patch by Victor Stinner.
This commit is contained in:
parent
9d8c3b7cef
commit
89da349b7b
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue