Backport fix for bug #1643943.
This commit is contained in:
parent
817b489422
commit
6d8e5ad09d
|
@ -273,6 +273,27 @@ _TimeRE_cache = TimeRE()
|
||||||
_CACHE_MAX_SIZE = 5 # Max number of regexes stored in _regex_cache
|
_CACHE_MAX_SIZE = 5 # Max number of regexes stored in _regex_cache
|
||||||
_regex_cache = {}
|
_regex_cache = {}
|
||||||
|
|
||||||
|
def _calc_julian_from_U_or_W(year, week_of_year, day_of_week, week_starts_Mon):
|
||||||
|
"""Calculate the Julian day based on the year, week of the year, and day of
|
||||||
|
the week, with week_start_day representing whether the week of the year
|
||||||
|
assumes the week starts on Sunday or Monday (6 or 0)."""
|
||||||
|
first_weekday = datetime_date(year, 1, 1).weekday()
|
||||||
|
# If we are dealing with the %U directive (week starts on Sunday), it's
|
||||||
|
# easier to just shift the view to Sunday being the first day of the
|
||||||
|
# week.
|
||||||
|
if not week_starts_Mon:
|
||||||
|
first_weekday = (first_weekday + 1) % 7
|
||||||
|
day_of_week = (day_of_week + 1) % 7
|
||||||
|
# Need to watch out for a week 0 (when the first day of the year is not
|
||||||
|
# the same as that specified by %U or %W).
|
||||||
|
week_0_length = (7 - first_weekday) % 7
|
||||||
|
if week_of_year == 0:
|
||||||
|
return 1 + day_of_week - first_weekday
|
||||||
|
else:
|
||||||
|
days_to_week = week_0_length + (7 * (week_of_year - 1))
|
||||||
|
return 1 + days_to_week + day_of_week
|
||||||
|
|
||||||
|
|
||||||
def strptime(data_string, format="%a %b %d %H:%M:%S %Y"):
|
def strptime(data_string, format="%a %b %d %H:%M:%S %Y"):
|
||||||
"""Return a time struct based on the input string and the format string."""
|
"""Return a time struct based on the input string and the format string."""
|
||||||
global _TimeRE_cache, _regex_cache
|
global _TimeRE_cache, _regex_cache
|
||||||
|
@ -385,10 +406,10 @@ def strptime(data_string, format="%a %b %d %H:%M:%S %Y"):
|
||||||
elif group_key in ('U', 'W'):
|
elif group_key in ('U', 'W'):
|
||||||
week_of_year = int(found_dict[group_key])
|
week_of_year = int(found_dict[group_key])
|
||||||
if group_key == 'U':
|
if group_key == 'U':
|
||||||
# U starts week on Sunday
|
# U starts week on Sunday.
|
||||||
week_of_year_start = 6
|
week_of_year_start = 6
|
||||||
else:
|
else:
|
||||||
# W starts week on Monday
|
# W starts week on Monday.
|
||||||
week_of_year_start = 0
|
week_of_year_start = 0
|
||||||
elif group_key == 'Z':
|
elif group_key == 'Z':
|
||||||
# Since -1 is default value only need to worry about setting tz if
|
# 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"):
|
||||||
tz = value
|
tz = value
|
||||||
break
|
break
|
||||||
# If we know the week of the year and what day of that week, we can figure
|
# If we know the week of the year and what day of that week, we can figure
|
||||||
# out the Julian day of the year
|
# out the Julian day of the year.
|
||||||
# Calculations below assume 0 is a Monday
|
|
||||||
if julian == -1 and week_of_year != -1 and weekday != -1:
|
if julian == -1 and week_of_year != -1 and weekday != -1:
|
||||||
# Calculate how many days in week 0
|
week_starts_Mon = True if week_of_year_start == 0 else False
|
||||||
first_weekday = datetime_date(year, 1, 1).weekday()
|
julian = _calc_julian_from_U_or_W(year, week_of_year, weekday,
|
||||||
preceeding_days = 7 - first_weekday
|
week_starts_Mon)
|
||||||
if preceeding_days == 7:
|
|
||||||
preceeding_days = 0
|
|
||||||
# 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
|
|
||||||
# If a year starts and ends on a Monday but a week is specified to
|
|
||||||
# start on a Sunday we need to up the week to counter-balance the fact
|
|
||||||
# that with %W that first Monday starts week 1 while with %U that is
|
|
||||||
# week 0 and thus shifts everything by a week
|
|
||||||
if weekday == 0 and first_weekday == 0 and week_of_year_start == 6:
|
|
||||||
week_of_year += 1
|
|
||||||
# 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 week_of_year == 0:
|
|
||||||
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
|
# Cannot pre-calculate datetime_date() since can change in Julian
|
||||||
#calculation and thus could have different value for the day of the week
|
# calculation and thus could have different value for the day of the week
|
||||||
#calculation
|
# calculation.
|
||||||
if julian == -1:
|
if julian == -1:
|
||||||
# Need to add 1 to result since first day of the year is 1, not 0.
|
# Need to add 1 to result since first day of the year is 1, not 0.
|
||||||
julian = datetime_date(year, month, day).toordinal() - \
|
julian = datetime_date(year, month, day).toordinal() - \
|
||||||
datetime_date(year, 1, 1).toordinal() + 1
|
datetime_date(year, 1, 1).toordinal() + 1
|
||||||
else: # Assume that if they bothered to include Julian day it will
|
else: # Assume that if they bothered to include Julian day it will
|
||||||
#be accurate
|
# be accurate.
|
||||||
datetime_result = datetime_date.fromordinal((julian - 1) + datetime_date(year, 1, 1).toordinal())
|
datetime_result = datetime_date.fromordinal((julian - 1) + datetime_date(year, 1, 1).toordinal())
|
||||||
year = datetime_result.year
|
year = datetime_result.year
|
||||||
month = datetime_result.month
|
month = datetime_result.month
|
||||||
|
|
|
@ -463,6 +463,10 @@ class CalculationTests(unittest.TestCase):
|
||||||
"of the year")
|
"of the year")
|
||||||
test_helper((1917, 12, 31), "Dec 31 on Monday with year starting and "
|
test_helper((1917, 12, 31), "Dec 31 on Monday with year starting and "
|
||||||
"ending on Monday")
|
"ending on Monday")
|
||||||
|
test_helper((2007, 01, 07), "First Sunday of 2007")
|
||||||
|
test_helper((2007, 01, 14), "Second Sunday of 2007")
|
||||||
|
test_helper((2006, 12, 31), "Last Sunday of 2006")
|
||||||
|
test_helper((2006, 12, 24), "Second to last Sunday of 2006")
|
||||||
|
|
||||||
|
|
||||||
class CacheTests(unittest.TestCase):
|
class CacheTests(unittest.TestCase):
|
||||||
|
|
|
@ -154,6 +154,8 @@ Extension Modules
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Bug #1643943: Fix %U handling for time.strptime.
|
||||||
|
|
||||||
- Patch #1643874: memory leak in ctypes fixed.
|
- Patch #1643874: memory leak in ctypes fixed.
|
||||||
|
|
||||||
- Bug #1598181: Avoid O(N**2) bottleneck in subprocess communicate().
|
- Bug #1598181: Avoid O(N**2) bottleneck in subprocess communicate().
|
||||||
|
|
Loading…
Reference in New Issue