diff options
Diffstat (limited to 'Lib/_strptime.py')
-rw-r--r-- | Lib/_strptime.py | 372 |
1 files changed, 200 insertions, 172 deletions
diff --git a/Lib/_strptime.py b/Lib/_strptime.py index 6174718..263a2a6 100644 --- a/Lib/_strptime.py +++ b/Lib/_strptime.py @@ -18,7 +18,6 @@ FUNCTIONS: Requires Python 2.2.1 or higher. Can be used in Python 2.2 if the following line is added: >>> True = 1; False = 0 - """ import time import locale @@ -27,12 +26,15 @@ from re import compile as re_compile from re import IGNORECASE from string import whitespace as whitespace_string -__version__ = (2,1,5) +__version__ = (2,1,6) __author__ = "Brett Cannon" __email__ = "drifty@bigfoot.com" __all__ = ['strptime'] +RegexpType = type(re_compile('')) + + class LocaleTime(object): """Stores and handles locale-specific information related to time. @@ -52,33 +54,38 @@ class LocaleTime(object): (3-item list; code tacks on blank item at end for possible lack of timezone such as UTC) lang -- Language used by instance (string) - """ def __init__(self, f_weekday=None, a_weekday=None, f_month=None, - a_month=None, am_pm=None, LC_date_time=None, LC_time=None, LC_date=None, - timezone=None, lang=None): + a_month=None, am_pm=None, LC_date_time=None, LC_time=None, + LC_date=None, timezone=None, lang=None): """Optionally set attributes with passed-in values.""" - if f_weekday is None: self.__f_weekday = None - elif len(f_weekday) == 7: self.__f_weekday = list(f_weekday) + if f_weekday is None: + self.__f_weekday = None + elif len(f_weekday) == 7: + self.__f_weekday = list(f_weekday) else: raise TypeError("full weekday names must be a 7-item sequence") - if a_weekday is None: self.__a_weekday = None - elif len(a_weekday) == 7: self.__a_weekday = list(a_weekday) + if a_weekday is None: + self.__a_weekday = None + elif len(a_weekday) == 7: + self.__a_weekday = list(a_weekday) else: raise TypeError( - "abbreviated weekday names must be a 7-item sequence") - if f_month is None: self.__f_month = None + "abbreviated weekday names must be a 7-item sequence") + if f_month is None: + self.__f_month = None elif len(f_month) == 12: self.__f_month = self.__pad(f_month, True) else: raise TypeError("full month names must be a 12-item sequence") - if a_month is None: self.__a_month = None + if a_month is None: + self.__a_month = None elif len(a_month) == 12: self.__a_month = self.__pad(a_month, True) else: raise TypeError( - "abbreviated month names must be a 12-item sequence") + "abbreviated month names must be a 12-item sequence") if am_pm is None: self.__am_pm = None elif len(am_pm) == 2: @@ -97,112 +104,130 @@ class LocaleTime(object): self.__lang = lang def __pad(self, seq, front): - """Add '' to seq to either front (is True), else the back.""" + # Add '' to seq to either front (is True), else the back. seq = list(seq) - if front: seq.insert(0, '') - else: seq.append('') + if front: + seq.insert(0, '') + else: + seq.append('') return seq def __set_nothing(self, stuff): - """Raise TypeError when trying to set an attribute.""" + # Raise TypeError when trying to set an attribute. raise TypeError("attribute does not support assignment") def __get_f_weekday(self): - """Fetch self.f_weekday.""" - if not self.__f_weekday: self.__calc_weekday() + # Fetch self.f_weekday. + if not self.__f_weekday: + self.__calc_weekday() return self.__f_weekday def __get_a_weekday(self): - """Fetch self.a_weekday.""" - if not self.__a_weekday: self.__calc_weekday() + # Fetch self.a_weekday. + if not self.__a_weekday: + self.__calc_weekday() return self.__a_weekday f_weekday = property(__get_f_weekday, __set_nothing, - doc="Full weekday names") + doc="Full weekday names") a_weekday = property(__get_a_weekday, __set_nothing, - doc="Abbreviated weekday names") + doc="Abbreviated weekday names") def __get_f_month(self): - """Fetch self.f_month.""" - if not self.__f_month: self.__calc_month() + # Fetch self.f_month. + if not self.__f_month: + self.__calc_month() return self.__f_month def __get_a_month(self): - """Fetch self.a_month.""" - if not self.__a_month: self.__calc_month() + # Fetch self.a_month. + if not self.__a_month: + self.__calc_month() return self.__a_month f_month = property(__get_f_month, __set_nothing, - doc="Full month names (dummy value at index 0)") + doc="Full month names (dummy value at index 0)") a_month = property(__get_a_month, __set_nothing, - doc="Abbreviated month names (dummy value at index 0)") + doc="Abbreviated month names (dummy value at index 0)") def __get_am_pm(self): - """Fetch self.am_pm.""" - if not self.__am_pm: self.__calc_am_pm() + # Fetch self.am_pm. + if not self.__am_pm: + self.__calc_am_pm() return self.__am_pm am_pm = property(__get_am_pm, __set_nothing, doc="AM/PM representation") def __get_timezone(self): - """Fetch self.timezone.""" - if not self.__timezone: self.__calc_timezone() + # Fetch self.timezone. + if not self.__timezone: + self.__calc_timezone() return self.__timezone timezone = property(__get_timezone, __set_nothing, doc="Timezone representation (dummy value at index 2)") def __get_LC_date_time(self): - """Fetch self.LC_date_time.""" - if not self.__LC_date_time: self.__calc_date_time() + # Fetch self.LC_date_time. + if not self.__LC_date_time: + self.__calc_date_time() return self.__LC_date_time def __get_LC_date(self): - """Fetch self.LC_date.""" - if not self.__LC_date: self.__calc_date_time() + # Fetch self.LC_date. + if not self.__LC_date: + self.__calc_date_time() return self.__LC_date def __get_LC_time(self): - """Fetch self.LC_time.""" - if not self.__LC_time: self.__calc_date_time() + # Fetch self.LC_time. + if not self.__LC_time: + self.__calc_date_time() return self.__LC_time - LC_date_time = property(__get_LC_date_time, __set_nothing, - doc="Format string for locale's date/time representation ('%c' format)") + LC_date_time = property( + __get_LC_date_time, __set_nothing, + doc= + "Format string for locale's date/time representation ('%c' format)") LC_date = property(__get_LC_date, __set_nothing, doc="Format string for locale's date representation ('%x' format)") LC_time = property(__get_LC_time, __set_nothing, doc="Format string for locale's time representation ('%X' format)") def __get_lang(self): - """Fetch self.lang.""" - if not self.__lang: self.__calc_lang() + # Fetch self.lang. + if not self.__lang: + self.__calc_lang() return self.__lang - lang = property(__get_lang, __set_nothing, doc="Language used for instance") + lang = property(__get_lang, __set_nothing, + doc="Language used for instance") def __calc_weekday(self): - """Set self.__a_weekday and self.__f_weekday using the calendar module.""" + # Set self.__a_weekday and self.__f_weekday using the calendar + # module. a_weekday = [calendar.day_abbr[i] for i in range(7)] f_weekday = [calendar.day_name[i] for i in range(7)] - if not self.__a_weekday: self.__a_weekday = a_weekday - if not self.__f_weekday: self.__f_weekday = f_weekday + if not self.__a_weekday: + self.__a_weekday = a_weekday + if not self.__f_weekday: + self.__f_weekday = f_weekday def __calc_month(self): - """Set self.__f_month and self.__a_month using the calendar module.""" + # Set self.__f_month and self.__a_month using the calendar module. a_month = [calendar.month_abbr[i] for i in range(13)] f_month = [calendar.month_name[i] for i in range(13)] - if not self.__a_month: self.__a_month = a_month - if not self.__f_month: self.__f_month = f_month + if not self.__a_month: + self.__a_month = a_month + if not self.__f_month: + self.__f_month = f_month def __calc_am_pm(self): - """Set self.__am_pm by using time.strftime(). + # Set self.__am_pm by using time.strftime(). - The magic date (2002, 3, 17, hour, 44, 44, 2, 76, 0) is not really - that magical; just happened to have used it everywhere else where a - static date was needed. - - """ + # The magic date (1999,3,17,hour,44,55,2,76,0) is not really that + # magical; just happened to have used it everywhere else where a + # static date was needed. am_pm = [] for hour in (01,22): time_tuple = time.struct_time((1999,3,17,hour,44,55,2,76,0)) @@ -210,14 +235,13 @@ class LocaleTime(object): self.__am_pm = am_pm def __calc_date_time(self): - """Set self.__date_time, self.__date, & self.__time by using time.strftime(). - - Use (1999,3,17,22,44,55,2,76,0) for magic date because the amount of - overloaded numbers is minimized. The order in which searches for - values within the format string is very important; it eliminates - possible ambiguity for what something represents. + # Set self.__date_time, self.__date, & self.__time by using + # time.strftime(). - """ + # Use (1999,3,17,22,44,55,2,76,0) for magic date because the amount of + # overloaded numbers is minimized. The order in which searches for + # 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[0] = time.strftime("%c", time_tuple) @@ -249,37 +273,38 @@ class LocaleTime(object): else: U_W = '%W' date_time[offset] = current_format.replace('11', U_W) - if not self.__LC_date_time: self.__LC_date_time = date_time[0] - if not self.__LC_date: self.__LC_date = date_time[1] - if not self.__LC_time: self.__LC_time = date_time[2] + if not self.__LC_date_time: + self.__LC_date_time = date_time[0] + if not self.__LC_date: + self.__LC_date = date_time[1] + if not self.__LC_time: + self.__LC_time = date_time[2] def __calc_timezone(self): - """Set self.__timezone by using time.tzname. - - Empty string used for matching when timezone is not used/needed such - as with UTC. - - """ + # Set self.__timezone by using time.tzname. + # + # Empty string used for matching when timezone is not used/needed such + # as with UTC. self.__timezone = self.__pad(time.tzname, 0) def __calc_lang(self): - """Set self.lang by using locale.getlocale() or - locale.getdefaultlocale(). - - """ + # Set self.lang by using locale.getlocale() or + # locale.getdefaultlocale(). current_lang = locale.getlocale(locale.LC_TIME)[0] - if current_lang: self.__lang = current_lang - else: self.__lang = locale.getdefaultlocale()[0] + if current_lang: + self.__lang = current_lang + else: + self.__lang = locale.getdefaultlocale()[0] + class TimeRE(dict): """Handle conversion from format directives to regexes.""" def __init__(self, locale_time=LocaleTime()): - """Initialize instance with non-locale regexes and store LocaleTime object.""" + """Init inst with non-locale regexes and store LocaleTime object.""" super(TimeRE,self).__init__({ - 'd': r"(?P<d>3[0-1]|[0-2]\d|\d| \d)", #The " \d" option is - #to make %c from ANSI - #C work + # The " \d" option is to make %c from ANSI C work + 'd': r"(?P<d>3[0-1]|[0-2]\d|\d| \d)", 'H': r"(?P<H>2[0-3]|[0-1]\d|\d)", 'I': r"(?P<I>0\d|1[0-2]|\d)", 'j': r"(?P<j>(?:3[0-5]\d|6[0-6])|[0-2]\d\d|\d)", @@ -288,7 +313,7 @@ class TimeRE(dict): 'S': r"(?P<S>6[0-1]|[0-5]\d|\d)", 'U': r"(?P<U>5[0-3]|[0-4]\d|\d)", 'w': r"(?P<w>[0-6])", - 'W': r"(?P<W>5[0-3]|[0-4]\d|\d)", #Same as U + 'W': r"(?P<W>5[0-3]|[0-4]\d|\d)", # Same as U 'y': r"(?P<y>\d\d)", 'Y': r"(?P<Y>\d\d\d\d)"}) self.locale_time = locale_time @@ -300,16 +325,16 @@ class TimeRE(dict): except KeyError: if fetch == 'A': self[fetch] = self.__seqToRE(self.locale_time.f_weekday, - fetch) + fetch) elif fetch == 'a': self[fetch] = self.__seqToRE(self.locale_time.a_weekday, - fetch) + fetch) elif fetch == 'B': self[fetch] = self.__seqToRE(self.locale_time.f_month[1:], - fetch) + fetch) elif fetch == 'b': self[fetch] = self.__seqToRE(self.locale_time.a_month[1:], - fetch) + fetch) elif fetch == 'c': self[fetch] = self.pattern(self.locale_time.LC_date_time) elif fetch == 'p': @@ -320,7 +345,7 @@ class TimeRE(dict): self[fetch] = self.pattern(self.locale_time.LC_time) elif fetch == 'Z': self[fetch] = self.__seqToRE(self.locale_time.timezone, - fetch) + fetch) elif fetch == '%': return '%' return super(TimeRE,self).__getitem__(fetch) @@ -333,15 +358,18 @@ class TimeRE(dict): Done in case for some strange reason that names in the locale only differ by a suffix and thus want the name with the suffix to match first. - """ - try: a_length = len(a) - except TypeError: a_length = 0 - try: b_length = len(b) - except TypeError: b_length = 0 + try: + a_length = len(a) + except TypeError: + a_length = 0 + try: + b_length = len(b) + except TypeError: + b_length = 0 return cmp(b_length, a_length) - to_convert = to_convert[:] #Don't want to change value in-place. + to_convert = to_convert[:] # Don't want to change value in-place. to_convert.sort(sorter) regex = '(?P<%s>' % directive for item in to_convert: @@ -358,8 +386,8 @@ class TimeRE(dict): while format.find('%') != -1: directive_index = format.index('%')+1 processed_format = "%s%s%s" % (processed_format, - format[:directive_index-1], - self[format[directive_index]]) + format[:directive_index-1], + self[format[directive_index]]) format = format[directive_index+1:] return "%s%s" % (processed_format, format) @@ -370,19 +398,18 @@ class TimeRE(dict): def strptime(data_string, format="%a %b %d %H:%M:%S %Y"): - """Convert data_string to a time struct based on the format string or re object; will return an re object for format if data_string is False. - - The object passed in for format may either be a re object compiled by - strptime() or a format string. If False is passed in for data_string - then an re object for format will be returned. The re object - must be used with the same language as used to compile the re object. + """Return a time struct based on the input data and the format string. + The format argument may either be a regular expression object compiled by + strptime(), or a format string. If False is passed in for data_string + then the re object calculated for format will be returned. The re object + must be used with the same locale as was used to compile the re object. """ locale_time = LocaleTime() - if isinstance(format, type(re_compile(''))): + if isinstance(format, RegexpType): if format.pattern.find(locale_time.lang) == -1: - raise TypeError("re object not created with same language as \ - LocaleTime instance") + raise TypeError("re object not created with same language as " + "LocaleTime instance") else: compiled_re = format else: @@ -393,59 +420,56 @@ def strptime(data_string, format="%a %b %d %H:%M:%S %Y"): found = compiled_re.match(data_string) if not found: raise ValueError("time data did not match format") - year = month = day = hour = minute = second = weekday = julian = tz = -1 + year = month = day = hour = minute = second = weekday = julian = tz =-1 found_dict = found.groupdict() for group_key in found_dict.iterkeys(): - if group_key in 'yY': - if group_key is 'y': - year = int("%s%s" % (time.strftime("%Y")[:-2], found_dict['y'])) - else: - year = int(found_dict['Y']) - elif group_key in 'Bbm': - if group_key is 'm': - month = int(found_dict['m']) - elif group_key is 'B': - month = locale_time.f_month.index(found_dict['B']) - else: - month = locale_time.a_month.index(found_dict['b']) - elif group_key is 'd': + if group_key == 'y': + year = int("%s%s" % + (time.strftime("%Y")[:-2], found_dict['y'])) + elif group_key == 'Y': + year = int(found_dict['Y']) + elif group_key == 'm': + month = int(found_dict['m']) + elif group_key == 'B': + month = locale_time.f_month.index(found_dict['B']) + elif group_key == 'b': + month = locale_time.a_month.index(found_dict['b']) + elif group_key == 'd': day = int(found_dict['d']) - elif group_key in 'HI': - if group_key is 'H': - hour = int(found_dict['H']) - else: - hour = int(found_dict['I']) - ampm = found_dict.get('p') - if ampm == locale_time.am_pm[0]: - # We're in AM so the hour is correct unless we're - # looking at 12 midnight. - # 12 midnight == 12 AM == hour 0 - if hour == 12: - hour = 0 - elif ampm == locale_time.am_pm[1]: - # We're in PM so we need to add 12 to the hour unless - # we're looking at 12 noon. - # 12 noon == 12 PM == hour 12 - if hour != 12: - hour += 12 - elif group_key is 'M': + elif group_key is 'H': + hour = int(found_dict['H']) + elif group_key == 'I': + hour = int(found_dict['I']) + ampm = found_dict.get('p') + if ampm == locale_time.am_pm[0]: + # We're in AM so the hour is correct unless we're + # looking at 12 midnight. + # 12 midnight == 12 AM == hour 0 + if hour == 12: + hour = 0 + elif ampm == locale_time.am_pm[1]: + # We're in PM so we need to add 12 to the hour unless + # we're looking at 12 noon. + # 12 noon == 12 PM == hour 12 + if hour != 12: + hour += 12 + elif group_key == 'M': minute = int(found_dict['M']) - elif group_key is 'S': + elif group_key == 'S': second = int(found_dict['S']) - elif group_key in 'Aaw': - if group_key is 'A': - weekday = locale_time.f_weekday.index(found_dict['A']) - elif group_key is 'a': - weekday = locale_time.a_weekday.index(found_dict['a']) + elif group_key == 'A': + weekday = locale_time.f_weekday.index(found_dict['A']) + elif group_key == 'a': + weekday = locale_time.a_weekday.index(found_dict['a']) + elif group_key == 'w': + weekday = int(found_dict['w']) + if weekday == 0: + weekday = 6 else: - weekday = int(found_dict['w']) - if weekday == 0: - weekday = 6 - else: - weekday -= 1 - elif group_key is 'j': + weekday -= 1 + elif group_key == 'j': julian = int(found_dict['j']) - elif group_key is 'Z': + elif group_key == 'Z': if locale_time.timezone[0] == found_dict['Z']: tz = 0 elif locale_time.timezone[1] == found_dict['Z']: @@ -455,40 +479,44 @@ def strptime(data_string, format="%a %b %d %H:%M:%S %Y"): if julian == -1 and year != -1 and month != -1 and day != -1: julian = julianday(year, month, day) if (month == -1 or day == -1) and julian != -1 and year != -1: - year,month,day = gregorian(julian, year) + year, month, day = gregorian(julian, year) if weekday == -1 and year != -1 and month != -1 and day != -1: weekday = dayofweek(year, month, day) - return time.struct_time((year,month,day,hour,minute,second,weekday, - julian,tz)) + return time.struct_time( + (year,month,day,hour,minute,second,weekday, julian,tz)) def firstjulian(year): """Calculate the Julian date up until the first of the year.""" - return ((146097*(year+4799))//400)-31738 + return ((146097 * (year + 4799)) // 400) - 31738 def julianday(year, month, day): - """Calculate the Julian day since the beginning of the year from the Gregorian date.""" - a = (14-month)//12 - return (day-32045+(((153*(month+(12*a)-3))+2)//5)+\ - ((146097*(year+4800-a))//400))-firstjulian(year)+1 + """Calculate the Julian day since the beginning of the year. + Calculated from the Gregorian date. + """ + a = (14 - month) // 12 + return (day - 32045 + + (((153 * (month + (12 * a) - 3)) + 2) // 5) + + ((146097 * (year + 4800 - a)) // 400)) - firstjulian(year) + 1 def gregorian(julian, year): - """Return a 3-item list containing the Gregorian date based on the Julian day.""" - a = 32043+julian+firstjulian(year) - b = ((4*a)+3)//146097 - c = a-((146097*b)//4) - d = ((4*c)+3)//1461 - e = c-((1461*d)//4) - m = ((5*e)+2)//153 - day = 1+e-(((153*m)+2)//5) - month = m+3-(12*(m//10)) - year = (100*b)+d-4800+(m//10) + """Return 3-item list containing Gregorian date based on the Julian day.""" + a = 32043 + julian + firstjulian(year) + b = ((4 * a) + 3) // 146097 + c = a - ((146097 * b) // 4) + d = ((4 * c) + 3) // 1461 + e = c - ((1461 * d) // 4) + m = ((5 * e) + 2) // 153 + day = 1 + e - (((153 * m) + 2) // 5) + month = m + 3 - (12 * (m // 10)) + year = (100 * b) + d - 4800 + (m // 10) return [year, month, day] def dayofweek(year, month, day): """Calculate the day of the week (Monday is 0).""" - a = (14-month)//12 - y = year-a - weekday = (day+y+((97*y)//400)+((31*(month+(12*a)-2))//12))%7 + a = (14 - month) // 12 + y = year - a + weekday = (day + y + ((97 * y) // 400) + + ((31 * (month + (12 * a) -2 )) // 12)) % 7 if weekday == 0: return 6 else: |