diff -r 1cdedc9a9e9f Doc/library/datetime.rst --- a/Doc/library/datetime.rst Tue Jun 09 14:24:30 2015 -0400 +++ b/Doc/library/datetime.rst Tue Jun 09 23:05:00 2015 +0200 @@ -557,7 +557,7 @@ .. method:: date.isocalendar() - Return a 3-tuple, (ISO year, ISO week number, ISO weekday). + Return a 3-namedtuple, (ISO year, ISO week number, ISO weekday). The ISO calendar is a widely used variant of the Gregorian calendar. See http://www.staff.science.uu.nl/~gent0113/calendar/isocalendar.htm for a good @@ -573,6 +573,9 @@ ``date(2003, 12, 29).isocalendar() == (2004, 1, 1)`` and ``date(2004, 1, 4).isocalendar() == (2004, 1, 7)``. + .. versionchanged:: 3.5 + Result changed from a tuple to a namedtuple. + .. method:: date.isoformat() @@ -1129,8 +1132,8 @@ .. method:: datetime.isocalendar() - Return a 3-tuple, (ISO year, ISO week number, ISO weekday). The same as - ``self.date().isocalendar()``. + Return a 3-namedtuple, (ISO year, ISO week number, ISO weekday). The same + as ``self.date().isocalendar()``. .. method:: datetime.isoformat(sep='T') diff -r 1cdedc9a9e9f Lib/datetime.py --- a/Lib/datetime.py Tue Jun 09 14:24:30 2015 -0400 +++ b/Lib/datetime.py Tue Jun 09 23:05:00 2015 +0200 @@ -4,6 +4,7 @@ time zone and DST data sources. """ +from collections import namedtuple as _namedtuple import time as _time import math as _math @@ -638,6 +639,8 @@ microseconds=999999) timedelta.resolution = timedelta(microseconds=1) +ISOCalendarResult = _namedtuple('ISOCalendarResult', 'year week weekday') + class date: """Concrete date type. @@ -910,7 +913,7 @@ if today >= _isoweek1monday(year+1): year += 1 week = 0 - return year, week+1, day+1 + return ISOCalendarResult(year, week+1, day+1) # Pickle support. diff -r 1cdedc9a9e9f Lib/test/datetimetester.py --- a/Lib/test/datetimetester.py Tue Jun 09 14:24:30 2015 -0400 +++ b/Lib/test/datetimetester.py Tue Jun 09 23:05:00 2015 +0200 @@ -1102,6 +1102,13 @@ d = self.theclass(2010, 1, 4+i) self.assertEqual(d.isocalendar(), (2010, 1, i+1)) + def test_isocalendar_named(self): + d = self.theclass(2008, 12, 3) + t = d.isocalendar() + self.assertEqual(t.year, 2008) + self.assertEqual(t.week, 49) + self.assertEqual(t.weekday, 3) + def test_iso_long_years(self): # Calculate long ISO years and compare to table from # http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm diff -r 1cdedc9a9e9f Misc/NEWS --- a/Misc/NEWS Tue Jun 09 14:24:30 2015 -0400 +++ b/Misc/NEWS Tue Jun 09 23:05:00 2015 +0200 @@ -13,6 +13,8 @@ Library ------- +- Issue #24416: date.isocalendar() now returns a namedtuple. + Documentation ------------- diff -r 1cdedc9a9e9f Modules/_datetimemodule.c --- a/Modules/_datetimemodule.c Tue Jun 09 14:24:30 2015 -0400 +++ b/Modules/_datetimemodule.c Tue Jun 09 23:05:00 2015 +0200 @@ -109,6 +109,7 @@ #define MONTH_IS_SANE(M) ((unsigned int)(M) - 1 < 12) /* Forward declarations. */ +static PyTypeObject *ISOCalendarResult; static PyTypeObject PyDateTime_DateType; static PyTypeObject PyDateTime_DateTimeType; static PyTypeObject PyDateTime_DeltaType; @@ -2727,7 +2728,8 @@ ++year; week = 0; } - return Py_BuildValue("iii", year, week + 1, day + 1); + return PyObject_CallFunction((PyObject *)ISOCalendarResult, "iii", + year, week + 1, day + 1); } /* Miscellaneous methods. */ @@ -5160,6 +5162,7 @@ NULL }; + PyMODINIT_FUNC PyInit__datetime(void) { @@ -5167,6 +5170,7 @@ PyObject *d; /* its dict */ PyObject *x; PyObject *delta; + PyObject *collections = NULL; m = PyModule_Create(&datetimemodule); if (m == NULL) @@ -5297,6 +5301,17 @@ PyModule_AddIntMacro(m, MINYEAR); PyModule_AddIntMacro(m, MAXYEAR); + /* ISOCalendarResult */ + collections = PyImport_ImportModule("collections"); + ISOCalendarResult = (PyTypeObject *)PyObject_CallMethod(collections, + "namedtuple", "(ss)", "ISOCalendarResult", + "year week weekday"); + + Py_CLEAR(collections); + + Py_INCREF(ISOCalendarResult); + PyModule_AddObject(m, "ISOCalendarResult", (PyObject *)ISOCalendarResult); + Py_INCREF(&PyDateTime_DateType); PyModule_AddObject(m, "date", (PyObject *) &PyDateTime_DateType);