Index: Lib/test/test_time.py =================================================================== --- Lib/test/test_time.py (revision 87811) +++ Lib/test/test_time.py (working copy) @@ -3,6 +3,7 @@ import unittest import locale import sysconfig +import warnings class TimeTestCase(unittest.TestCase): @@ -44,7 +45,7 @@ # Check year [1900, max(int)] self.assertRaises(ValueError, func, - (1899, 1, 1, 0, 0, 0, 0, 1, -1)) + (999, 1, 1, 0, 0, 0, 0, 1, -1)) if time.accept2dyear: self.assertRaises(ValueError, func, (-1, 1, 1, 0, 0, 0, 0, 1, -1)) @@ -97,7 +98,8 @@ # No test for daylight savings since strftime() does not change output # based on its value. expected = "2000 01 01 00 00 00 1 001" - result = time.strftime("%Y %m %d %H %M %S %w %j", (0,)*9) + with support.check_warnings(): + result = time.strftime("%Y %m %d %H %M %S %w %j", (0,)*9) self.assertEqual(expected, result) def test_strptime(self): @@ -274,16 +276,18 @@ time.accept2dyear = self.saved_accept2dyear def yearstr(self, y): - return time.strftime('%Y', (y,) + (0,) * 8) + # return time.strftime('%Y', (y,) + (0,) * 8) + return time.asctime((y,) + (0,) * 8).split()[-1] def test_2dyear(self): - self.assertEqual(self.yearstr(0), '2000') - self.assertEqual(self.yearstr(69), '1969') - self.assertEqual(self.yearstr(68), '2068') - self.assertEqual(self.yearstr(99), '1999') + with support.check_warnings(): + self.assertEqual(self.yearstr(0), '2000') + self.assertEqual(self.yearstr(69), '1969') + self.assertEqual(self.yearstr(68), '2068') + self.assertEqual(self.yearstr(99), '1999') def test_invalid(self): - self.assertRaises(ValueError, self.yearstr, 1899) + self.assertRaises(ValueError, self.yearstr, 999) self.assertRaises(ValueError, self.yearstr, 100) self.assertRaises(ValueError, self.yearstr, -1) @@ -293,11 +297,16 @@ class TestDontAccept2Year(TestAccept2Year): accept2dyear = 0 def test_2dyear(self): - self.assertRaises(ValueError, self.yearstr, 0) - self.assertRaises(ValueError, self.yearstr, 69) - self.assertRaises(ValueError, self.yearstr, 68) - self.assertRaises(ValueError, self.yearstr, 99) + self.assertEqual(self.yearstr(0), '0') + self.assertEqual(self.yearstr(69), '69') + self.assertEqual(self.yearstr(68), '68') + self.assertEqual(self.yearstr(99), '99') + self.assertEqual(self.yearstr(999), '999') + self.assertEqual(self.yearstr(9999), '9999') + def test_invalid(self): + pass + class TestDontAccept2YearBool(TestDontAccept2Year): accept2dyear = False Index: Modules/timemodule.c =================================================================== --- Modules/timemodule.c (revision 87811) +++ Modules/timemodule.c (working copy) @@ -312,35 +312,43 @@ &p->tm_wday, &p->tm_yday, &p->tm_isdst)) return 0; - /* XXX: Why 1900? If the goal is to interpret 2-digit years as those in - * 20th / 21st century according to the POSIX standard, we can just treat - * 0 <= y < 100 as special. Year 100 is probably too ambiguous and should - * be rejected, but years 101 through 1899 can be passed through. + /* If year is specified with less than 4 digits, its interpretation + * depends on the accept2dyear value. + * + * If accept2dyear is true (default), a backward compatibility behavior is + * invoked as follows: + * + * - for 2-digit year, century is guessed according to POSIX rules for + * %y strptime format: 21st century for y < 69, 20th century + * otherwise. A deprecation warning is issued when century + * information is guessed in this way. + * + * - for 3-digit or negative year, a ValueError exception is raised. + * + * If accept2dyear is false (set by the program or as a result of a + * non-empty value assigned to PYTHONY2K environment variable) all year + * values are interpreted as given. */ - if (y < 1900) { + if (y < 1000) { PyObject *accept = PyDict_GetItemString(moddict, "accept2dyear"); int acceptval = accept != NULL && PyObject_IsTrue(accept); if (acceptval == -1) return 0; if (acceptval) { - if (69 <= y && y <= 99) + if (0 <= y && y < 69) + y += 2000; + else if (69 <= y && y < 100) y += 1900; - else if (0 <= y && y <= 68) - y += 2000; else { PyErr_SetString(PyExc_ValueError, "year out of range"); return 0; } + if (PyErr_WarnEx(PyExc_DeprecationWarning, + "Century info guessed for a 2-digit year.", 1) != 0) + return 0; } - /* XXX: When accept2dyear is false, we don't have to reject y < 1900. - * Consider removing the following else-clause. */ - else { - PyErr_SetString(PyExc_ValueError, - "year out of range"); - return 0; - } } p->tm_year = y - 1900; p->tm_mon--;