rtutil: Add RTDateTime class.

See comments for rationale.
This commit is contained in:
Brett Smith 2021-03-10 11:57:46 -05:00
parent 9e33b2795c
commit 7335282e5a
3 changed files with 58 additions and 0 deletions

View file

@ -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

View file

@ -17,6 +17,7 @@ setup(
# 1.4.1 crashes when trying to save some documents.
'odfpy>=1.4.0,!=1.4.1', # Debian:python3-odf
'pdfminer.six>=20200101',
'python-dateutil>=2.7', # Debian:python3-dateutil
'PyYAML>=3.0', # Debian:python3-yaml
'regex', # Debian:python3-regex
'rt>=2.0',

View file

@ -6,6 +6,7 @@
# LICENSE.txt in the repository.
import contextlib
import datetime
import itertools
import logging
import re
@ -287,3 +288,34 @@ def test_txn_with_urls_with_fmts(rt):
f'<{DEFAULT_RT_URL}{statement_path}>',
'[stmt.txt]',
])
@pytest.mark.parametrize('arg,exp_num,exp_offset', [
# These correspond to the different datetime formats available through
# RT's user settings.
('Mon Mar 1 01:01:01 2021', 1, None),
('2021-03-02 02:02:02', 2, None),
('2021-03-03T03:03:03-0500', 3, -18000),
('Thu, 4 Mar 2021 04:04:04 -0600', 4, -21600),
('Fri, 5 Mar 2021 05:05:05 GMT', 5, 0),
('20210306T060606Z', 6, 0),
('Sun, Mar 7, 2021 07:07:07 AM', 7, None),
('Sun, Mar 14, 2021 02:14:14 PM', 14, None),
])
def test_rt_datetime(arg, exp_num, exp_offset):
actual = rtutil.RTDateTime(arg)
assert actual.year == 2021
assert actual.month == 3
assert actual.day == exp_num
assert actual.hour == exp_num
assert actual.minute == exp_num
assert actual.second == exp_num
if exp_offset is None:
assert actual.tzinfo is None
else:
assert actual.tzinfo.utcoffset(None).total_seconds() == exp_offset
@pytest.mark.parametrize('arg', ['Not set', '', None])
def test_rt_datetime_empty(arg):
actual = rtutil.RTDateTime(arg)
assert actual == datetime.datetime.min
assert actual.tzinfo is None