|
@@ -3,34 +3,37 @@ import dateutil.parser
|
|
|
import dateutil.tz.tz
|
|
|
import re
|
|
|
|
|
|
+
|
|
|
def construct_yaml_timestamp(loader, node):
|
|
|
loaded_dt = loader.construct_yaml_timestamp(node)
|
|
|
if type(loaded_dt) is datetime.datetime and loaded_dt.tzinfo is None:
|
|
|
timezone_match = re.search(
|
|
|
r'(Z|(?P<sign>[\+-])(?P<h>\d{2}):(?P<m>\d{2}))$',
|
|
|
loader.construct_yaml_str(node),
|
|
|
- )
|
|
|
+ )
|
|
|
if timezone_match:
|
|
|
# loader.construct_yaml_timestamp converts to UTC
|
|
|
- loaded_dt = loaded_dt.replace(tzinfo = dateutil.tz.tz.tzutc())
|
|
|
+ loaded_dt = loaded_dt.replace(tzinfo=dateutil.tz.tz.tzutc())
|
|
|
timezone_attr = timezone_match.groupdict()
|
|
|
if timezone_attr['h']:
|
|
|
timezone = dateutil.tz.tz.tzoffset(
|
|
|
- name = timezone_match.group(0),
|
|
|
- offset = (int(timezone_attr['h']) * 60 + int(timezone_attr['m'])) * 60
|
|
|
- * (-1 if timezone_attr['sign'] == '-' else 1),
|
|
|
- )
|
|
|
+ name = timezone_match.group(0),
|
|
|
+ offset = (int(timezone_attr['h']) * 60 + int(timezone_attr['m'])) * 60
|
|
|
+ * (-1 if timezone_attr['sign'] == '-' else 1),
|
|
|
+ )
|
|
|
loaded_dt = loaded_dt.astimezone(timezone)
|
|
|
return loaded_dt
|
|
|
|
|
|
-def register_yaml_timestamp_constructor(loader, tag = u'tag:yaml.org,2002:timestamp'):
|
|
|
+
|
|
|
+def register_yaml_timestamp_constructor(loader, tag=u'tag:yaml.org,2002:timestamp'):
|
|
|
loader.add_constructor(tag, construct_yaml_timestamp)
|
|
|
|
|
|
+
|
|
|
class Duration(object):
|
|
|
|
|
|
yaml_tag = u'!duration'
|
|
|
|
|
|
- def __init__(self, years = 0):
|
|
|
+ def __init__(self, years=0):
|
|
|
self.years = years
|
|
|
|
|
|
@property
|
|
@@ -59,34 +62,40 @@ class Duration(object):
|
|
|
return cls(**loader.construct_mapping(node))
|
|
|
|
|
|
@classmethod
|
|
|
- def register_yaml_constructor(cls, loader, tag = yaml_tag):
|
|
|
+ def register_yaml_constructor(cls, loader, tag=yaml_tag):
|
|
|
loader.add_constructor(tag, cls.from_yaml)
|
|
|
|
|
|
@classmethod
|
|
|
- def to_yaml(cls, dumper, duration, tag = yaml_tag):
|
|
|
+ def to_yaml(cls, dumper, duration, tag=yaml_tag):
|
|
|
return dumper.represent_mapping(
|
|
|
- tag = tag,
|
|
|
- mapping = {k: v for k, v in {
|
|
|
+ tag=tag,
|
|
|
+ mapping={k: v for k, v in {
|
|
|
'years': duration.years,
|
|
|
}.items() if v != 0},
|
|
|
- )
|
|
|
+ )
|
|
|
|
|
|
@classmethod
|
|
|
def register_yaml_representer(cls, dumper):
|
|
|
dumper.add_representer(cls, cls.to_yaml)
|
|
|
|
|
|
+
|
|
|
class Period(object):
|
|
|
|
|
|
yaml_tag = u'!period'
|
|
|
|
|
|
_timestamp_iso_format = r'\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(.\d+)?(Z|[-\+]\d{2}:\d{2})?'
|
|
|
- _timeperiod_iso_format = r'(?P<start>%(t)s)\/(?P<end>%(t)s)' % {'t': _timestamp_iso_format}
|
|
|
+ _timeperiod_iso_format = r'(?P<start>{t})\/(?P<end>{t})'.format(
|
|
|
+ t=_timestamp_iso_format,
|
|
|
+ )
|
|
|
|
|
|
- def __init__(self, start = None, end = None, isoformat = None):
|
|
|
+ def __init__(self, start=None, end=None, isoformat=None):
|
|
|
self._start = None
|
|
|
self._end = None
|
|
|
if (start or end) and isoformat:
|
|
|
- raise AttributeError('when providing isoformat no other parameters may be specified')
|
|
|
+ raise AttributeError(
|
|
|
+ 'when providing isoformat no other'
|
|
|
+ + ' parameters may be specified',
|
|
|
+ )
|
|
|
elif isoformat:
|
|
|
self.isoformat = isoformat
|
|
|
else:
|
|
@@ -118,9 +127,9 @@ class Period(object):
|
|
|
if self.start is None or self.end is None:
|
|
|
raise ValueError('both start and end must be set')
|
|
|
return '%s/%s' % (
|
|
|
- self.start.isoformat().replace('+00:00', 'Z'),
|
|
|
- self.end.isoformat().replace('+00:00', 'Z'),
|
|
|
- )
|
|
|
+ self.start.isoformat().replace('+00:00', 'Z'),
|
|
|
+ self.end.isoformat().replace('+00:00', 'Z'),
|
|
|
+ )
|
|
|
|
|
|
@isoformat.setter
|
|
|
def isoformat(self, text):
|