Index: py3k/Doc/library/datetime.rst =================================================================== --- py3k/Doc/library/datetime.rst (revision 80032) +++ py3k/Doc/library/datetime.rst (working copy) @@ -982,6 +982,20 @@ '2002-12-25 00:00:00-06:39' +.. method:: datetime.rfcformat() + + Return a string representing the date and time in RFC 3339 format, + YYYY-MM-DDTHH:MM:SS.mmmmmm+HH:MM or, if :attr:`microsecond` is 0, + YYYY-MM-DDTHH:MM:SS+HH:MM + + This method differs from :meth:`isoformat` in that the separator is + always 'T', and the string always contains the UTC offset. For + naive instances the default UTC offset is '-00:00'. For example, + + >>> datetime(2010, 4, 12).rfcformat() + '2010-04-12T00:00:00-00:00' + + .. method:: datetime.__str__() For a :class:`datetime` instance *d*, ``str(d)`` is equivalent to Index: py3k/Lib/test/test_datetime.py =================================================================== --- py3k/Lib/test/test_datetime.py (revision 80032) +++ py3k/Lib/test/test_datetime.py (working copy) @@ -1186,6 +1186,23 @@ # str is ISO format with the separator forced to a blank. self.assertEqual(str(t), "0002-03-02 00:00:00") + def test_rfcformat(self): + t = self.theclass(2, 3, 2, 4, 5, 1, 123) + self.assertEqual(t.rfcformat(), "0002-03-02T04:05:01.000123-00:00") + + t = self.theclass(2, 3, 2, 4, 5, 1, 0) + self.assertEqual(t.rfcformat(), "0002-03-02T04:05:01-00:00") + + t = self.theclass(2, 3, 2) + self.assertEqual(t.rfcformat(), "0002-03-02T00:00:00-00:00") + + # with tzinfo: + t = self.theclass(2, 3, 2, 4, 5, 1, 123, FixedOffset(0, "UTC")) + self.assertEqual(t.rfcformat(), "0002-03-02T04:05:01.000123+00:00") + + t = self.theclass(2, 3, 2, 4, 5, 1, 123, FixedOffset(77, "77min")) + self.assertEqual(t.rfcformat(), "0002-03-02T04:05:01.000123+01:17") + def test_format(self): dt = self.theclass(2007, 9, 10, 4, 5, 1, 123) self.assertEqual(dt.__format__(''), str(dt)) Index: py3k/Modules/datetimemodule.c =================================================================== --- py3k/Modules/datetimemodule.c (revision 80032) +++ py3k/Modules/datetimemodule.c (working copy) @@ -4180,6 +4180,38 @@ } static PyObject * +datetime_rfcformat(PyDateTime_DateTime *self) +{ + char buffer[100]; + PyObject *result; + int us = DATE_GET_MICROSECOND(self); + + /* We will need the UTC offset. */ + if (!HASTZINFO(self)) { + PyOS_snprintf(buffer, sizeof(buffer), "-00:00"); + } + else if (format_utcoffset(buffer, sizeof(buffer), ":", self->tzinfo, + (PyObject *)self) < 0) { + return NULL; + } + + if (us) + result = PyUnicode_FromFormat("%04d-%02d-%02dT%02d:%02d:%02d.%06d%s", + GET_YEAR(self), GET_MONTH(self), + GET_DAY(self), + DATE_GET_HOUR(self), DATE_GET_MINUTE(self), + DATE_GET_SECOND(self), us, buffer); + else + result = PyUnicode_FromFormat("%04d-%02d-%02dT%02d:%02d:%02d%s", + GET_YEAR(self), GET_MONTH(self), + GET_DAY(self), + DATE_GET_HOUR(self), DATE_GET_MINUTE(self), + DATE_GET_SECOND(self), buffer); + + return result; +} + +static PyObject * datetime_ctime(PyDateTime_DateTime *self) { return format_ctime((PyDateTime_Date *)self, @@ -4568,6 +4600,10 @@ "sep is used to separate the year from the time, and " "defaults to 'T'.")}, + {"rfcformat", (PyCFunction)datetime_rfcformat, METH_NOARGS, + PyDoc_STR("Return string in RFC 3339 format, " + "YYYY-MM-DDTHH:MM:SS[.mmmmmm]+HH:MM.")}, + {"utcoffset", (PyCFunction)datetime_utcoffset, METH_NOARGS, PyDoc_STR("Return self.tzinfo.utcoffset(self).")},