def parse(self, expression): """Parse an ISO duration expression into a Duration instance.""" sign_factor = 1 if expression.startswith("-"): sign_factor = -1 expression = expression[1:] for rec_regex in self.DURATION_REGEXES: result = rec_regex.search(expression) if not result: continue result_map = result.groupdict() for key, value in list(result_map.items()): if value is None: result_map.pop(key) continue if key in ["years", "months", "days", "weeks"]: value = int(value) else: if "," in value: value = value.replace(",", ".") value = float(value) result_map[key] = value * sign_factor return data.Duration(**result_map) if expression.startswith("P") and sign_factor != -1: # TimePoint-like duration - don't allow our negative extension. try: timepoint = parse_timepoint_expression( expression[1:], # this is a duration but we are parsing it as a timepoint # so don't validate. validate=False, allow_truncated=False, assumed_time_zone=(0, 0) ) except ISO8601SyntaxError: raise ISO8601SyntaxError("duration", expression) if timepoint.get_is_week_date(): raise ISO8601SyntaxError("duration", expression) result_map = {} result_map["years"] = timepoint.year if timepoint.get_is_calendar_date(): result_map["months"] = timepoint.month_of_year result_map["days"] = timepoint.day_of_month if timepoint.get_is_ordinal_date(): result_map["days"] = timepoint.day_of_year result_map["hours"] = timepoint.hour_of_day if timepoint.minute_of_hour is not None: result_map["minutes"] = timepoint.minute_of_hour if timepoint.second_of_minute is not None: result_map["seconds"] = timepoint.second_of_minute return data.Duration(**result_map) raise ISO8601SyntaxError("duration", expression)
def parse(self, expression): """Parse a recurrence string into a TimeRecurrence instance.""" for regex in self.RECURRENCE_REGEXES: result = regex.search(expression) if not result: continue result_map = result.groupdict() repetitions = None start_point = None end_point = None duration = None if "reps" in result_map and result_map["reps"] is not None: repetitions = int(result_map["reps"]) if "start" in result_map: start_point = self.timepoint_parser.parse(result_map["start"]) if "end" in result_map: end_point = self.timepoint_parser.parse(result_map["end"]) if "intv" in result_map: duration = self.duration_parser.parse( result_map["intv"]) return data.TimeRecurrence( repetitions=repetitions, start_point=start_point, end_point=end_point, duration=duration ) raise ISO8601SyntaxError("recurrence", expression)
def get_time_zone_info(self, time_zone_string, bad_formats=None): """Return the properties from a time zone string.""" if bad_formats is None: bad_formats = [] for format_key, regex_list in self._time_zone_regex_map.items(): if format_key in bad_formats: continue for regex, expr in regex_list: result = regex.match(time_zone_string) if result: return expr, result.groupdict() raise ISO8601SyntaxError("time zone", time_zone_string)
def get_date_info(self, date_string, bad_types=None): """Return the format and properties from a date string.""" type_keys = ["complete", "truncated", "reduced"] if bad_types is not None: for type_key in bad_types: type_keys.remove(type_key) if not self.allow_truncated and "truncated" in type_keys: type_keys.remove("truncated") for format_key, type_regex_map in self._date_regex_map.items(): for type_key in type_keys: regex_list = type_regex_map[type_key] for regex, expr in regex_list: result = regex.match(date_string) if result: return ((format_key, type_key, expr), result.groupdict()) raise ISO8601SyntaxError("date", date_string)