Commit a6867258 authored by Alexander Belopolsky's avatar Alexander Belopolsky

- time.accept2dyear = True is now equivalent to time.accept2dyear = 1

- removed unnecessary struct_time to tuple conversion
- added more unit tests
(See issue #10827 for discussion.)
parent e40808a9
...@@ -263,8 +263,48 @@ class TestLocale(unittest.TestCase): ...@@ -263,8 +263,48 @@ class TestLocale(unittest.TestCase):
# This should not cause an exception # This should not cause an exception
time.strftime("%B", (2009,2,1,0,0,0,0,0,0)) time.strftime("%B", (2009,2,1,0,0,0,0,0,0))
class TestAccept2Year(unittest.TestCase):
accept2dyear = 1
def setUp(self):
self.saved_accept2dyear = time.accept2dyear
time.accept2dyear = self.accept2dyear
def tearDown(self):
time.accept2dyear = self.saved_accept2dyear
def yearstr(self, y):
return time.strftime('%Y', (y,) + (0,) * 8)
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')
def test_invalid(self):
self.assertRaises(ValueError, self.yearstr, 1899)
self.assertRaises(ValueError, self.yearstr, 100)
self.assertRaises(ValueError, self.yearstr, -1)
class TestAccept2YearBool(TestAccept2Year):
accept2dyear = True
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)
class TestDontAccept2YearBool(TestDontAccept2Year):
accept2dyear = False
def test_main(): def test_main():
support.run_unittest(TimeTestCase, TestLocale) support.run_unittest(TimeTestCase, TestLocale,
TestAccept2Year, TestAccept2YearBool,
TestDontAccept2Year, TestDontAccept2YearBool)
if __name__ == "__main__": if __name__ == "__main__":
test_main() test_main()
...@@ -216,29 +216,6 @@ tmtotuple(struct tm *p) ...@@ -216,29 +216,6 @@ tmtotuple(struct tm *p)
return v; return v;
} }
static PyObject *
structtime_totuple(PyObject *t)
{
PyObject *x = NULL;
unsigned int i;
PyObject *v = PyTuple_New(9);
if (v == NULL)
return NULL;
for (i=0; i<9; i++) {
x = PyStructSequence_GET_ITEM(t, i);
Py_INCREF(x);
PyTuple_SET_ITEM(v, i, x);
}
if (PyErr_Occurred()) {
Py_XDECREF(v);
return NULL;
}
return v;
}
static PyObject * static PyObject *
time_convert(double when, struct tm * (*function)(const time_t *)) time_convert(double when, struct tm * (*function)(const time_t *))
{ {
...@@ -328,9 +305,6 @@ gettmarg(PyObject *args, struct tm *p) ...@@ -328,9 +305,6 @@ gettmarg(PyObject *args, struct tm *p)
t = args; t = args;
Py_INCREF(t); Py_INCREF(t);
} }
else if (Py_TYPE(args) == &StructTimeType) {
t = structtime_totuple(args);
}
else { else {
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
"Tuple or struct_time argument required"); "Tuple or struct_time argument required");
...@@ -352,15 +326,18 @@ gettmarg(PyObject *args, struct tm *p) ...@@ -352,15 +326,18 @@ gettmarg(PyObject *args, struct tm *p)
} }
Py_DECREF(t); Py_DECREF(t);
/* 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 (y < 1900) { if (y < 1900) {
PyObject *accept = PyDict_GetItemString(moddict, PyObject *accept = PyDict_GetItemString(moddict,
"accept2dyear"); "accept2dyear");
if (accept == NULL || !PyLong_CheckExact(accept) || int acceptval = accept != NULL && PyObject_IsTrue(accept);
!PyObject_IsTrue(accept)) { if (acceptval == -1)
PyErr_SetString(PyExc_ValueError,
"year >= 1900 required");
return 0; return 0;
} if (acceptval) {
if (69 <= y && y <= 99) if (69 <= y && y <= 99)
y += 1900; y += 1900;
else if (0 <= y && y <= 68) else if (0 <= y && y <= 68)
...@@ -371,6 +348,14 @@ gettmarg(PyObject *args, struct tm *p) ...@@ -371,6 +348,14 @@ gettmarg(PyObject *args, struct tm *p)
return 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_year = y - 1900;
p->tm_mon--; p->tm_mon--;
p->tm_wday = (p->tm_wday + 1) % 7; p->tm_wday = (p->tm_wday + 1) % 7;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment