why not datetime.strptime() ?

josh at yucs.org josh at yucs.org
Tue Jan 11 11:29:01 EST 2005


David M. Cookie writes:
> You don't check for errors: an exception being thrown by
> PyObject_CallMethod will return obj == NULL.

Oops, missed that one. Thanks.

> If there's a module in sys.path called time that overrides the stdlib
> time, things will fail, and you should be able to catch that.

Maybe someone really does want to override the time module, and then we
shouldn't get in their way? For example, if someone adds a new field
descriptor for nanoseconds to time.strptime, then it'd be nice to have
it work with datetime.datetime.strptime as well.

Incidentally, this is the way that the rest of datetime does it.

> Are you positive those PySequence_GetItem calls will succeed? That
> they will return Python integers?

Well, without interfaces, I can't be sure :). Throwing an exception
is cool (especially if we do allow user implemented time.strptime).

-------------- next part --------------
--- Modules/datetimemodule.c.orig	2003-10-20 10:34:46.000000000 -0400
+++ Modules/datetimemodule.c	2005-01-11 10:42:23.000000000 -0500
@@ -3774,6 +3774,47 @@
 	return result;
 }
 
+/* Return new datetime from time.strptime(). */
+static PyObject *
+datetime_strptime(PyObject *cls, PyObject *args)
+{
+	PyObject *result = NULL, *obj, *module;
+	const char *string, *format;
+
+	if (!PyArg_ParseTuple(args, "ss:strptime", &string, &format))
+		return NULL;
+
+	if ((module = PyImport_ImportModule("time")) == NULL)
+		return NULL;
+	obj = PyObject_CallMethod(module, "strptime", "ss", string, format);
+	Py_DECREF(module);
+
+	if (obj != NULL) {
+		int good_timetuple = 1;
+		if (PySequence_Check(obj) && PySequence_Size(obj) > 6) {
+			int i;
+			for (i=0; i <= 6; i++)
+				if (!PyInt_Check(PySequence_GetItem(obj, i)))
+					good_timetuple = 0;
+		} else
+			good_timetuple = 0;
+		if (good_timetuple)
+			result = PyObject_CallFunction(cls, "iiiiiii",
+				PyInt_AsLong(PySequence_GetItem(obj, 0)),
+				PyInt_AsLong(PySequence_GetItem(obj, 1)),
+				PyInt_AsLong(PySequence_GetItem(obj, 2)),
+				PyInt_AsLong(PySequence_GetItem(obj, 3)),
+				PyInt_AsLong(PySequence_GetItem(obj, 4)),
+				PyInt_AsLong(PySequence_GetItem(obj, 5)),
+				PyInt_AsLong(PySequence_GetItem(obj, 6)));
+		else
+			PyErr_SetString(PyExc_ValueError,
+				"unexpected value from time.strptime");
+		Py_DECREF(obj);
+	}
+	return result;
+}
+
 /* Return new datetime from date/datetime and time arguments. */
 static PyObject *
 datetime_combine(PyObject *cls, PyObject *args, PyObject *kw)
@@ -4385,6 +4426,11 @@
 	 PyDoc_STR("timestamp -> UTC datetime from a POSIX timestamp "
 	 	   "(like time.time()).")},
 
+	{"strptime", (PyCFunction)datetime_strptime,
+	 METH_VARARGS | METH_CLASS,
+	 PyDoc_STR("strptime -> new datetime parsed from a string"
+	 	   "(like time.strptime()).")},
+
 	{"combine", (PyCFunction)datetime_combine,
 	 METH_VARARGS | METH_KEYWORDS | METH_CLASS,
 	 PyDoc_STR("date, time -> datetime with same date and time fields")},
--- Doc/lib/libdatetime.tex.orig	2003-09-06 01:36:56.000000000 -0400
+++ Doc/lib/libdatetime.tex	2005-01-11 11:06:22.699348152 -0500
@@ -624,6 +624,13 @@
   ignored.
   \end{methoddesc}
 
+\begin{methoddesc}{strptime}{date_string, format}
+  Return the date corresponding to date_string, parsed according
+  to format. This is equivalent to \code{datetime(*(time.strptime(
+  date_string, format)[0:7]))}. \exception{ValueError} is raised if
+  \code{time.strptime()} returns a value which isn't a timetuple.
+\end{methoddesc}
+
 Class attributes:
 
 \begin{memberdesc}{min}


More information about the Python-list mailing list