diff --git a/maya/core.py b/maya/core.py index d4875f8..8f66f83 100644 --- a/maya/core.py +++ b/maya/core.py @@ -12,12 +12,14 @@ import time import functools from datetime import timedelta, datetime as Datetime +import re import pytz import humanize import dateparser import pendulum import snaptime from tzlocal import get_localzone +from dateutil.relativedelta import relativedelta from .compat import cmp, comparable @@ -423,6 +425,29 @@ class MayaInterval(object): """Returns an ISO 8601 representation of the MayaInterval.""" return '{0}/{1}'.format(self.start.iso8601(), self.end.iso8601()) + @classmethod + def parse_iso8601_duration(cls, duration, start=None, end=None): + match = re.match( + r'(?:P(?P\d+)W)|(?:P(?:(?:(?P\d+)Y)?(?:(?P\d+)M)?(?:(?P\d+)D))?(?:T(?:(?P\d+)H)?(?:(?P\d+)M)?(?:(?P\d+)S)?)?)', + duration + ) + + time_components = {} + if match: + time_components = match.groupdict(0) + for key, value in time_components.items(): + time_components[key] = int(value) + + duration = relativedelta(**time_components) + + if start: + return parse(start.datetime() + duration) + + if end: + return parse(end.datetime() - duration) + + return None + @classmethod def from_iso8601(cls, s): # # Start and end, such as "2007-03-01T13:00:00Z/2008-05-11T15:30:00Z" @@ -430,14 +455,13 @@ class MayaInterval(object): try: start = parse(start) except pendulum.parsing.exceptions.ParserError: - # start = self._parse_iso8601_duration(start) + # start = self._parse_iso8601_duration(start, end=end) raise NotImplementedError() try: end = parse(end) except pendulum.parsing.exceptions.ParserError as e: - # end = self._parse_iso8601_duration(end) - raise NotImplementedError() + end = cls.parse_iso8601_duration(end, start=start) return cls(start=start, end=end) diff --git a/tests/test_maya_interval.py b/tests/test_maya_interval.py index 338fa95..1d040a4 100755 --- a/tests/test_maya_interval.py +++ b/tests/test_maya_interval.py @@ -550,3 +550,23 @@ def test_interval_from_iso8601(): assert interval.start == s assert interval.end == e + + +def test_interval_from_iso8601_duration(): + interval = maya.MayaInterval.from_iso8601( + "2018-03-18T14:27:18Z/P13DT13H48M9S" + ) + s = maya.when("2018-03-18T14:27:18Z") + e = maya.when("2018-04-01T04:15:27Z") + + assert interval.start == s + assert interval.end == e + + interval = maya.MayaInterval.from_iso8601( + "2018-03-05T14:27:18Z/P2W" + ) + s = maya.when("2018-03-05T14:27:18Z") + e = maya.when("2018-03-19T14:27:18Z") + + assert interval.start == s + assert interval.end == e