diff options
Diffstat (limited to 'Lib')
-rw-r--r-- | Lib/_strptime.py | 44 | ||||
-rw-r--r-- | Lib/test/test_strptime.py | 22 |
2 files changed, 65 insertions, 1 deletions
diff --git a/Lib/_strptime.py b/Lib/_strptime.py index 17460ce..e2657d7 100644 --- a/Lib/_strptime.py +++ b/Lib/_strptime.py @@ -212,7 +212,7 @@ class TimeRE(dict): for tz in tz_names), 'Z'), '%': '%'}) - base.__setitem__('W', base.__getitem__('U')) + base.__setitem__('W', base.__getitem__('U').replace('U', 'W')) base.__setitem__('c', self.pattern(self.locale_time.LC_date_time)) base.__setitem__('x', self.pattern(self.locale_time.LC_date)) base.__setitem__('X', self.pattern(self.locale_time.LC_time)) @@ -298,10 +298,17 @@ def strptime(data_string, format="%a %b %d %H:%M:%S %Y"): month = day = 1 hour = minute = second = 0 tz = -1 + week_of_year = -1 + week_of_year_start = -1 # weekday and julian defaulted to -1 so as to signal need to calculate values weekday = julian = -1 found_dict = found.groupdict() for group_key in found_dict.iterkeys(): + # Directives not explicitly handled below: + # c, x, X + # handled by making out of other directives + # U, W + # worthless without day of the week if group_key == 'y': year = int(found_dict['y']) # Open Group specification for strptime() states that a %y @@ -355,6 +362,14 @@ def strptime(data_string, format="%a %b %d %H:%M:%S %Y"): weekday -= 1 elif group_key == 'j': julian = int(found_dict['j']) + elif group_key in ('U', 'W'): + week_of_year = int(found_dict[group_key]) + if group_key == 'U': + # U starts week on Sunday + week_of_year_start = 6 + else: + # W starts week on Monday + week_of_year_start = 0 elif group_key == 'Z': # Since -1 is default value only need to worry about setting tz if # it can be something other than -1. @@ -370,6 +385,33 @@ def strptime(data_string, format="%a %b %d %H:%M:%S %Y"): else: tz = value break + # If we know the week of the year and what day of that week, we can figure + # out the Julian day of the year + # Calculations below assume 0 is a Monday + # XXX only works for W + if julian == -1 and week_of_year != -1 and weekday != -1 and year != -1: + # Adjust for U directive so that calculations are not dependent on + # directive used to figure out week of year + if weekday == 6 and week_of_year_start == 6: + week_of_year -= 1 + # For some reason when Dec 31 falls on a Monday the week of the year is + # off by a week; verified on both OS X and Solaris. + elif weekday == 0 and week_of_year_start == 6 and week_of_year >= 52: + week_of_year += 1 + # Calculate how many days in week 0 + first_weekday = datetime_date(year, 1, 1).weekday() + preceeding_days = 7 - first_weekday + if preceeding_days == 7: + preceeding_days = 0 + # If in week 0, then just figure out how many days from Jan 1 to day of + # week specified, else calculate by multiplying week of year by 7, + # adding in days in week 0, and the number of days from Monday to the + # day of the week + if not week_of_year: + julian = 1 + weekday - first_weekday + else: + days_to_week = preceeding_days + (7 * (week_of_year - 1)) + julian = 1 + days_to_week + weekday # Cannot pre-calculate datetime_date() since can change in Julian #calculation and thus could have different value for the day of the week #calculation diff --git a/Lib/test/test_strptime.py b/Lib/test/test_strptime.py index 17f339b..bc68851 100644 --- a/Lib/test/test_strptime.py +++ b/Lib/test/test_strptime.py @@ -6,6 +6,7 @@ import locale import re import sys from test import test_support +from datetime import date as datetime_date import _strptime @@ -417,6 +418,27 @@ class CalculationTests(unittest.TestCase): "Calculation of day of the week failed;" "%s != %s" % (result.tm_wday, self.time_tuple.tm_wday)) + def test_week_of_year_and_day_of_week_calculation(self): + # Should be able to infer date if given year, week of year (%U or %W) + # and day of the week + def test_helper(ymd_tuple, test_reason): + for directive in ('W', 'U'): + format_string = "%%Y %%%s %%w" % directive + strp_input = datetime_date(*ymd_tuple).strftime(format_string) + strp_output = _strptime.strptime(strp_input, format_string) + self.failUnless(strp_output[:3] == ymd_tuple, + "%s(%s) test failed w/ '%s': %s != %s" % + (test_reason, directive, strp_input, + strp_output[:3], ymd_tuple[:3])) + test_helper((1901, 1, 3), "week 0") + test_helper((1901, 1, 8), "common case") + test_helper((1901, 1, 13), "day on Sunday") + test_helper((1901, 1, 14), "day on Monday") + test_helper((1905, 1, 1), "Jan 1 on Sunday") + test_helper((1906, 1, 1), "Jan 1 on Monday") + test_helper((1905, 12, 31), "Dec 31 on Sunday") + test_helper((1906, 12, 31), "Dec 31 on Monday") + class CacheTests(unittest.TestCase): """Test that caching works properly.""" |