diff -r 7c48bb929e6e Doc/library/datetime.rst --- a/Doc/library/datetime.rst Tue Mar 27 11:49:21 2012 +0200 +++ b/Doc/library/datetime.rst Sat Mar 31 05:10:44 2012 -0500 @@ -417,6 +417,15 @@ d``. +.. classmethod:: date.from_iso_week(year, week, day=1) + + Return the date corresponding to the ISO year, week and optionally day. + :exc:`ValueError` is raised unless ``1 <= week <= 53``, ``1 <= day <= 7``, + further :exc:`ValueError` is raised if the choosen week overflows the year. + The default behaviour, without supplying a day, returns the date for monday + of that week, if a ISO day is supplied that days date is returned. + + Class attributes: .. attribute:: date.min diff -r 7c48bb929e6e Lib/datetime.py --- a/Lib/datetime.py Tue Mar 27 11:49:21 2012 +0200 +++ b/Lib/datetime.py Sat Mar 31 05:10:44 2012 -0500 @@ -896,6 +896,23 @@ week = 0 return year, week+1, day+1 + @classmethod + def from_iso_week(cls, year, week, day=1): + """Construct a self from ISO year, week number and weekday (default 1) + """ + if not 1 <= day <= 7: + raise ValueError("'day' invalid, acceptable range 1-7") + if not 1 <= week <= 53: + raise ValueError("'week' invalid, accaptable range 1-53") + self = cls(year, 1, 1) + if self.isocalendar()[1] != 1: + if self.weekday() > 3: # Jan 1 is not in week one + self += timedelta(7 - self.weekday()) + self += timedelta(7 * (week - 1)) + if self.isocalendar()[0] != year: + raise OverflowError("'week' within range but overflows to next year") + return self + timedelta(day - 1) + # Pickle support. def _getstate(self): diff -r 7c48bb929e6e Lib/test/datetimetester.py --- a/Lib/test/datetimetester.py Tue Mar 27 11:49:21 2012 +0200 +++ b/Lib/test/datetimetester.py Sat Mar 31 05:10:44 2012 -0500 @@ -980,6 +980,39 @@ self.assertRaises(OverflowError, self.theclass.fromtimestamp, insane) + def test_from_iso_week(self): + # This is an edge case, 1998 had 53 weeks + year, month, week, day = 1998, 12, 53, 31 + d = self.theclass.from_iso_week(year, week) + self.assertEqual(d.year, year) + self.assertEqual(d.month, month) + self.assertEqual(d.day, day) + + def test_from_iso_week_overflow(self): + # Test that we get the OverflowError when the year has 52 weeks + year, week = 1999, 53 + self.assertRaises(OverflowError, self.theclass.from_iso_week, year, + week) + + def test_from_iso_week_value_week(self): + # Test that we get the ValueError when we try setting an invalid week + year, week = 1999, 54 + self.assertRaises(ValueError, self.theclass.from_iso_week, year, + week) + year, week = 1999, 0 + self.assertRaises(ValueError, self.theclass.from_iso_week, year, + week) + + def test_from_iso_week_value_day(self): + # Test that we get the ValueError when we try setting an invalid week + year, week, day = 1999, 1, 0 + self.assertRaises(ValueError, self.theclass.from_iso_week, year, + week, day) + year, week, day = 1999, 1, 8 + self.assertRaises(ValueError, self.theclass.from_iso_week, year, + week, day) + + def test_today(self): import time