diff --git a/conservancy_beancount/rtutil.py b/conservancy_beancount/rtutil.py index 86653633da35421c01c2bd66b17cdeda4daf4a5a..6893750df539ac031a041485de4d7c9c02fadd76 100644 --- a/conservancy_beancount/rtutil.py +++ b/conservancy_beancount/rtutil.py @@ -5,6 +5,7 @@ # Full copyright and licensing details can be found at toplevel file # LICENSE.txt in the repository. +import datetime import functools import logging import mimetypes @@ -13,6 +14,7 @@ import re import sqlite3 import urllib.parse as urlparse +import dateutil.parser import rt from pathlib import Path @@ -21,6 +23,7 @@ from . import data from beancount.core import data as bc_data from typing import ( + cast, overload, Callable, Iterable, @@ -40,6 +43,28 @@ TicketAttachmentIds = Tuple[str, Optional[str]] _LinkCache = MutableMapping[TicketAttachmentIds, Optional[str]] _URLLookup = Callable[..., Optional[str]] +class RTDateTime(datetime.datetime): + """Construct datetime objects from strings returned by RT + + Typical usage looks like:: + + ticket = rt_client.get_ticket(...) + created = RTDateTime(ticket.get('Created')) + """ + # Normally I'd just write a function to do this, but having a dedicated + # class helps support query-report: the class can pull double duty to both + # parse the data from RT, and determine proper output formatting. + # The RT REST API returns datetimes in the user's configured timezone, and + # there doesn't seem to be any API call that tells you what that is. You + # have to live with the object being timezone-naive. + def __new__(cls, source: str) -> 'RTDateTime': + if not source or source == 'Not set': + retval = datetime.datetime.min + else: + retval = dateutil.parser.parse(source) + return cast(RTDateTime, retval) + + class RTLinkCache(_LinkCache): """Cache RT links to disk