Index: Lib/test/test_datetime.py =================================================================== --- Lib/test/test_datetime.py (revision 58174) +++ Lib/test/test_datetime.py (working copy) @@ -1488,9 +1488,9 @@ def test_more_strftime(self): # This tests fields beyond those tested by the TestDate.test_strftime. - t = self.theclass(2004, 12, 31, 6, 22, 33) - self.assertEqual(t.strftime("%m %d %y %S %M %H %j"), - "12 31 04 33 22 06 366") + t = self.theclass(2004, 12, 31, 6, 22, 33, 47) + self.assertEqual(t.strftime("%m %d %y %f %S %M %H %j"), + "12 31 04 000047 33 22 06 366") def test_extract(self): dt = self.theclass(2002, 3, 4, 18, 45, 3, 1234) @@ -1763,7 +1763,7 @@ def test_strftime(self): t = self.theclass(1, 2, 3, 4) - self.assertEqual(t.strftime('%H %M %S'), "01 02 03") + self.assertEqual(t.strftime('%H %M %S %f'), "01 02 03 000004") # A naive object replaces %z and %Z with empty strings. self.assertEqual(t.strftime("'%z' '%Z'"), "'' ''") Index: Modules/datetimemodule.c =================================================================== --- Modules/datetimemodule.c (revision 58174) +++ Modules/datetimemodule.c (working copy) @@ -1130,10 +1130,24 @@ return 0; } +static PyObject * +make_freplacement(PyObject *object) +{ + char freplacement[7]; + if (PyTime_Check(object)) + sprintf(freplacement, "%06d", TIME_GET_MICROSECOND(object)); + else if (PyDateTime_Check(object)) + sprintf(freplacement, "%06d", DATE_GET_MICROSECOND(object)); + else + sprintf(freplacement, "%06d", 0); + + return PyString_FromStringAndSize(freplacement, strlen(freplacement)); +} + /* I sure don't want to reproduce the strftime code from the time module, * so this imports the module and calls it. All the hair is due to - * giving special meanings to the %z and %Z format codes via a preprocessing - * step on the format string. + * giving special meanings to the %z, %Z and %f format codes via a + * preprocessing step on the format string. * tzinfoarg is the argument to pass to the object's tzinfo method, if * needed. */ @@ -1145,6 +1159,7 @@ PyObject *zreplacement = NULL; /* py string, replacement for %z */ PyObject *Zreplacement = NULL; /* py string, replacement for %Z */ + PyObject *freplacement = NULL; /* py string, replacement for %f */ char *pin; /* pointer to next char in input format */ char ch; /* next char in input format */ @@ -1186,11 +1201,11 @@ } } - /* Scan the input format, looking for %z and %Z escapes, building + /* 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. */ - totalnew = PyString_Size(format) + 1; /* realistic if no %z/%Z */ + totalnew = PyString_Size(format) + 1; /* realistic if no %z/%Z/%f */ newfmt = PyString_FromStringAndSize(NULL, totalnew); if (newfmt == NULL) goto Done; pnew = PyString_AsString(newfmt); @@ -1272,6 +1287,18 @@ ptoappend = PyString_AS_STRING(Zreplacement); ntoappend = PyString_GET_SIZE(Zreplacement); } + else if (ch == 'f') { + /* format microseconds */ + if (freplacement == NULL) { + freplacement = make_freplacement(object); + if (freplacement == NULL) + goto Done; + } + assert(freplacement != NULL); + assert(PyString_Check(freplacement)); + ptoappend = PyString_AS_STRING(freplacement); + ntoappend = PyString_GET_SIZE(freplacement); + } else { /* percent followed by neither z nor Z */ ptoappend = pin - 2; @@ -1313,6 +1340,7 @@ Py_DECREF(time); } Done: + Py_XDECREF(freplacement); Py_XDECREF(zreplacement); Py_XDECREF(Zreplacement); Py_XDECREF(newfmt); Index: Doc/library/datetime.rst =================================================================== --- Doc/library/datetime.rst (revision 58174) +++ Doc/library/datetime.rst (working copy) @@ -1297,10 +1297,16 @@ be used, as time objects have no such values. If they're used anyway, ``1900`` is substituted for the year, and ``0`` for the month and day. -For :class:`date` objects, the format codes for hours, minutes, and seconds -should not be used, as :class:`date` objects have no such values. If they're -used anyway, ``0`` is substituted for them. +For :class:`date` objects, the format codes for hours, minutes, seconds, and +fractions of sections should not be used, as :class:`date` objects have no +such values. If they're used anyway, ``0`` is substituted for them. +:class:`time` and :class:`datetime` objects support a ``%f`` format code +which expands to the number of microseconds in the object, zero-padded on +the left to six places. + +.. versionadded:: 2.6 + For a naive object, the ``%z`` and ``%Z`` format codes are replaced by empty strings.