def strptime(data_string, format="%a %b %d %H:%M:%S %Y", reference=(1900, 1, 1, 0, 0, 0, -1, -1, -1), complete_with_zeroes=True): """Return time struct and microseconds based on an input and format string An optional ``reference`` is set by default to 1900-01-01 00:00:00. ``reference`` field is a tuple with: (year, month, day, hour, minute, second, weekday, julian, tz), microseconds Please note that weekday and julian will be ignored. >>> from sact.epoch.strptime import strptime >>> strptime('13:05', '%H:%M', ... reference=((2000, 1, 1, 0, 0, 30, -1, -1, -1), 5)) (time.struct_time(tm_year=2000, tm_mon=1, tm_mday=1, tm_hour=13, tm_min=5, tm_sec=0, tm_wday=5, tm_yday=1, tm_isdst=-1), 0) Notice how all the left most values (the biggest weight value) where used from the given reference, and how the left most value (least weight values) was zeroed. The middle part is what was parsed. You can switch of the zeroing of the left most part: >>> strptime('13:05', '%H:%M', ... reference=((2000, 1, 1, 0, 0, 0, -1, -1, -1), 5), ... complete_with_zeroes=False) (time.struct_time(tm_year=2000, tm_mon=1, tm_mday=1, tm_hour=13, tm_min=5, tm_sec=0, tm_wday=5, tm_yday=1, tm_isdst=-1), 5) """ with _strptime._cache_lock: if _strptime._getlang() != _strptime._TimeRE_cache.locale_time.lang: _strptime._TimeRE_cache = TimeRE() _strptime._regex_cache.clear() if len(_strptime._regex_cache) > _strptime._CACHE_MAX_SIZE: _strptime._regex_cache.clear() locale_time = _strptime._TimeRE_cache.locale_time format_regex = _strptime._regex_cache.get(format) if not format_regex: try: format_regex = _strptime._TimeRE_cache.compile(format) # KeyError raised when a bad format is found; can be specified as # \\, in which case it was a stray % but with a space after it except KeyError as err: bad_directive = err.args[0] if bad_directive == "\\": bad_directive = "%" del err raise ValueError("'%s' is a bad directive in format '%s'" % (bad_directive, format)) # IndexError only occurs when the format string is "%" except IndexError: raise ValueError("stray %% in format '%s'" % format) _strptime._regex_cache[format] = format_regex found = format_regex.match(data_string) if not found: raise ValueError("time data %r does not match format %r" % (data_string, format)) if len(data_string) != found.end(): raise ValueError("unconverted data remains: %s" % data_string[found.end():]) (year, month, day, hour, minute, second, weekday, julian, tz), \ fraction = reference # Force calculation for julian and weekday julian = -1 weekday = -1 # Default to -1 to signify that values not known; not critical to have, # though week_of_year = -1 week_of_year_start = -1 found_dict = found.groupdict() for group_key in found_dict.keys(): # 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 #value in the range of [00, 68] is in the century 2000, while #[69,99] is in the century 1900 if year <= 68: year += 2000 else: year += 1900 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'].lower()) elif group_key == 'b': month = locale_time.a_month.index(found_dict['b'].lower()) elif group_key == 'd': day = int(found_dict['d']) elif group_key == 'H': hour = int(found_dict['H']) elif group_key == 'I': hour = int(found_dict['I']) ampm = found_dict.get('p', '').lower() # If there was no AM/PM indicator, we'll treat this like AM if ampm in ('', 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 == 'S': second = int(found_dict['S']) elif group_key == 'f': s = found_dict['f'] # Pad to always return microseconds. s += "0" * (6 - len(s)) fraction = int(s) elif group_key == 'A': weekday = locale_time.f_weekday.index(found_dict['A'].lower()) elif group_key == 'a': weekday = locale_time.a_weekday.index(found_dict['a'].lower()) elif group_key == 'w': weekday = int(found_dict['w']) if weekday == 0: weekday = 6 else: 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. found_zone = found_dict['Z'].lower() for value, tz_values in enumerate(locale_time.timezone): if found_zone in tz_values: # Deal with bad locale setup where timezone names are the # same and yet time.daylight is true; too ambiguous to # be able to tell what timezone has daylight savings if (time.tzname[0] == time.tzname[1] and time.daylight and found_zone not in ("utc", "gmt")): break 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. if julian == -1 and week_of_year != -1 and weekday != -1: week_starts_Mon = True if week_of_year_start == 0 else False julian = _strptime._calc_julian_from_U_or_W(year, week_of_year, weekday, week_starts_Mon) if complete_with_zeroes: idxs = ("j", "Y", "mBb", "UW", "dAaw", "HI", "M", "S", "f") specified = [idxs.index(gk) for gk in [first(idxs, lambda key_group: k in key_group) for k in found_dict.keys()]] rightmost_specified = max(specified) if len(specified) else 0 base = (1900, 1, 1, 1, 0, 0, 0, 0) values = year, month, week_of_year, day, hour, minute, second, fraction year, month, week_of_year, day, hour, minute, second, fraction = \ values[:rightmost_specified] + base[rightmost_specified:] # Cannot pre-calculate datetime_date() since can change in Julian # calculation and thus could have different value for the day of the week # calculation. if julian == -1: # Need to add 1 to result since first day of the year is 1, not 0. julian = datetime_date(year, month, day).toordinal() - \ datetime_date(year, 1, 1).toordinal() + 1 else: # Assume that if they bothered to include Julian day it will # be accurate. datetime_result = datetime_date.fromordinal( (julian - 1) + datetime_date(year, 1, 1).toordinal()) year = datetime_result.year month = datetime_result.month day = datetime_result.day if weekday == -1: weekday = datetime_date(year, month, day).weekday() return (time.struct_time((year, month, day, hour, minute, second, weekday, julian, tz)), fraction)
def reGroupDictStrptime(found_dict, msec=False, default_tz=None): """Return time from dictionary of strptime fields This is tweaked from python built-in _strptime. Parameters ---------- found_dict : dict Dictionary where keys represent the strptime fields, and values the respective value. default_tz : default timezone to apply if nothing relevant is in found_dict (may be a non-fixed one in the future) Returns ------- float Unix time stamp. """ now = \ year = month = day = hour = minute = tzoffset = \ weekday = julian = week_of_year = None second = fraction = 0 for key, val in found_dict.iteritems(): if val is None: continue # Directives not explicitly handled below: # c, x, X # handled by making out of other directives # U, W # worthless without day of the week if key == 'y': year = int(val) # Fail2ban year should be always in the current century (>= 2000) if year <= 2000: year += 2000 elif key == 'Y': year = int(val) elif key == 'm': month = int(val) elif key == 'B': month = locale_time.f_month.index(val.lower()) elif key == 'b': month = locale_time.a_month.index(val.lower()) elif key == 'd': day = int(val) elif key == 'H': hour = int(val) elif key == 'I': hour = int(val) ampm = found_dict.get('p', '').lower() # If there was no AM/PM indicator, we'll treat this like AM if ampm in ('', 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 key == 'M': minute = int(val) elif key == 'S': second = int(val) elif key == 'f': if msec: # pragma: no cover - currently unused s = val # Pad to always return microseconds. s += "0" * (6 - len(s)) fraction = int(s) elif key == 'A': weekday = locale_time.f_weekday.index(val.lower()) elif key == 'a': weekday = locale_time.a_weekday.index(val.lower()) elif key == 'w': weekday = int(val) - 1 if weekday < 0: weekday = 6 elif key == 'j': julian = int(val) elif key in ('U', 'W'): week_of_year = int(val) # U starts week on Sunday, W - on Monday week_of_year_start = 6 if key == 'U' else 0 elif key in ('z', 'Z'): z = val if z in ("Z", "UTC", "GMT"): tzoffset = 0 else: tzoffset = zone2offset(z, 0); # currently offset-based only # Fail2Ban will assume it's this year assume_year = False if year is None: if not now: now = MyTime.now() year = now.year assume_year = True if month is None or day is None: # If we know the week of the year and what day of that week, we can figure # out the Julian day of the year. if julian is None and week_of_year is not None and weekday is not None: julian = _calc_julian_from_U_or_W(year, week_of_year, weekday, (week_of_year_start == 0)) # Cannot pre-calculate datetime.datetime() since can change in Julian # calculation and thus could have different value for the day of the week # calculation. if julian is not None: datetime_result = datetime.datetime.fromordinal((julian - 1) + datetime.datetime(year, 1, 1).toordinal()) year = datetime_result.year month = datetime_result.month day = datetime_result.day # Fail2Ban assume today assume_today = False if month is None and day is None: if not now: now = MyTime.now() month = now.month day = now.day assume_today = True # Actully create date date_result = datetime.datetime( year, month, day, hour, minute, second, fraction) # Correct timezone if not supplied in the log linge if tzoffset is None and default_tz is not None: tzoffset = zone2offset(default_tz, date_result) # Add timezone info if tzoffset is not None: date_result -= datetime.timedelta(seconds=tzoffset * 60) if assume_today: if not now: now = MyTime.now() if date_result > now: # Rollover at midnight, could mean it's yesterday... date_result -= datetime.timedelta(days=1) if assume_year: if not now: now = MyTime.now() if date_result > now + datetime.timedelta(days=1): # ignore by timezone issues (+24h) # assume last year - also reset month and day as it's not yesterday... date_result = date_result.replace( year=year-1, month=month, day=day) # make time: if tzoffset is not None: tm = calendar.timegm(date_result.utctimetuple()) else: tm = time.mktime(date_result.timetuple()) if msec: # pragma: no cover - currently unused tm += fraction/1000000.0 return tm
def reGroupDictStrptime(found_dict): """Return time from dictionary of strptime fields This is tweaked from python built-in _strptime. Parameters ---------- found_dict : dict Dictionary where keys represent the strptime fields, and values the respective value. Returns ------- float Unix time stamp. """ now = MyTime.now() year = month = day = hour = minute = None hour = minute = None second = fraction = 0 tzoffset = None # Default to -1 to signify that values not known; not critical to have, # though 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 for group_key in found_dict.keys(): # 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 #value in the range of [00, 68] is in the century 2000, while #[69,99] is in the century 1900 if year <= 68: year += 2000 else: year += 1900 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'].lower()) elif group_key == 'b': month = locale_time.a_month.index(found_dict['b'].lower()) elif group_key == 'd': day = int(found_dict['d']) elif group_key == 'H': hour = int(found_dict['H']) elif group_key == 'I': hour = int(found_dict['I']) ampm = found_dict.get('p', '').lower() # If there was no AM/PM indicator, we'll treat this like AM if ampm in ('', 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 == 'S': second = int(found_dict['S']) elif group_key == 'f': s = found_dict['f'] # Pad to always return microseconds. s += "0" * (6 - len(s)) fraction = int(s) elif group_key == 'A': weekday = locale_time.f_weekday.index(found_dict['A'].lower()) elif group_key == 'a': weekday = locale_time.a_weekday.index(found_dict['a'].lower()) elif group_key == 'w': weekday = int(found_dict['w']) if weekday == 0: weekday = 6 else: 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': z = found_dict['z'] if z == "Z": tzoffset = 0 else: tzoffset = int(z[1:3]) * 60 # Hours... if len(z)>3: tzoffset += int(z[-2:]) # ...and minutes if z.startswith("-"): tzoffset = -tzoffset # Fail2Ban will assume it's this year assume_year = False if year is None: year = now.year assume_year = True # If we know the week of the year and what day of that week, we can figure # out the Julian day of the year. if julian == -1 and week_of_year != -1 and weekday != -1: week_starts_Mon = True if week_of_year_start == 0 else False julian = _calc_julian_from_U_or_W(year, week_of_year, weekday, week_starts_Mon) # Cannot pre-calculate datetime.datetime() since can change in Julian # calculation and thus could have different value for the day of the week # calculation. if julian != -1 and (month is None or day is None): datetime_result = datetime.datetime.fromordinal((julian - 1) + datetime.datetime(year, 1, 1).toordinal()) year = datetime_result.year month = datetime_result.month day = datetime_result.day # Add timezone info if tzoffset is not None: gmtoff = tzoffset * 60 else: gmtoff = None # Fail2Ban assume today assume_today = False if month is None and day is None: month = now.month day = now.day assume_today = True # Actully create date date_result = datetime.datetime( year, month, day, hour, minute, second, fraction) if gmtoff: date_result = date_result - datetime.timedelta(seconds=gmtoff) if date_result > now and assume_today: # Rollover at midnight, could mean it's yesterday... date_result = date_result - datetime.timedelta(days=1) if date_result > now and assume_year: # Could be last year? # also reset month and day as it's not yesterday... date_result = date_result.replace( year=year-1, month=month, day=day) if gmtoff is not None: return calendar.timegm(date_result.utctimetuple()) else: return time.mktime(date_result.timetuple())
def update_event(self, inp=-1): self.set_output_val(0, _strptime._calc_julian_from_U_or_W(self.input(0), self.input(1), self.input(2), self.input(3)))
def strptime(data_string, format="%a %b %d %H:%M:%S %Y", lang=None): """Return a time struct based on the input string and the format string.""" global lang_loader # This code has been copied from python's _strptime module. if lang is False: lang = 'C' elif lang is None: lang = locale.getlocale(locale.LC_TIME) or 'C' if isinstance(lang, (basestring, tuple)): lang = lang_loader.loadLang(lang) locale_time = lang.locale_time format_regex = lang.getTimeRegex(format) assert format_regex found = format_regex.match(data_string) if not found: raise ValueError("time data %r does not match format %r" % (data_string, format)) if len(data_string) != found.end(): raise ValueError("unconverted data remains: %s" % data_string[found.end():]) year = 1900 month = day = 1 hour = minute = second = fraction = 0 tz = -1 # Default to -1 to signify that values not known; not critical to have, # though 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 #value in the range of [00, 68] is in the century 2000, while #[69,99] is in the century 1900 if year <= 68: year += 2000 else: year += 1900 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'].lower()) elif group_key == 'b': month = locale_time.a_month.index(found_dict['b'].lower()) elif group_key == 'd': day = int(found_dict['d']) elif group_key == 'H': hour = int(found_dict['H']) elif group_key == 'I': hour = int(found_dict['I']) ampm = found_dict.get('p', '').lower() # If there was no AM/PM indicator, we'll treat this like AM if ampm in ('', 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 == 'S': second = int(found_dict['S']) elif group_key == 'f': s = found_dict['f'] # Pad to always return microseconds. s += "0" * (6 - len(s)) fraction = int(s) elif group_key == 'A': weekday = locale_time.f_weekday.index(found_dict['A'].lower()) elif group_key == 'a': weekday = locale_time.a_weekday.index(found_dict['a'].lower()) elif group_key == 'w': weekday = int(found_dict['w']) if weekday == 0: weekday = 6 else: 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. found_zone = found_dict['Z'].lower() for value, tz_values in enumerate(locale_time.timezone): if found_zone in tz_values: # Deal with bad locale setup where timezone names are the # same and yet time.daylight is true; too ambiguous to # be able to tell what timezone has daylight savings if (time.tzname[0] == time.tzname[1] and time.daylight and found_zone not in ("utc", "gmt")): break 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. if julian == -1 and week_of_year != -1 and weekday != -1: week_starts_Mon = True if week_of_year_start == 0 else False julian = _strptime_module._calc_julian_from_U_or_W(year, week_of_year, weekday, week_starts_Mon) # Cannot pre-calculate datetime_date() since can change in Julian # calculation and thus could have different value for the day of the week # calculation. if julian == -1: # Need to add 1 to result since first day of the year is 1, not 0. julian = datetime_date(year, month, day).toordinal() - \ datetime_date(year, 1, 1).toordinal() + 1 else: # Assume that if they bothered to include Julian day it will # be accurate. datetime_result = datetime_date.fromordinal((julian - 1) + datetime_date(year, 1, 1).toordinal()) year = datetime_result.year month = datetime_result.month day = datetime_result.day if weekday == -1: weekday = datetime_date(year, month, day).weekday() return (time.struct_time((year, month, day, hour, minute, second, weekday, julian, tz)), fraction)
def _mock_strptime(data_string, fmt, _regex_cache=_regex_cache, _TimeRE_cache=_TimeRE_cache, locale_time=_locale_time): """ Return a 2-tuple consisting of a time struct and an int containing the number of microseconds based on the input string and the format string. @param data_string: date string to format @type data_string: str @param fmt: valid strptime format @type fmt: str @return: @rtype: """ with _cache_lock: format_regex = _regex_cache.get(fmt) if not format_regex: try: format_regex = _TimeRE_cache.compile(fmt) # KeyError raised when a bad format is found; can be specified as # \\, in which case it was a stray % but with a space after it except KeyError as err: bad_directive = err.args[0] if bad_directive == "\\": bad_directive = "%" del err raise ValueError("'%s' is a bad directive in format '%s'" % (bad_directive, fmt)) from None # IndexError only occurs when the format string is "%" except IndexError: raise ValueError("stray %% in format '%s'" % fmt) _regex_cache[fmt] = format_regex found = format_regex.match(data_string) if not found: raise ValueError("time data %r does not match format %r" % (data_string, fmt)) if len(data_string) != found.end(): raise ValueError("unconverted data remains: %s" % data_string[found.end():]) year = None month = day = 1 hour = minute = second = fraction = 0 tz = -1 tzoffset = None # Default to -1 to signify that values not known; not critical to have, # though 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.keys(): # 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 #value in the range of [00, 68] is in the century 2000, while #[69,99] is in the century 1900 if year <= 68: year += 2000 else: year += 1900 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'].lower()) elif group_key == 'b': month = locale_time.a_month.index(found_dict['b'].lower()) elif group_key == 'd': day = int(found_dict['d']) elif group_key == 'H': hour = int(found_dict['H']) elif group_key == 'I': hour = int(found_dict['I']) ampm = found_dict.get('p', '').lower() # If there was no AM/PM indicator, we'll treat this like AM if ampm in ('', 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 == 'S': second = int(found_dict['S']) elif group_key == 'f': s = found_dict['f'] # Pad to always return microseconds. s += "0" * (6 - len(s)) fraction = int(s) elif group_key == 'A': weekday = locale_time.f_weekday.index(found_dict['A'].lower()) elif group_key == 'a': weekday = locale_time.a_weekday.index(found_dict['a'].lower()) elif group_key == 'w': weekday = int(found_dict['w']) if weekday == 0: weekday = 6 else: 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': z = found_dict['z'] tzoffset = int(z[1:3]) * 60 + int(z[3:5]) if z.startswith("-"): tzoffset = -tzoffset elif group_key == 'Z': # Since -1 is default value only need to worry about setting tz if # it can be something other than -1. found_zone = found_dict['Z'].lower() for value, tz_values in enumerate(locale_time.timezone): if found_zone in tz_values: # Deal with bad locale setup where timezone names are the # same and yet time.daylight is true; too ambiguous to # be able to tell what timezone has daylight savings if (time.tzname[0] == time.tzname[1] and time.daylight and found_zone not in ("utc", "gmt")): break else: tz = value break leap_year_fix = False if year is None and month == 2 and day == 29: year = 1904 # 1904 is first leap year of 20th century leap_year_fix = True elif year is None: year = 1900 # If we know the week of the year and what day of that week, we can figure # out the Julian day of the year. if julian == -1 and week_of_year != -1 and weekday != -1: week_starts_Mon = True if week_of_year_start == 0 else False julian = _calc_julian_from_U_or_W(year, week_of_year, weekday, week_starts_Mon) # Cannot pre-calculate datetime_date() since can change in Julian # calculation and thus could have different value for the day of the week # calculation. if julian == -1: # Need to add 1 to result since first day of the year is 1, not 0. julian = datetime_date(year, month, day).toordinal() - \ datetime_date(year, 1, 1).toordinal() + 1 else: # Assume that if they bothered to include Julian day it will # be accurate. datetime_result = datetime_date.fromordinal((julian - 1) + datetime_date(year, 1, 1).toordinal()) year = datetime_result.year month = datetime_result.month day = datetime_result.day if weekday == -1: weekday = datetime_date(year, month, day).weekday() # Add timezone info tzname = found_dict.get("Z") if tzoffset is not None: gmtoff = tzoffset * 60 else: gmtoff = None if leap_year_fix: # the caller didn't supply a year but asked for Feb 29th. We couldn't # use the default of 1900 for computations. We set it back to ensure # that February 29th is smaller than March 1st. year = 1900 return (year, month, day, hour, minute, second, weekday, julian, tz, tzname, gmtoff), fraction
def to_time_tuple(found_dict): u'''Closely based on _strptime in standard Python.''' year = None month = day = 1 hour = minute = second = fraction = 0 tz = -1 tzoffset = None # Default to -1 to signify that values not known; not critical to have week_of_year = -1 week_of_year_start = -1 # weekday and julian defaulted to -1 so as to signal need to calculate weekday = julian = -1 for group_key in (key for key in found_dict.keys() if found_dict[key] is not None): # 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 == u'y': year = int(found_dict[u'y']) # Open Group specification for strptime() states that a %y #value in the range of [00, 68] is in the century 2000, while #[69,99] is in the century 1900 if year <= 68: year += 2000 else: year += 1900 elif group_key == u'y50': year = int(found_dict[u'y50']) # ASN.1 / RFC 3852 if year < 50: year += 2000 else: year += 1900 elif group_key == u'Y': year = int(found_dict[u'Y']) elif group_key == u'm': month = int(found_dict[u'm']) elif group_key == u'B': month = LOCALE_TIME.f_month.index(found_dict[u'B'].lower()) elif group_key == u'b': month = LOCALE_TIME.a_month.index(found_dict[u'b'].lower()) elif group_key == u'd': day = int(found_dict[u'd']) elif group_key == u'H': hour = int(found_dict[u'H']) elif group_key == u'I': hour = int(found_dict[u'I']) ampm = found_dict.get(u'p', u'').lower() # If there was no AM/PM indicator, we'll treat this like AM if ampm in (u'', 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 == u'M': minute = int(found_dict[u'M']) elif group_key == u'S': second = int(found_dict[u'S']) elif group_key == u'f': s = found_dict[u'f'] # Pad to always return microseconds. s += u"0" * (6 - len(s)) fraction = int(s) elif group_key == u'A': weekday = LOCALE_TIME.f_weekday.index(found_dict[u'A'].lower()) elif group_key == u'a': weekday = LOCALE_TIME.a_weekday.index(found_dict[u'a'].lower()) elif group_key == u'w': weekday = int(found_dict[u'w']) if weekday == 0: weekday = 6 else: weekday -= 1 elif group_key == u'j': julian = int(found_dict[u'j']) elif group_key in (u'U', u'W'): week_of_year = int(found_dict[group_key]) if group_key == u'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 == u'z': z = found_dict[u'z'] tzoffset = int(z[1:3]) * 60 + int(z[-2:]) if z.startswith(u"-"): tzoffset = -tzoffset elif group_key == u'Z': # Since -1 is default value only need to worry about setting tz if # it can be something other than -1. found_zone = found_dict[u'Z'].lower() for value, tz_values in enumerate(LOCALE_TIME.timezone): if found_zone in tz_values: # Deal with bad locale setup where timezone names are the # same and yet time.daylight is true; too ambiguous to # be able to tell what timezone has daylight savings if (time.tzname[0] == time.tzname[1] and time.daylight and found_zone not in (u"utc", u"gmt")): break else: tz = value break leap_year_fix = False if year is None and month == 2 and day == 29: year = 1904 # 1904 is first leap year of 20th century leap_year_fix = True elif year is None: year = 1900 # If we know the week of the year and what day of that week, we can figure # out the Julian day of the year. if julian == -1 and week_of_year != -1 and weekday != -1: week_starts_Mon = True if week_of_year_start == 0 else False julian = _calc_julian_from_U_or_W(year, week_of_year, weekday, week_starts_Mon) # Cannot pre-calculate date() since can change in Julian # calculation and thus could have different value for the day of the week # calculation. if julian == -1: # Need to add 1 to result since first day of the year is 1, not 0. julian = date(year, month, day).toordinal() - \ date(year, 1, 1).toordinal() + 1 else: # Assume that if they bothered to include Julian day it will # be accurate. datetime_result = date.fromordinal((julian - 1) + date(year, 1, 1).toordinal()) year = datetime_result.year month = datetime_result.month day = datetime_result.day if weekday == -1: weekday = date(year, month, day).weekday() # Add timezone info tzname = found_dict.get(u'Z') if tzoffset is not None: gmtoff = tzoffset * 60 else: gmtoff = None if leap_year_fix: # the caller didn't supply a year but asked for Feb 29th. We couldn't # use the default of 1900 for computations. We set it back to ensure # that February 29th is smaller than March 1st. year = 1900 return (year, month, day, hour, minute, second, weekday, julian, tz, tzname, gmtoff), fraction