Add support for %U and %W to contribute to calculating the date when the year

and day of the week are specified.

Closes bug #1045381.
This commit is contained in:
Brett Cannon 2004-10-18 01:37:57 +00:00
parent be8370dc9c
commit 8abcc5d533
4 changed files with 72 additions and 4 deletions

View file

@ -247,11 +247,11 @@ specification, and are replaced by the indicated characters in the
\lineiii{\%S}{Second as a decimal number [00,61].}{(2)}
\lineiii{\%U}{Week number of the year (Sunday as the first day of the
week) as a decimal number [00,53]. All days in a new year
preceding the first Sunday are considered to be in week 0.}{}
preceding the first Sunday are considered to be in week 0.}{(3)}
\lineiii{\%w}{Weekday as a decimal number [0(Sunday),6].}{}
\lineiii{\%W}{Week number of the year (Monday as the first day of the
week) as a decimal number [00,53]. All days in a new year
preceding the first Monday are considered to be in week 0.}{}
preceding the first Monday are considered to be in week 0.}{(3)}
\lineiii{\%x}{Locale's appropriate date representation.}{}
\lineiii{\%X}{Locale's appropriate time representation.}{}
\lineiii{\%y}{Year without century as a decimal number [00,99].}{}
@ -271,6 +271,9 @@ Notes:
\item[(2)]
The range really is \code{0} to \code{61}; this accounts for leap
seconds and the (very rare) double leap seconds.
\item[(3)]
\code{\%U} and \code{\%W} are only used in calculations when the day of the
week and the year are specified.
\end{description}
Here is an example, a format for dates compatible with that specified

View file

@ -212,7 +212,7 @@ def __init__(self, locale_time=None):
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

View file

@ -6,6 +6,7 @@
import re
import sys
from test import test_support
from datetime import date as datetime_date
import _strptime
@ -417,6 +418,27 @@ def test_day_of_week_calculation(self):
"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."""

View file

@ -22,7 +22,8 @@ Extension Modules
Library
-------
...
- Bug #1045381: time.strptime() can now infer the date using %U or %W (week of
the year) when the day of the week and year are also specified.
Build
-----