# HG changeset patch # User Paul Boddie # Date 1425674516 -3600 # Node ID 4a55201d7985addac69c16a49ca84422d6305eac # Parent e2771305e3578f653e5287e2779ffa6ea1ce3fd1 Added initial support for duration and period value types. diff -r e2771305e357 -r 4a55201d7985 imiptools/dates.py --- a/imiptools/dates.py Fri Mar 06 00:07:47 2015 +0100 +++ b/imiptools/dates.py Fri Mar 06 21:41:56 2015 +0100 @@ -33,8 +33,28 @@ ur'(?PZ)?' \ ur')?' +duration_time_icalendar_regexp_str = \ + ur'T' \ + ur'(?:' \ + ur'([0-9]+H)(?:([0-9]+M)([0-9]+S)?)?' \ + ur'|' \ + ur'([0-9]+M)([0-9]+S)?' \ + ur'|' \ + ur'([0-9]+S)' \ + ur')' + +duration_icalendar_regexp_str = ur'P' \ + ur'(?:' \ + ur'([0-9]+W)' \ + ur'|' \ + ur'(?:%s)' \ + ur'|' \ + ur'([0-9]+D)(?:%s)?' \ + ur')' % (duration_time_icalendar_regexp_str, duration_time_icalendar_regexp_str) + match_date_icalendar = re.compile(date_icalendar_regexp_str, re.UNICODE).match match_datetime_icalendar = re.compile(datetime_icalendar_regexp_str, re.UNICODE).match +match_duration_icalendar = re.compile(duration_icalendar_regexp_str, re.UNICODE).match def to_utc_datetime(dt): @@ -169,6 +189,52 @@ return None +def get_period(value, attr=None): + + """ + Return a tuple of the form (start, end) for the given 'value' in iCalendar + format, using the 'attr' mapping (if specified) to control the conversion. + """ + + if not value or attr and attr.get("VALUE") != "PERIOD": + return None + + t = value.split("/") + if len(t) != 2: + return None + + start = get_datetime(t[0]) + if t[1].startswith("P"): + end = start + get_duration(t[1]) + else: + end = get_datetime(t[1]) + + return start, end + +def get_duration(value): + + "Return a duration for the given 'value'." + + if not value: + return None + + m = match_duration_icalendar(value) + if m: + weeks, days, hours, minutes, seconds = 0, 0, 0, 0, 0 + for s in m.groups(): + if not s: continue + if s[-1] == "W": weeks += int(s[:-1]) + elif s[-1] == "D": days += int(s[:-1]) + elif s[-1] == "H": hours += int(s[:-1]) + elif s[-1] == "M": minutes += int(s[:-1]) + elif s[-1] == "S": seconds += int(s[:-1]) + return timedelta( + int(weeks) * 7 + int(days), + (int(hours) * 60 + int(minutes)) * 60 + int(seconds) + ) + else: + return None + def get_date(dt): "Return the date of 'dt'."