Index: Lib/_strptime.py =================================================================== --- Lib/_strptime.py (revision 41910) +++ Lib/_strptime.py (working copy) @@ -45,6 +45,8 @@ class LocaleTime(object): LC_date_time -- format string for date/time representation (string) LC_date -- format string for date representation (string) LC_time -- format string for time representation (string) + LC_time_ampm -- format string for time representation (string) with + the locale's AM/PM timezone -- daylight- and non-daylight-savings timezone representation (2-item list of sets) lang -- Language used by instance (2-item tuple) @@ -124,10 +126,11 @@ class LocaleTime(object): # values within the format string is very important; it eliminates # possible ambiguity for what something represents. time_tuple = time.struct_time((1999,3,17,22,44,55,2,76,0)) - date_time = [None, None, None] + date_time = [None, None, None, None] date_time[0] = time.strftime("%c", time_tuple).lower() date_time[1] = time.strftime("%x", time_tuple).lower() date_time[2] = time.strftime("%X", time_tuple).lower() + date_time[3] = time.strftime("%r", time_tuple).lower() replacement_pairs = [('%', '%%'), (self.f_weekday[2], '%A'), (self.f_month[3], '%B'), (self.a_weekday[2], '%a'), (self.a_month[3], '%b'), (self.am_pm[1], '%p'), @@ -138,7 +141,7 @@ class LocaleTime(object): ('2', '%w'), ('10', '%I')] replacement_pairs.extend([(tz, "%Z") for tz_values in self.timezone for tz in tz_values]) - for offset,directive in ((0,'%c'), (1,'%x'), (2,'%X')): + for offset,directive in ((0,'%c'), (1,'%x'), (2,'%X'), (3,'%r')): current_format = date_time[offset] for old, new in replacement_pairs: # Must deal with possible lack of locale info @@ -159,6 +162,7 @@ class LocaleTime(object): self.LC_date_time = date_time[0] self.LC_date = date_time[1] self.LC_time = date_time[2] + self.LC_time_ampm = date_time[3] def __calc_timezone(self): # Set self.timezone by using time.tzname. @@ -197,7 +201,9 @@ class TimeRE(dict): 'I': r"(?P1[0-2]|0[1-9]|[1-9])", 'j': r"(?P36[0-6]|3[0-5]\d|[1-2]\d\d|0[1-9]\d|00[1-9]|[1-9]\d|0[1-9]|[1-9])", 'm': r"(?P1[0-2]|0[1-9]|[1-9])", + 'n': r"\s*", 'M': r"(?P[0-5]\d|\d)", + 't': r"\s*", 'S': r"(?P6[0-1]|[0-5]\d|\d)", 'U': r"(?P5[0-3]|[0-4]\d|\d)", 'w': r"(?P[0-6])", @@ -219,7 +225,16 @@ class TimeRE(dict): 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)) - + base.__setitem__('r', self.pattern(self.locale_time.LC_time_ampm)) + base.__setitem__('e', base.__getitem__('d')) + base.__setitem__('h', base.__getitem__('b')) + base.__setitem__('D', (base.__getitem__('m') + '/' + + base.__getitem__('d') + '/' + + base.__getitem__('y'))) + base.__setitem__('R', base.__getitem__('H') + ':' + base.__getitem__('M')) + base.__setitem__('T', (base.__getitem__('H') + ':' + + base.__getitem__('M') + ':' + + base.__getitem__('S'))) def __seqToRE(self, to_convert, directive): """Convert a list to a regex string for matching a directive. Index: Lib/test/test_strptime.py =================================================================== --- Lib/test/test_strptime.py (revision 41910) +++ Lib/test/test_strptime.py (working copy) @@ -97,6 +97,10 @@ class LocaleTime_Tests(unittest.TestCase self.failUnless(strftime_output == time.strftime(self.LT_ins.LC_time, magic_date), "LC_time incorrect") + strftime_output = time.strftime("%r", magic_date) + self.failUnless(strftime_output == time.strftime(self.LT_ins.LC_time_ampm, + magic_date), + "LC_time incorrect") LT = _strptime.LocaleTime() LT.am_pm = ('', '') self.failUnless(LT.LC_time, "LocaleTime's LC directives cannot handle " @@ -335,6 +339,11 @@ class StrptimeTests(unittest.TestCase): for position in range(3,6): self.helper('X', position) + def test_time_ampm(self): + # Test %r directive + for position in range(3,6): + self.helper('r', position) + def test_percent(self): # Make sure % signs are handled properly strf_output = time.strftime("%m %% %Y", self.time_tuple) @@ -361,6 +370,22 @@ class StrptimeTests(unittest.TestCase): "Default values for strptime() are incorrect;" " %s != %s" % (strp_output, defaults)) + def test_aliases(self): + self.assertEqual(_strptime.strptime('1', '%e'), + _strptime.strptime('1', '%d')) + self.assertEqual(_strptime.strptime('sep', '%h'), + _strptime.strptime('sep', '%b')) + self.assertEqual(_strptime.strptime('9/7/81', '%m/%d/%y'), + _strptime.strptime('9/7/81', '%D')) + self.assertEqual(_strptime.strptime('11:38', '%H:%M'), + _strptime.strptime('11:38', '%R')) + self.assertEqual(_strptime.strptime('11:38:34', '%H:%M:%S'), + _strptime.strptime('11:38:34', '%T')) + + def test_whitespace(self): + self.failUnless(_strptime.strptime(' \t\n\r\f\v', '%n')) + self.failUnless(_strptime.strptime(' \t\n\r\f\v', '%t')) + def test_escaping(self): # Make sure all characters that have regex significance are escaped. # Parentheses are in a purposeful order; will cause an error of Index: Lib/test/test_time.py =================================================================== --- Lib/test/test_time.py (revision 41910) +++ Lib/test/test_time.py (working copy) @@ -95,9 +95,9 @@ class TimeTestCase(unittest.TestCase): def test_strptime(self): tt = time.gmtime(self.t) - for directive in ('a', 'A', 'b', 'B', 'c', 'd', 'H', 'I', - 'j', 'm', 'M', 'p', 'S', - 'U', 'w', 'W', 'x', 'X', 'y', 'Y', 'Z', '%'): + for directive in ('a', 'A', 'b', 'B', 'c', 'd', 'D', 'e', 'h', 'H', + 'I', 'j', 'n', 'm', 'M', 'p', 'r', 'R', 'S', 't', + 'T', 'U', 'w', 'W', 'x', 'X', 'y', 'Y', 'Z', '%'): format = ' %' + directive try: time.strptime(time.strftime(format, tt), format) Index: Doc/lib/libtime.tex =================================================================== --- Doc/lib/libtime.tex (revision 41910) +++ Doc/lib/libtime.tex (working copy) @@ -239,13 +239,19 @@ specification, and are replaced by the i \lineiii{\%B}{Locale's full month name.}{} \lineiii{\%c}{Locale's appropriate date and time representation.}{} \lineiii{\%d}{Day of the month as a decimal number [01,31].}{} + \lineiii{\%D}{Equivalent to \%m/\%d/\%y.}{} + \lineiii{\%e}{Equivalent to \%d.}{} + \lineiii{\%h}{Equivalent to \%b.}{} \lineiii{\%H}{Hour (24-hour clock) as a decimal number [00,23].}{} \lineiii{\%I}{Hour (12-hour clock) as a decimal number [01,12].}{} \lineiii{\%j}{Day of the year as a decimal number [001,366].}{} \lineiii{\%m}{Month as a decimal number [01,12].}{} \lineiii{\%M}{Minute as a decimal number [00,59].}{} \lineiii{\%p}{Locale's equivalent of either AM or PM.}{(1)} + \lineiii{\%r}{The 12-hour clock time}{} + \lineiii{\%R}{Equivalent to \%H:\%M.}{} \lineiii{\%S}{Second as a decimal number [00,61].}{(2)} + \lineiii{\%T}{Equivalent to \%H:\%M:\%S.}{} \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.}{(3)}