14adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao"""Strptime-related classes and functions. 24adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 34adfde8bc82dd39f59e0445588c3e599ada477dJosh GaoCLASSES: 44adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao LocaleTime -- Discovers and stores locale-specific time information 54adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao TimeRE -- Creates regexes for pattern matching a string of text containing 64adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao time information 74adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 84adfde8bc82dd39f59e0445588c3e599ada477dJosh GaoFUNCTIONS: 94adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao _getlang -- Figure out what language is being used for the locale 104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao strptime -- Calculates the time struct represented by the passed-in string 114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao""" 134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport time 144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport locale 154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoimport calendar 164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaofrom re import compile as re_compile 174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaofrom re import IGNORECASE 184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaofrom re import escape as re_escape 194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaofrom datetime import date as datetime_date 204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaotry: 214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao from thread import allocate_lock as _thread_allocate_lock 224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoexcept: 234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao from dummy_thread import allocate_lock as _thread_allocate_lock 244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao__all__ = [] 264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef _getlang(): 284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # Figure out what the current language is set to. 294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return locale.getlocale(locale.LC_TIME) 304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass LocaleTime(object): 324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """Stores and handles locale-specific information related to time. 334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ATTRIBUTES: 354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao f_weekday -- full weekday names (7-item list) 364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao a_weekday -- abbreviated weekday names (7-item list) 374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao f_month -- full month names (13-item list; dummy value in [0], which 384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao is added by code) 394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao a_month -- abbreviated month names (13-item list, dummy value in 404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao [0], which is added by code) 414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao am_pm -- AM/PM representation (2-item list) 424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao LC_date_time -- format string for date/time representation (string) 434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao LC_date -- format string for date representation (string) 444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao LC_time -- format string for time representation (string) 454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao timezone -- daylight- and non-daylight-savings timezone representation 464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao (2-item list of sets) 474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao lang -- Language used by instance (2-item tuple) 484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """ 494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __init__(self): 514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """Set all attributes. 524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao Order of methods called matters for dependency reasons. 544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao The locale language is set at the offset and then checked again before 564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao exiting. This is to make sure that the attributes were not set with a 574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao mix of information from more than one locale. This would most likely 584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao happen when using threads where one thread calls a locale-dependent 594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao function while another thread changes the locale while the function in 604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao the other thread is still running. Proper coding would call for 614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao locks to prevent changing the locale while locale-dependent code is 624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao running. The check here is done in case someone does not think about 634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao doing this. 644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao Only other possible issue is if someone changed the timezone and did 664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao not call tz.tzset . That is an issue for the programmer, though, 674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao since changing the timezone is worthless without that call. 684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """ 704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.lang = _getlang() 714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.__calc_weekday() 724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.__calc_month() 734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.__calc_am_pm() 744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.__calc_timezone() 754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.__calc_date_time() 764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if _getlang() != self.lang: 774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise ValueError("locale changed during initialization") 784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __pad(self, seq, front): 804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # Add '' to seq to either the front (is True), else the back. 814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao seq = list(seq) 824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if front: 834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao seq.insert(0, '') 844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao else: 854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao seq.append('') 864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return seq 874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __calc_weekday(self): 894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # Set self.a_weekday and self.f_weekday using the calendar 904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # module. 914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao a_weekday = [calendar.day_abbr[i].lower() for i in range(7)] 924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao f_weekday = [calendar.day_name[i].lower() for i in range(7)] 934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.a_weekday = a_weekday 944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.f_weekday = f_weekday 954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __calc_month(self): 974adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # Set self.f_month and self.a_month using the calendar module. 984adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao a_month = [calendar.month_abbr[i].lower() for i in range(13)] 994adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao f_month = [calendar.month_name[i].lower() for i in range(13)] 1004adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.a_month = a_month 1014adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.f_month = f_month 1024adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1034adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __calc_am_pm(self): 1044adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # Set self.am_pm by using time.strftime(). 1054adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1064adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # The magic date (1999,3,17,hour,44,55,2,76,0) is not really that 1074adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # magical; just happened to have used it everywhere else where a 1084adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # static date was needed. 1094adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao am_pm = [] 1104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao for hour in (01,22): 1114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao time_tuple = time.struct_time((1999,3,17,hour,44,55,2,76,0)) 1124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao am_pm.append(time.strftime("%p", time_tuple).lower()) 1134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.am_pm = am_pm 1144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __calc_date_time(self): 1164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # Set self.date_time, self.date, & self.time by using 1174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # time.strftime(). 1184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # Use (1999,3,17,22,44,55,2,76,0) for magic date because the amount of 1204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # overloaded numbers is minimized. The order in which searches for 1214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # values within the format string is very important; it eliminates 1224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # possible ambiguity for what something represents. 1234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao time_tuple = time.struct_time((1999,3,17,22,44,55,2,76,0)) 1244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao date_time = [None, None, None] 1254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao date_time[0] = time.strftime("%c", time_tuple).lower() 1264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao date_time[1] = time.strftime("%x", time_tuple).lower() 1274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao date_time[2] = time.strftime("%X", time_tuple).lower() 1284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao replacement_pairs = [('%', '%%'), (self.f_weekday[2], '%A'), 1294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao (self.f_month[3], '%B'), (self.a_weekday[2], '%a'), 1304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao (self.a_month[3], '%b'), (self.am_pm[1], '%p'), 1314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ('1999', '%Y'), ('99', '%y'), ('22', '%H'), 1324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ('44', '%M'), ('55', '%S'), ('76', '%j'), 1334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ('17', '%d'), ('03', '%m'), ('3', '%m'), 1344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # '3' needed for when no leading zero. 1354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ('2', '%w'), ('10', '%I')] 1364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao replacement_pairs.extend([(tz, "%Z") for tz_values in self.timezone 1374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao for tz in tz_values]) 1384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao for offset,directive in ((0,'%c'), (1,'%x'), (2,'%X')): 1394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao current_format = date_time[offset] 1404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao for old, new in replacement_pairs: 1414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # Must deal with possible lack of locale info 1424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # manifesting itself as the empty string (e.g., Swedish's 1434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # lack of AM/PM info) or a platform returning a tuple of empty 1444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # strings (e.g., MacOS 9 having timezone as ('','')). 1454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if old: 1464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao current_format = current_format.replace(old, new) 1474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # If %W is used, then Sunday, 2005-01-03 will fall on week 0 since 1484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # 2005-01-03 occurs before the first Monday of the year. Otherwise 1494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # %U is used. 1504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao time_tuple = time.struct_time((1999,1,3,1,1,1,6,3,0)) 1514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if '00' in time.strftime(directive, time_tuple): 1524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao U_W = '%W' 1534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao else: 1544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao U_W = '%U' 1554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao date_time[offset] = current_format.replace('11', U_W) 1564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.LC_date_time = date_time[0] 1574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.LC_date = date_time[1] 1584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.LC_time = date_time[2] 1594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __calc_timezone(self): 1614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # Set self.timezone by using time.tzname. 1624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # Do not worry about possibility of time.tzname[0] == timetzname[1] 1634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # and time.daylight; handle that in strptime . 1644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao try: 1654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao time.tzset() 1664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao except AttributeError: 1674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao pass 1684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao no_saving = frozenset(["utc", "gmt", time.tzname[0].lower()]) 1694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if time.daylight: 1704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao has_saving = frozenset([time.tzname[1].lower()]) 1714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao else: 1724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao has_saving = frozenset() 1734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.timezone = (no_saving, has_saving) 1744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaoclass TimeRE(dict): 1774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """Handle conversion from format directives to regexes.""" 1784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __init__(self, locale_time=None): 1804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """Create keys/values. 1814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao Order of execution is important for dependency reasons. 1834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 1844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """ 1854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if locale_time: 1864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.locale_time = locale_time 1874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao else: 1884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self.locale_time = LocaleTime() 1894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao base = super(TimeRE, self) 1904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao base.__init__({ 1914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # The " \d" part of the regex is to make %c from ANSI C work 1924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 'd': r"(?P<d>3[0-1]|[1-2]\d|0[1-9]|[1-9]| [1-9])", 1934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 'f': r"(?P<f>[0-9]{1,6})", 1944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 'H': r"(?P<H>2[0-3]|[0-1]\d|\d)", 1954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 'I': r"(?P<I>1[0-2]|0[1-9]|[1-9])", 1964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 'j': r"(?P<j>36[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])", 1974adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 'm': r"(?P<m>1[0-2]|0[1-9]|[1-9])", 1984adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 'M': r"(?P<M>[0-5]\d|\d)", 1994adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 'S': r"(?P<S>6[0-1]|[0-5]\d|\d)", 2004adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 'U': r"(?P<U>5[0-3]|[0-4]\d|\d)", 2014adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 'w': r"(?P<w>[0-6])", 2024adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # W is set below by using 'U' 2034adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 'y': r"(?P<y>\d\d)", 2044adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao #XXX: Does 'Y' need to worry about having less or more than 2054adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # 4 digits? 2064adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 'Y': r"(?P<Y>\d\d\d\d)", 2074adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 'A': self.__seqToRE(self.locale_time.f_weekday, 'A'), 2084adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 'a': self.__seqToRE(self.locale_time.a_weekday, 'a'), 2094adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 'B': self.__seqToRE(self.locale_time.f_month[1:], 'B'), 2104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 'b': self.__seqToRE(self.locale_time.a_month[1:], 'b'), 2114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 'p': self.__seqToRE(self.locale_time.am_pm, 'p'), 2124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 'Z': self.__seqToRE((tz for tz_names in self.locale_time.timezone 2134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao for tz in tz_names), 2144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 'Z'), 2154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao '%': '%'}) 2164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao base.__setitem__('W', base.__getitem__('U').replace('U', 'W')) 2174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao base.__setitem__('c', self.pattern(self.locale_time.LC_date_time)) 2184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao base.__setitem__('x', self.pattern(self.locale_time.LC_date)) 2194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao base.__setitem__('X', self.pattern(self.locale_time.LC_time)) 2204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def __seqToRE(self, to_convert, directive): 2224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """Convert a list to a regex string for matching a directive. 2234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao Want possible matching values to be from longest to shortest. This 2254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao prevents the possibility of a match occuring for a value that also 2264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao a substring of a larger value that should have matched (e.g., 'abc' 2274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao matching when 'abcdef' should have been the match). 2284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """ 2304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao to_convert = sorted(to_convert, key=len, reverse=True) 2314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao for value in to_convert: 2324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if value != '': 2334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao break 2344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao else: 2354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return '' 2364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao regex = '|'.join(re_escape(stuff) for stuff in to_convert) 2374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao regex = '(?P<%s>%s' % (directive, regex) 2384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return '%s)' % regex 2394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def pattern(self, format): 2414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """Return regex pattern for the format string. 2424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao Need to make sure that any characters that might be interpreted as 2444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao regex syntax are escaped. 2454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """ 2474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao processed_format = '' 2484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # The sub() call escapes all characters that might be misconstrued 2494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # as regex syntax. Cannot use re.escape since we have to deal with 2504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # format directives (%m, etc.). 2514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao regex_chars = re_compile(r"([\\.^$*+?\(\){}\[\]|])") 2524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao format = regex_chars.sub(r"\\\1", format) 2534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao whitespace_replacement = re_compile('\s+') 2544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao format = whitespace_replacement.sub('\s+', format) 2554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao while '%' in format: 2564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao directive_index = format.index('%')+1 2574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao processed_format = "%s%s%s" % (processed_format, 2584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao format[:directive_index-1], 2594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao self[format[directive_index]]) 2604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao format = format[directive_index+1:] 2614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return "%s%s" % (processed_format, format) 2624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao def compile(self, format): 2644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """Return a compiled re object for the format string.""" 2654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return re_compile(self.pattern(format), IGNORECASE) 2664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao_cache_lock = _thread_allocate_lock() 2684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# DO NOT modify _TimeRE_cache or _regex_cache without acquiring the cache lock 2694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao# first! 2704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao_TimeRE_cache = TimeRE() 2714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao_CACHE_MAX_SIZE = 5 # Max number of regexes stored in _regex_cache 2724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao_regex_cache = {} 2734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef _calc_julian_from_U_or_W(year, week_of_year, day_of_week, week_starts_Mon): 2754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """Calculate the Julian day based on the year, week of the year, and day of 2764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao the week, with week_start_day representing whether the week of the year 2774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao assumes the week starts on Sunday or Monday (6 or 0).""" 2784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao first_weekday = datetime_date(year, 1, 1).weekday() 2794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # If we are dealing with the %U directive (week starts on Sunday), it's 2804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # easier to just shift the view to Sunday being the first day of the 2814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # week. 2824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if not week_starts_Mon: 2834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao first_weekday = (first_weekday + 1) % 7 2844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao day_of_week = (day_of_week + 1) % 7 2854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # Need to watch out for a week 0 (when the first day of the year is not 2864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # the same as that specified by %U or %W). 2874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao week_0_length = (7 - first_weekday) % 7 2884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if week_of_year == 0: 2894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return 1 + day_of_week - first_weekday 2904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao else: 2914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao days_to_week = week_0_length + (7 * (week_of_year - 1)) 2924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return 1 + days_to_week + day_of_week 2934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 2954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef _strptime(data_string, format="%a %b %d %H:%M:%S %Y"): 2964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao """Return a time struct based on the input string and the format string.""" 2974adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao global _TimeRE_cache, _regex_cache 2984adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao with _cache_lock: 2994adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if _getlang() != _TimeRE_cache.locale_time.lang: 3004adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao _TimeRE_cache = TimeRE() 3014adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao _regex_cache.clear() 3024adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if len(_regex_cache) > _CACHE_MAX_SIZE: 3034adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao _regex_cache.clear() 3044adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao locale_time = _TimeRE_cache.locale_time 3054adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao format_regex = _regex_cache.get(format) 3064adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if not format_regex: 3074adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao try: 3084adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao format_regex = _TimeRE_cache.compile(format) 3094adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # KeyError raised when a bad format is found; can be specified as 3104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # \\, in which case it was a stray % but with a space after it 3114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao except KeyError, err: 3124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao bad_directive = err.args[0] 3134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if bad_directive == "\\": 3144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao bad_directive = "%" 3154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao del err 3164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise ValueError("'%s' is a bad directive in format '%s'" % 3174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao (bad_directive, format)) 3184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # IndexError only occurs when the format string is "%" 3194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao except IndexError: 3204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise ValueError("stray %% in format '%s'" % format) 3214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao _regex_cache[format] = format_regex 3224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao found = format_regex.match(data_string) 3234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if not found: 3244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise ValueError("time data %r does not match format %r" % 3254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao (data_string, format)) 3264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if len(data_string) != found.end(): 3274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao raise ValueError("unconverted data remains: %s" % 3284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao data_string[found.end():]) 3294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 3304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao year = None 3314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao month = day = 1 3324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao hour = minute = second = fraction = 0 3334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao tz = -1 3344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # Default to -1 to signify that values not known; not critical to have, 3354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # though 3364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao week_of_year = -1 3374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao week_of_year_start = -1 3384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # weekday and julian defaulted to -1 so as to signal need to calculate 3394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # values 3404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao weekday = julian = -1 3414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao found_dict = found.groupdict() 3424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao for group_key in found_dict.iterkeys(): 3434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # Directives not explicitly handled below: 3444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # c, x, X 3454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # handled by making out of other directives 3464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # U, W 3474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # worthless without day of the week 3484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if group_key == 'y': 3494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao year = int(found_dict['y']) 3504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # Open Group specification for strptime() states that a %y 3514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao #value in the range of [00, 68] is in the century 2000, while 3524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao #[69,99] is in the century 1900 3534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if year <= 68: 3544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao year += 2000 3554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao else: 3564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao year += 1900 3574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao elif group_key == 'Y': 3584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao year = int(found_dict['Y']) 3594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao elif group_key == 'm': 3604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao month = int(found_dict['m']) 3614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao elif group_key == 'B': 3624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao month = locale_time.f_month.index(found_dict['B'].lower()) 3634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao elif group_key == 'b': 3644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao month = locale_time.a_month.index(found_dict['b'].lower()) 3654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao elif group_key == 'd': 3664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao day = int(found_dict['d']) 3674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao elif group_key == 'H': 3684adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao hour = int(found_dict['H']) 3694adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao elif group_key == 'I': 3704adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao hour = int(found_dict['I']) 3714adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao ampm = found_dict.get('p', '').lower() 3724adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # If there was no AM/PM indicator, we'll treat this like AM 3734adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if ampm in ('', locale_time.am_pm[0]): 3744adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # We're in AM so the hour is correct unless we're 3754adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # looking at 12 midnight. 3764adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # 12 midnight == 12 AM == hour 0 3774adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if hour == 12: 3784adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao hour = 0 3794adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao elif ampm == locale_time.am_pm[1]: 3804adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # We're in PM so we need to add 12 to the hour unless 3814adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # we're looking at 12 noon. 3824adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # 12 noon == 12 PM == hour 12 3834adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if hour != 12: 3844adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao hour += 12 3854adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao elif group_key == 'M': 3864adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao minute = int(found_dict['M']) 3874adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao elif group_key == 'S': 3884adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao second = int(found_dict['S']) 3894adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao elif group_key == 'f': 3904adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao s = found_dict['f'] 3914adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # Pad to always return microseconds. 3924adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao s += "0" * (6 - len(s)) 3934adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao fraction = int(s) 3944adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao elif group_key == 'A': 3954adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao weekday = locale_time.f_weekday.index(found_dict['A'].lower()) 3964adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao elif group_key == 'a': 3974adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao weekday = locale_time.a_weekday.index(found_dict['a'].lower()) 3984adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao elif group_key == 'w': 3994adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao weekday = int(found_dict['w']) 4004adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if weekday == 0: 4014adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao weekday = 6 4024adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao else: 4034adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao weekday -= 1 4044adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao elif group_key == 'j': 4054adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao julian = int(found_dict['j']) 4064adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao elif group_key in ('U', 'W'): 4074adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao week_of_year = int(found_dict[group_key]) 4084adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if group_key == 'U': 4094adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # U starts week on Sunday. 4104adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao week_of_year_start = 6 4114adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao else: 4124adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # W starts week on Monday. 4134adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao week_of_year_start = 0 4144adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao elif group_key == 'Z': 4154adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # Since -1 is default value only need to worry about setting tz if 4164adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # it can be something other than -1. 4174adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao found_zone = found_dict['Z'].lower() 4184adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao for value, tz_values in enumerate(locale_time.timezone): 4194adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if found_zone in tz_values: 4204adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # Deal with bad locale setup where timezone names are the 4214adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # same and yet time.daylight is true; too ambiguous to 4224adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # be able to tell what timezone has daylight savings 4234adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if (time.tzname[0] == time.tzname[1] and 4244adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao time.daylight and found_zone not in ("utc", "gmt")): 4254adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao break 4264adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao else: 4274adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao tz = value 4284adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao break 4294adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao leap_year_fix = False 4304adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if year is None and month == 2 and day == 29: 4314adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao year = 1904 # 1904 is first leap year of 20th century 4324adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao leap_year_fix = True 4334adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao elif year is None: 4344adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao year = 1900 4354adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # If we know the week of the year and what day of that week, we can figure 4364adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # out the Julian day of the year. 4374adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if julian == -1 and week_of_year != -1 and weekday != -1: 4384adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao week_starts_Mon = True if week_of_year_start == 0 else False 4394adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao julian = _calc_julian_from_U_or_W(year, week_of_year, weekday, 4404adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao week_starts_Mon) 4414adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # Cannot pre-calculate datetime_date() since can change in Julian 4424adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # calculation and thus could have different value for the day of the week 4434adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # calculation. 4444adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if julian == -1: 4454adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # Need to add 1 to result since first day of the year is 1, not 0. 4464adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao julian = datetime_date(year, month, day).toordinal() - \ 4474adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao datetime_date(year, 1, 1).toordinal() + 1 4484adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao else: # Assume that if they bothered to include Julian day it will 4494adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # be accurate. 4504adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao datetime_result = datetime_date.fromordinal((julian - 1) + datetime_date(year, 1, 1).toordinal()) 4514adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao year = datetime_result.year 4524adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao month = datetime_result.month 4534adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao day = datetime_result.day 4544adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if weekday == -1: 4554adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao weekday = datetime_date(year, month, day).weekday() 4564adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao if leap_year_fix: 4574adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # the caller didn't supply a year but asked for Feb 29th. We couldn't 4584adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # use the default of 1900 for computations. We set it back to ensure 4594adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao # that February 29th is smaller than March 1st. 4604adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao year = 1900 4614adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 4624adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return (time.struct_time((year, month, day, 4634adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao hour, minute, second, 4644adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao weekday, julian, tz)), fraction) 4654adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao 4664adfde8bc82dd39f59e0445588c3e599ada477dJosh Gaodef _strptime_time(data_string, format="%a %b %d %H:%M:%S %Y"): 4674adfde8bc82dd39f59e0445588c3e599ada477dJosh Gao return _strptime(data_string, format)[0] 468