Jelajahi Sumber

datetimeex: added Duration.from_iso() & Duration.iso_format

Fabian Peter Hammerle 8 tahun lalu
induk
melakukan
e64bb4d137
2 mengubah file dengan 40 tambahan dan 0 penghapusan
  1. 18 0
      ioex/datetimeex.py
  2. 22 0
      tests/datetimeex/test_duration.py

+ 18 - 0
ioex/datetimeex.py

@@ -35,6 +35,8 @@ class Duration(object):
 
     yaml_tag = u'!duration'
 
+    iso_format = r'P((?P<y>\d+)Y)?((?P<d>\d+)D)?'
+
     years = ioex.classex.AttributeDescriptor('_years', types=(int,), min=0)
     days = ioex.classex.AttributeDescriptor('_days', types=(int,), min=0)
 
@@ -51,6 +53,22 @@ class Duration(object):
         )
         return 'P0Y' if iso_str == 'P' else iso_str
 
+    @classmethod
+    def from_iso(cls, iso):
+        match = re.search(
+            r'^{}$'.format(cls.iso_format),
+            iso,
+        )
+        if not match:
+            raise ValueError('unsupported string {!r}'.format(iso))
+        else:
+            attr = {k: int(v) if v is not None else 0
+                    for k, v in match.groupdict().items()}
+            return cls(
+                years=attr['y'],
+                days=attr['d'],
+            )
+
     def __eq__(self, other):
         return (type(self) == type(other)
                 and self.years == other.years

+ 22 - 0
tests/datetimeex/test_duration.py

@@ -90,6 +90,28 @@ def test_get_isoformat(init_params, iso):
     assert d.isoformat == iso
 
 
+@pytest.mark.parametrize(('expected', 'source_iso'), [
+    [Duration(years=0), 'P0Y'],
+    [Duration(years=30), 'P30Y'],
+    [Duration(years=3), 'P3Y'],
+    [Duration(days=30), 'P30D'],
+    [Duration(days=3), 'P3D'],
+    [Duration(years=10, days=30), 'P10Y30D'],
+])
+def test_from_iso(expected, source_iso):
+    d = Duration.from_iso(source_iso)
+    assert expected == d
+
+
+@pytest.mark.parametrize(('source_iso'), [
+    'Q0Y',
+    '2017-05-19T20:02:22+02:00',
+])
+def test_from_iso_fail(source_iso):
+    with pytest.raises(ValueError):
+        Duration.from_iso(source_iso)
+
+
 @pytest.mark.parametrize(('a', 'b'), [
     [Duration(), Duration(years=0, days=0)],
     [Duration(years=0), Duration(years=0)],