diff options
author | Paul Ganssle <pganssle@users.noreply.github.com> | 2019-04-29 13:22:03 (GMT) |
---|---|---|
committer | Victor Stinner <vstinner@redhat.com> | 2019-04-29 13:22:03 (GMT) |
commit | 88c093705615c50c47fdd9ab976803f73de7e308 (patch) | |
tree | 4a76496a2c930d1e27e020555f4b91e2b43f777b /Lib/datetime.py | |
parent | a86e06433a010f873dfd7957e0f87a39539876ee (diff) | |
download | cpython-88c093705615c50c47fdd9ab976803f73de7e308.zip cpython-88c093705615c50c47fdd9ab976803f73de7e308.tar.gz cpython-88c093705615c50c47fdd9ab976803f73de7e308.tar.bz2 |
bpo-36004: Add date.fromisocalendar (GH-11888)
This commit implements the first version of date.fromisocalendar, the
inverse function for date.isocalendar.
Diffstat (limited to 'Lib/datetime.py')
-rw-r--r-- | Lib/datetime.py | 35 |
1 files changed, 35 insertions, 0 deletions
diff --git a/Lib/datetime.py b/Lib/datetime.py index 85bfa48..0e64815 100644 --- a/Lib/datetime.py +++ b/Lib/datetime.py @@ -884,6 +884,40 @@ class date: except Exception: raise ValueError(f'Invalid isoformat string: {date_string!r}') + @classmethod + def fromisocalendar(cls, year, week, day): + """Construct a date from the ISO year, week number and weekday. + + This is the inverse of the date.isocalendar() function""" + # Year is bounded this way because 9999-12-31 is (9999, 52, 5) + if not MINYEAR <= year <= MAXYEAR: + raise ValueError(f"Year is out of range: {year}") + + if not 0 < week < 53: + out_of_range = True + + if week == 53: + # ISO years have 53 weeks in them on years starting with a + # Thursday and leap years starting on a Wednesday + first_weekday = _ymd2ord(year, 1, 1) % 7 + if (first_weekday == 4 or (first_weekday == 3 and + _is_leap(year))): + out_of_range = False + + if out_of_range: + raise ValueError(f"Invalid week: {week}") + + if not 0 < day < 8: + raise ValueError(f"Invalid weekday: {day} (range is [1, 7])") + + # Now compute the offset from (Y, 1, 1) in days: + day_offset = (week - 1) * 7 + (day - 1) + + # Calculate the ordinal day for monday, week 1 + day_1 = _isoweek1monday(year) + ord_day = day_1 + day_offset + + return cls(*_ord2ymd(ord_day)) # Conversions to string @@ -2141,6 +2175,7 @@ def _isoweek1monday(year): week1monday += 7 return week1monday + class timezone(tzinfo): __slots__ = '_offset', '_name' |