| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent aa92a7c commit 1b97b9b
7 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -670,7 +670,8 @@ Instance methods: | |||
| 670 | 670 | ||
| 671 | 671 | .. method:: date.isocalendar() | |
| 672 | 672 | ||
| 673 | - Return a 3-tuple, (ISO year, ISO week number, ISO weekday). | ||
| 673 | + Return a :term:`named tuple` object with three components: ``year``, | ||
| 674 | + ``week`` and ``weekday``. | ||
| 674 | 675 | ||
| 675 | 676 | The ISO calendar is a widely used variant of the Gregorian calendar. [#]_ | |
| 676 | 677 | ||
@@ -682,11 +683,14 @@ Instance methods: | |||
| 682 | 683 | For example, 2004 begins on a Thursday, so the first week of ISO year 2004 | |
| 683 | 684 | begins on Monday, 29 Dec 2003 and ends on Sunday, 4 Jan 2004:: | |
| 684 | 685 | ||
| 685 | - >>> from datetime import date | ||
| 686 | - >>> date(2003, 12, 29).isocalendar() | ||
| 687 | - (2004, 1, 1) | ||
| 688 | - >>> date(2004, 1, 4).isocalendar() | ||
| 689 | - (2004, 1, 7) | ||
| 686 | + >>> from datetime import date | ||
| 687 | + >>> date(2003, 12, 29).isocalendar() | ||
| 688 | + datetime.IsoCalendarDate(year=2004, week=1, weekday=1) | ||
| 689 | + >>> date(2004, 1, 4).isocalendar() | ||
| 690 | + datetime.IsoCalendarDate(year=2004, week=1, weekday=7) | ||
| 691 | + | ||
| 692 | + .. versionchanged:: 3.9 | ||
| 693 | + Result changed from a tuple to a :term:`named tuple`. | ||
| 690 | 694 | ||
| 691 | 695 | .. method:: date.isoformat() | |
| 692 | 696 | ||
@@ -1397,8 +1401,8 @@ Instance methods: | |||
| 1397 | 1401 | ||
| 1398 | 1402 | .. method:: datetime.isocalendar() | |
| 1399 | 1403 | ||
| 1400 | - Return a 3-tuple, (ISO year, ISO week number, ISO weekday). The same as | ||
| 1401 | - ``self.date().isocalendar()``. | ||
| 1404 | + Return a :term:`named tuple` with three components: ``year``, ``week`` | ||
| 1405 | + and ``weekday``. The same as ``self.date().isocalendar()``. | ||
| 1402 | 1406 | ||
| 1403 | 1407 | ||
| 1404 | 1408 | .. method:: datetime.isoformat(sep='T', timespec='auto') | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -281,6 +281,13 @@ Add :func:`curses.get_escdelay`, :func:`curses.set_escdelay`, | |||
| 281 | 281 | :func:`curses.get_tabsize`, and :func:`curses.set_tabsize` functions. | |
| 282 | 282 | (Contributed by Anthony Sottile in :issue:`38312`.) | |
| 283 | 283 | ||
| 284 | + datetime | ||
| 285 | + -------- | ||
| 286 | + The :meth:`~datetime.date.isocalendar()` of :class:`datetime.date` | ||
| 287 | + and :meth:`~datetime.datetime.isocalendar()` of :class:`datetime.datetime` | ||
| 288 | + methods now returns a :func:`~collections.namedtuple` instead of a :class:`tuple`. | ||
| 289 | + (Contributed by Dong-hee Na in :issue:`24416`.) | ||
| 290 | + | ||
| 284 | 291 | fcntl | |
| 285 | 292 | ----- | |
| 286 | 293 | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1095,7 +1095,7 @@ def isoweekday(self): | |||
| 1095 | 1095 | return self.toordinal() % 7 or 7 | |
| 1096 | 1096 | ||
| 1097 | 1097 | def isocalendar(self): | |
| 1098 | - """Return a 3-tuple containing ISO year, week number, and weekday. | ||
| 1098 | + """Return a named tuple containing ISO year, week number, and weekday. | ||
| 1099 | 1099 | ||
| 1100 | 1100 | The first ISO week of the year is the (Mon-Sun) week | |
| 1101 | 1101 | containing the year's first Thursday; everything else derives | |
@@ -1120,7 +1120,7 @@ def isocalendar(self): | |||
| 1120 | 1120 | if today >= _isoweek1monday(year+1): | |
| 1121 | 1121 | year += 1 | |
| 1122 | 1122 | week = 0 | |
| 1123 | - return year, week+1, day+1 | ||
| 1123 | + return _IsoCalendarDate(year, week+1, day+1) | ||
| 1124 | 1124 | ||
| 1125 | 1125 | # Pickle support. | |
| 1126 | 1126 | ||
@@ -1210,6 +1210,36 @@ def __reduce__(self): | |||
| 1210 | 1210 | else: | |
| 1211 | 1211 | return (self.__class__, args, state) | |
| 1212 | 1212 | ||
| 1213 | + | ||
| 1214 | + class IsoCalendarDate(tuple): | ||
| 1215 | + | ||
| 1216 | + def __new__(cls, year, week, weekday, /): | ||
| 1217 | + return super().__new__(cls, (year, week, weekday)) | ||
| 1218 | + | ||
| 1219 | + @property | ||
| 1220 | + def year(self): | ||
| 1221 | + return self[0] | ||
| 1222 | + | ||
| 1223 | + @property | ||
| 1224 | + def week(self): | ||
| 1225 | + return self[1] | ||
| 1226 | + | ||
| 1227 | + @property | ||
| 1228 | + def weekday(self): | ||
| 1229 | + return self[2] | ||
| 1230 | + | ||
| 1231 | + def __reduce__(self): | ||
| 1232 | + # This code is intended to pickle the object without making the | ||
| 1233 | + # class public. See https://bugs.python.org/msg352381 | ||
| 1234 | + return (tuple, (tuple(self),)) | ||
| 1235 | + | ||
| 1236 | + def __repr__(self): | ||
| 1237 | + return (f'{self.__class__.__name__}' | ||
| 1238 | + f'(year={self[0]}, week={self[1]}, weekday={self[2]})') | ||
| 1239 | + | ||
| 1240 | + | ||
| 1241 | + _IsoCalendarDate = IsoCalendarDate | ||
| 1242 | + del IsoCalendarDate | ||
| 1213 | 1243 | _tzinfo_class = tzinfo | |
| 1214 | 1244 | ||
| 1215 | 1245 | class time: | |
@@ -1559,6 +1589,7 @@ def __reduce__(self): | |||
| 1559 | 1589 | time.max = time(23, 59, 59, 999999) | |
| 1560 | 1590 | time.resolution = timedelta(microseconds=1) | |
| 1561 | 1591 | ||
| 1592 | + | ||
| 1562 | 1593 | class datetime(date): | |
| 1563 | 1594 | """datetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]]) | |
| 1564 | 1595 | ||
@@ -2514,7 +2545,7 @@ def _name_from_offset(delta): | |||
| 2514 | 2545 | _format_time, _format_offset, _is_leap, _isoweek1monday, _math, | |
| 2515 | 2546 | _ord2ymd, _time, _time_class, _tzinfo_class, _wrap_strftime, _ymd2ord, | |
| 2516 | 2547 | _divide_and_round, _parse_isoformat_date, _parse_isoformat_time, | |
| 2517 | - _parse_hh_mm_ss_ff) | ||
| 2548 | + _parse_hh_mm_ss_ff, _IsoCalendarDate) | ||
| 2518 | 2549 | # XXX Since import * above excludes names that start with _, | |
| 2519 | 2550 | # docstring does not get overwritten. In the future, it may be | |
| 2520 | 2551 | # appropriate to maintain a single module level docstring and | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -2,6 +2,7 @@ | |||
| 2 | 2 | ||
| 3 | 3 | See http://www.zope.org/Members/fdrake/DateTimeWiki/TestCases | |
| 4 | 4 | """ | |
| 5 | + import io | ||
| 5 | 6 | import itertools | |
| 6 | 7 | import bisect | |
| 7 | 8 | import copy | |
@@ -1355,19 +1356,43 @@ def test_weekday(self): | |||
| 1355 | 1356 | def test_isocalendar(self): | |
| 1356 | 1357 | # Check examples from | |
| 1357 | 1358 | # http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm | |
| 1358 | - for i in range(7): | ||
| 1359 | - d = self.theclass(2003, 12, 22+i) | ||
| 1360 | - self.assertEqual(d.isocalendar(), (2003, 52, i+1)) | ||
| 1361 | - d = self.theclass(2003, 12, 29) + timedelta(i) | ||
| 1362 | - self.assertEqual(d.isocalendar(), (2004, 1, i+1)) | ||
| 1363 | - d = self.theclass(2004, 1, 5+i) | ||
| 1364 | - self.assertEqual(d.isocalendar(), (2004, 2, i+1)) | ||
| 1365 | - d = self.theclass(2009, 12, 21+i) | ||
| 1366 | - self.assertEqual(d.isocalendar(), (2009, 52, i+1)) | ||
| 1367 | - d = self.theclass(2009, 12, 28) + timedelta(i) | ||
| 1368 | - self.assertEqual(d.isocalendar(), (2009, 53, i+1)) | ||
| 1369 | - d = self.theclass(2010, 1, 4+i) | ||
| 1370 | - self.assertEqual(d.isocalendar(), (2010, 1, i+1)) | ||
| 1359 | + week_mondays = [ | ||
| 1360 | + ((2003, 12, 22), (2003, 52, 1)), | ||
| 1361 | + ((2003, 12, 29), (2004, 1, 1)), | ||
| 1362 | + ((2004, 1, 5), (2004, 2, 1)), | ||
| 1363 | + ((2009, 12, 21), (2009, 52, 1)), | ||
| 1364 | + ((2009, 12, 28), (2009, 53, 1)), | ||
| 1365 | + ((2010, 1, 4), (2010, 1, 1)), | ||
| 1366 | + ] | ||
| 1367 | + | ||
| 1368 | + test_cases = [] | ||
| 1369 | + for cal_date, iso_date in week_mondays: | ||
| 1370 | + base_date = self.theclass(*cal_date) | ||
| 1371 | + # Adds one test case for every day of the specified weeks | ||
| 1372 | + for i in range(7): | ||
| 1373 | + new_date = base_date + timedelta(i) | ||
| 1374 | + new_iso = iso_date[0:2] + (iso_date[2] + i,) | ||
| 1375 | + test_cases.append((new_date, new_iso)) | ||
| 1376 | + | ||
| 1377 | + for d, exp_iso in test_cases: | ||
| 1378 | + with self.subTest(d=d, comparison="tuple"): | ||
| 1379 | + self.assertEqual(d.isocalendar(), exp_iso) | ||
| 1380 | + | ||
| 1381 | + # Check that the tuple contents are accessible by field name | ||
| 1382 | + with self.subTest(d=d, comparison="fields"): | ||
| 1383 | + t = d.isocalendar() | ||
| 1384 | + self.assertEqual((t.year, t.week, t.weekday), exp_iso) | ||
| 1385 | + | ||
| 1386 | + def test_isocalendar_pickling(self): | ||
| 1387 | + """Test that the result of datetime.isocalendar() can be pickled. | ||
| 1388 | + | ||
| 1389 | + The result of a round trip should be a plain tuple. | ||
| 1390 | + """ | ||
| 1391 | + d = self.theclass(2019, 1, 1) | ||
| 1392 | + p = pickle.dumps(d.isocalendar()) | ||
| 1393 | + res = pickle.loads(p) | ||
| 1394 | + self.assertEqual(type(res), tuple) | ||
| 1395 | + self.assertEqual(res, (2019, 1, 2)) | ||
| 1371 | 1396 | ||
| 1372 | 1397 | def test_iso_long_years(self): | |
| 1373 | 1398 | # Calculate long ISO years and compare to table from | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,3 @@ | |||
| 1 | + The ``isocalendar()`` methods of :class:`datetime.date` and | ||
| 2 | + :class:`datetime.datetime` now return a :term:`named tuple` | ||
| 3 | + instead of a :class:`tuple`. | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments