summaryrefslogtreecommitdiffstats
path: root/Lib/datetime.py
diff options
context:
space:
mode:
authorPaul Ganssle <pganssle@users.noreply.github.com>2019-04-29 13:22:03 (GMT)
committerVictor Stinner <vstinner@redhat.com>2019-04-29 13:22:03 (GMT)
commit88c093705615c50c47fdd9ab976803f73de7e308 (patch)
tree4a76496a2c930d1e27e020555f4b91e2b43f777b /Lib/datetime.py
parenta86e06433a010f873dfd7957e0f87a39539876ee (diff)
downloadcpython-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.py35
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'