@@ -273,6 +273,27 @@ def compile(self, format):
273273_CACHE_MAX_SIZE = 5 # Max number of regexes stored in _regex_cache
274274_regex_cache = {}
275275
276+ def _calc_julian_from_U_or_W (year , week_of_year , day_of_week , week_starts_Mon ):
277+ """Calculate the Julian day based on the year, week of the year, and day of
278+ the week, with week_start_day representing whether the week of the year
279+ assumes the week starts on Sunday or Monday (6 or 0)."""
280+ first_weekday = datetime_date (year , 1 , 1 ).weekday ()
281+ # If we are dealing with the %U directive (week starts on Sunday), it's
282+ # easier to just shift the view to Sunday being the first day of the
283+ # week.
284+ if not week_starts_Mon :
285+ first_weekday = (first_weekday + 1 ) % 7
286+ day_of_week = (day_of_week + 1 ) % 7
287+ # Need to watch out for a week 0 (when the first day of the year is not
288+ # the same as that specified by %U or %W).
289+ week_0_length = (7 - first_weekday ) % 7
290+ if week_of_year == 0 :
291+ return 1 + day_of_week - first_weekday
292+ else :
293+ days_to_week = week_0_length + (7 * (week_of_year - 1 ))
294+ return 1 + days_to_week + day_of_week
295+
296+
276297def strptime (data_string , format = "%a %b %d %H:%M:%S %Y" ):
277298 """Return a time struct based on the input string and the format string."""
278299 global _TimeRE_cache , _regex_cache
@@ -385,10 +406,10 @@ def strptime(data_string, format="%a %b %d %H:%M:%S %Y"):
385406 elif group_key in ('U' , 'W' ):
386407 week_of_year = int (found_dict [group_key ])
387408 if group_key == 'U' :
388- # U starts week on Sunday
409+ # U starts week on Sunday.
389410 week_of_year_start = 6
390411 else :
391- # W starts week on Monday
412+ # W starts week on Monday.
392413 week_of_year_start = 0
393414 elif group_key == 'Z' :
394415 # Since -1 is default value only need to worry about setting tz if
@@ -406,42 +427,20 @@ def strptime(data_string, format="%a %b %d %H:%M:%S %Y"):
406427 tz = value
407428 break
408429 # If we know the week of the year and what day of that week, we can figure
409- # out the Julian day of the year
410- # Calculations below assume 0 is a Monday
430+ # out the Julian day of the year.
411431 if julian == - 1 and week_of_year != - 1 and weekday != - 1 :
412- # Calculate how many days in week 0
413- first_weekday = datetime_date (year , 1 , 1 ).weekday ()
414- preceeding_days = 7 - first_weekday
415- if preceeding_days == 7 :
416- preceeding_days = 0
417- # Adjust for U directive so that calculations are not dependent on
418- # directive used to figure out week of year
419- if weekday == 6 and week_of_year_start == 6 :
420- week_of_year -= 1
421- # If a year starts and ends on a Monday but a week is specified to
422- # start on a Sunday we need to up the week to counter-balance the fact
423- # that with %W that first Monday starts week 1 while with %U that is
424- # week 0 and thus shifts everything by a week
425- if weekday == 0 and first_weekday == 0 and week_of_year_start == 6 :
426- week_of_year += 1
427- # If in week 0, then just figure out how many days from Jan 1 to day of
428- # week specified, else calculate by multiplying week of year by 7,
429- # adding in days in week 0, and the number of days from Monday to the
430- # day of the week
431- if week_of_year == 0 :
432- julian = 1 + weekday - first_weekday
433- else :
434- days_to_week = preceeding_days + (7 * (week_of_year - 1 ))
435- julian = 1 + days_to_week + weekday
432+ week_starts_Mon = True if week_of_year_start == 0 else False
433+ julian = _calc_julian_from_U_or_W (year , week_of_year , weekday ,
434+ week_starts_Mon )
436435 # Cannot pre-calculate datetime_date() since can change in Julian
437- #calculation and thus could have different value for the day of the week
438- #calculation
436+ # calculation and thus could have different value for the day of the week
437+ # calculation.
439438 if julian == - 1 :
440439 # Need to add 1 to result since first day of the year is 1, not 0.
441440 julian = datetime_date (year , month , day ).toordinal () - \
442441 datetime_date (year , 1 , 1 ).toordinal () + 1
443442 else : # Assume that if they bothered to include Julian day it will
444- #be accurate
443+ # be accurate.
445444 datetime_result = datetime_date .fromordinal ((julian - 1 ) + datetime_date (year , 1 , 1 ).toordinal ())
446445 year = datetime_result .year
447446 month = datetime_result .month
0 commit comments