Exemple #1
0
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)
Exemple #2
0
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
Exemple #3
0
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())
Exemple #4
0
 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)))
Exemple #5
0
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)
Exemple #6
0
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
Exemple #7
0
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