diff --git a/mypy.ini b/mypy.ini --- a/mypy.ini +++ b/mypy.ini @@ -11,6 +11,9 @@ [mypy-dulwich.*] ignore_missing_imports = True +[mypy-iso8601.*] +ignore_missing_imports = True + [mypy-pkg_resources.*] ignore_missing_imports = True diff --git a/requirements.txt b/requirements.txt --- a/requirements.txt +++ b/requirements.txt @@ -5,3 +5,4 @@ attrs hypothesis python-dateutil +iso8601 diff --git a/swh/model/model.py b/swh/model/model.py --- a/swh/model/model.py +++ b/swh/model/model.py @@ -7,10 +7,11 @@ from abc import ABCMeta, abstractmethod from enum import Enum -from typing import List, Optional, Dict +from typing import List, Optional, Dict, Union import attr import dateutil.parser +import iso8601 from .identifiers import ( normalize_timestamp, directory_identifier, revision_identifier, @@ -124,15 +125,28 @@ raise ValueError('offset too large: %d minutes' % value) @classmethod - def from_dict(cls, d): + def from_dict(cls, obj: Union[Dict, datetime.datetime, int]): """Builds a TimestampWithTimezone from any of the formats accepted by :func:`swh.model.normalize_timestamp`.""" - d = normalize_timestamp(d) + # TODO: this accept way more types than just dicts; find a better + # name + d = normalize_timestamp(obj) return cls( timestamp=Timestamp.from_dict(d['timestamp']), offset=d['offset'], negative_utc=d['negative_utc']) + @classmethod + def from_datetime(cls, dt: datetime.datetime): + return cls.from_dict(dt) + + @classmethod + def from_iso8601(cls, s): + """Builts a TimestampWithTimezone from an ISO8601-formatted string. + """ + d = iso8601.parse_date(s) + return cls.from_datetime(d) + @attr.s(frozen=True) class Origin(BaseModel):