def parse(duration, context=None):
matcher = _PATTERN.match(duration)<EOL>if matcher is None or matcher.end() < len(duration):<EOL><INDENT>raise Exception('<STR_LIT>' % duration)<EOL><DEDENT>else:<EOL><INDENT>result = timedelta()<EOL>if context is None:<EOL><INDENT>context = datetime.now()<EOL><DEDENT>year = context.year<EOL>month = context.month<EOL>day = context.day<EOL>for (key, value) in matcher.groupdict().items():<EOL><INDENT>weeks = <NUM_LIT:0><EOL>days = <NUM_LIT:0><EOL>hours = <NUM_LIT:0><EOL>minutes = <NUM_LIT:0><EOL>seconds = <NUM_LIT:0><EOL>milliseconds = <NUM_LIT:0><EOL>microseconds = <NUM_LIT:0><EOL>if value is not None:<EOL><INDENT>value = float(value)<EOL>whole = int(value)<EOL>fraction = abs(whole - value)<EOL>if key == '<STR_LIT>':<EOL><INDENT>start = datetime(year, month, day)<EOL>end = datetime(year + whole, month, day)<EOL>if fraction > <NUM_LIT:0>:<EOL><INDENT>days_in_year = (datetime(year + whole, <NUM_LIT:12>, <NUM_LIT>) -<EOL>datetime(year + whole, <NUM_LIT:1>, <NUM_LIT:1>)).days + <NUM_LIT:1><EOL>end += timedelta(days=(fraction * days_in_year))<EOL><DEDENT>seconds = (end - start).total_seconds()<EOL><DEDENT>elif key == '<STR_LIT>':<EOL><INDENT>day = <NUM_LIT:1><EOL>years = whole // <NUM_LIT:12><EOL>months = whole % <NUM_LIT:12><EOL>end_month = month + months<EOL>if end_month > <NUM_LIT:12>:<EOL><INDENT>years += end_month // <NUM_LIT:12><EOL>end_month = end_month % <NUM_LIT:12><EOL><DEDENT>start = datetime(year, month, day)<EOL>end = datetime(year + years, end_month, day)<EOL>end_year = year + years<EOL>end_month = month + months + <NUM_LIT:1><EOL>if end_month > <NUM_LIT:12>:<EOL><INDENT>end_year += end_month // <NUM_LIT:12><EOL>end_month = end_month % <NUM_LIT:12><EOL><DEDENT>_, end_day = calendar.monthrange(end_year, end_month)<EOL>days_in_month = (datetime(end_year, end_month, end_day) -<EOL>datetime(end_year, end_month, <NUM_LIT:1>)).days<EOL>end += timedelta(days=(fraction * days_in_month))<EOL>seconds = (end - start).total_seconds()<EOL><DEDENT>elif key == '<STR_LIT>':<EOL><INDENT>weeks = whole<EOL>days = fraction * <NUM_LIT:7><EOL><DEDENT>elif key == '<STR_LIT>':<EOL><INDENT>days = whole<EOL>hours = fraction * <NUM_LIT><EOL><DEDENT>elif key == '<STR_LIT>':<EOL><INDENT>hours = whole<EOL>minutes = fraction * <NUM_LIT><EOL><DEDENT>elif key == '<STR_LIT>':<EOL><INDENT>minutes = whole<EOL>seconds = fraction * <NUM_LIT><EOL><DEDENT>elif key == '<STR_LIT>':<EOL><INDENT>seconds = whole<EOL>milliseconds = fraction * <NUM_LIT:1000><EOL><DEDENT>elif key == '<STR_LIT>':<EOL><INDENT>milliseconds = whole<EOL>microseconds = fraction * <NUM_LIT:1000><EOL><DEDENT>result += timedelta(weeks=weeks,<EOL>days=days,<EOL>hours=hours,<EOL>minutes=minutes,<EOL>seconds=seconds,<EOL>milliseconds=milliseconds,<EOL>microseconds=microseconds)<EOL><DEDENT><DEDENT>return result<EOL><DEDENT>
parse the duration string which contains a human readable duration and
return a datetime.timedelta object representing that duration

arguments:
    duration - the duration string following a notation like so:
               "1 hour"
               "1 month and 3 days" "1 year 2 weeks and 75 days"
               "1 year, 75 days and 33 seconds"
               ...
               etc

    context - the context keyword argument is used to provide the current
              datetime context object used when calculating years and
              months which are dependent on the "current time" you're
              calculating the relative delta in relation to.