Index: Doc/library/datetime.rst =================================================================== --- Doc/library/datetime.rst (revision 81859) +++ Doc/library/datetime.rst (working copy) @@ -381,6 +381,17 @@ d``. +.. method:: date.strptime(date_string, format) + + Return a :class:`date` corresponding to *date_string*, parsed according to + *format*. This is equivalent to ``date(*(time.strptime(date_string, + format)[0:3]))``. :exc:`ValueError` is raised if the date string and + format can't be parsed by `time.strptime`, or if it returns a value where + the time part is nonzero. + + .. versionadded:: 3.2 + + Class attributes: .. attribute:: date.min @@ -715,7 +726,7 @@ Return a :class:`datetime` corresponding to *date_string*, parsed according to *format*. This is equivalent to ``datetime(*(time.strptime(date_string, format)[0:6]))``. :exc:`ValueError` is raised if the date_string and format - can't be parsed by :func:`time.strptime` or if it returns a value which isn't a + cannot be parsed by :func:`time.strptime` or if it returns a value which isn't a time tuple. See section :ref:`strftime-strptime-behavior`. @@ -1162,9 +1173,22 @@ If an argument outside those ranges is given, :exc:`ValueError` is raised. All default to ``0`` except *tzinfo*, which defaults to :const:`None`. + +Other constructors, all class methods: + +.. method:: time.strptime(time_string, format) + + Return a :class:`time` corresponding to *time_string*, parsed according to + *format*. This is equivalent to ``time(*(time.strptime(time_string, + format)[4:7]))``. :exc:`ValueError` is raised if the time string and + format cannot be parsed by `time.strptime`, or if it returns a value with + non-default values for the date part. + + .. versionadded:: 3.2 + + Class attributes: - .. attribute:: time.min The earliest representable :class:`time`, ``time(0, 0, 0, 0)``. Index: Lib/test/test_datetime.py =================================================================== --- Lib/test/test_datetime.py (revision 81859) +++ Lib/test/test_datetime.py (working copy) @@ -614,6 +614,20 @@ dt2 = dt - delta self.assertEqual(dt2, dt - days) + def test_strptime(self): + import _strptime + + string = '2004-12-01 13:02:47.197' + format = '%Y-%m-%d %H:%M:%S.%f' + self.assertRaises(ValueError, date.strptime, string, format) + + string = '2004-12-01' + format = '%Y-%m-%d' + result, frac = _strptime._strptime(string, format) + expected = date(*(result[0:3])) + got = date.strptime(string, format) + self.assertEqual(expected, got) + class SubclassDate(date): sub_var = 1 @@ -1941,6 +1955,20 @@ # A naive object replaces %z and %Z with empty strings. self.assertEqual(t.strftime("'%z' '%Z'"), "'' ''") + def test_strptime(self): + import _strptime + + string = '2004-12-01 13:02:47.197' + format = '%Y-%m-%d %H:%M:%S.%f' + self.assertRaises(ValueError, self.theclass.strptime, string, format) + + string = '13:02:47.197' + format = '%H:%M:%S.%f' + result, frac = _strptime._strptime(string, format) + expected = self.theclass(*(result[3:6] + (frac,))) + got = self.theclass.strptime(string, format) + self.assertEqual(expected, got) + def test_format(self): t = self.theclass(1, 2, 3, 4) self.assertEqual(t.__format__(''), str(t)) Index: Modules/datetimemodule.c =================================================================== --- Modules/datetimemodule.c (revision 81859) +++ Modules/datetimemodule.c (working copy) @@ -102,6 +102,9 @@ static PyTypeObject PyDateTime_DeltaType; static PyTypeObject PyDateTime_TimeType; static PyTypeObject PyDateTime_TZInfoType; +static PyObject *datetime_strptime(PyObject *cls, PyObject *args); +static PyObject *datetime_getdate(PyDateTime_DateTime *self); +static PyObject *datetime_gettime(PyDateTime_DateTime *self); /* --------------------------------------------------------------------------- * Math utilities. @@ -2616,6 +2619,31 @@ return result; } +/* Return new date from time.strptime(). */ +static PyObject * +date_strptime(PyObject *cls, PyObject *args) +{ + PyObject *date = NULL; + PyObject *datetime; + + datetime = datetime_strptime((PyObject *)&PyDateTime_DateTimeType, args); + + if (datetime == NULL) + return NULL; + + if (DATE_GET_HOUR(datetime) || + DATE_GET_MINUTE(datetime) || + DATE_GET_SECOND(datetime) || + DATE_GET_MICROSECOND(datetime)) + PyErr_SetString(PyExc_ValueError, + "date.strptime value cannot have a time part"); + else + date = datetime_getdate((PyDateTime_DateTime *)datetime); + + Py_DECREF(datetime); + return date; +} + /* * Date arithmetic. */ @@ -2929,6 +2957,10 @@ PyDoc_STR("Current date or datetime: same as " "self.__class__.fromtimestamp(time.time()).")}, + {"strptime", (PyCFunction)date_strptime, METH_VARARGS | METH_CLASS, + PyDoc_STR("string, format -> new date parsed from a string " + "(like time.strptime()).")}, + /* Instance methods: */ {"ctime", (PyCFunction)date_ctime, METH_NOARGS, @@ -3397,6 +3429,38 @@ return self; } +/* Return new time from time.strptime(). */ +static PyObject * +time_strptime(PyObject *cls, PyObject *args) +{ + PyObject *time = NULL; + PyObject *datetime; + + static PyObject *emptyDatetime = NULL; + + datetime = datetime_strptime( + (PyObject *)&PyDateTime_DateTimeType, + args); + + if (datetime == NULL) + return NULL; + + /* To ensure that the given string does not contain a date, + * compare date fields with the default values. XXX: This will + * still allow parsing of '1900' for '%Y', '01' for '%m' etc. + */ + if (GET_YEAR(datetime) != 1900 || + GET_MONTH(datetime) != 1 || + GET_DAY(datetime) != 1) + PyErr_SetString(PyExc_ValueError, + "time.strptime value cannot have a date part"); + else + time = datetime_gettime((PyDateTime_DateTime *)datetime); + + Py_DECREF(datetime); + return time; +} + /* * Destructor. */ @@ -3709,6 +3773,14 @@ static PyMethodDef time_methods[] = { + /* Class methods: */ + + {"strptime", (PyCFunction)time_strptime, METH_VARARGS | METH_CLASS, + PyDoc_STR("string, format -> new time parsed from a string " + "(like time.strptime()).")}, + + /* Instance methods: */ + {"isoformat", (PyCFunction)time_isoformat, METH_NOARGS, PyDoc_STR("Return string in ISO 8601 format, HH:MM:SS[.mmmmmm]" "[+HH:MM].")},