rtutil: Add RTDateTime class.
See comments for rationale.
This commit is contained in:
parent
9e33b2795c
commit
7335282e5a
3 changed files with 58 additions and 0 deletions
|
@ -5,6 +5,7 @@
|
||||||
# Full copyright and licensing details can be found at toplevel file
|
# Full copyright and licensing details can be found at toplevel file
|
||||||
# LICENSE.txt in the repository.
|
# LICENSE.txt in the repository.
|
||||||
|
|
||||||
|
import datetime
|
||||||
import functools
|
import functools
|
||||||
import logging
|
import logging
|
||||||
import mimetypes
|
import mimetypes
|
||||||
|
@ -13,6 +14,7 @@ import re
|
||||||
import sqlite3
|
import sqlite3
|
||||||
import urllib.parse as urlparse
|
import urllib.parse as urlparse
|
||||||
|
|
||||||
|
import dateutil.parser
|
||||||
import rt
|
import rt
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
@ -21,6 +23,7 @@ from . import data
|
||||||
from beancount.core import data as bc_data
|
from beancount.core import data as bc_data
|
||||||
|
|
||||||
from typing import (
|
from typing import (
|
||||||
|
cast,
|
||||||
overload,
|
overload,
|
||||||
Callable,
|
Callable,
|
||||||
Iterable,
|
Iterable,
|
||||||
|
@ -40,6 +43,28 @@ TicketAttachmentIds = Tuple[str, Optional[str]]
|
||||||
_LinkCache = MutableMapping[TicketAttachmentIds, Optional[str]]
|
_LinkCache = MutableMapping[TicketAttachmentIds, Optional[str]]
|
||||||
_URLLookup = Callable[..., 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):
|
class RTLinkCache(_LinkCache):
|
||||||
"""Cache RT links to disk
|
"""Cache RT links to disk
|
||||||
|
|
||||||
|
|
1
setup.py
1
setup.py
|
@ -17,6 +17,7 @@ setup(
|
||||||
# 1.4.1 crashes when trying to save some documents.
|
# 1.4.1 crashes when trying to save some documents.
|
||||||
'odfpy>=1.4.0,!=1.4.1', # Debian:python3-odf
|
'odfpy>=1.4.0,!=1.4.1', # Debian:python3-odf
|
||||||
'pdfminer.six>=20200101',
|
'pdfminer.six>=20200101',
|
||||||
|
'python-dateutil>=2.7', # Debian:python3-dateutil
|
||||||
'PyYAML>=3.0', # Debian:python3-yaml
|
'PyYAML>=3.0', # Debian:python3-yaml
|
||||||
'regex', # Debian:python3-regex
|
'regex', # Debian:python3-regex
|
||||||
'rt>=2.0',
|
'rt>=2.0',
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
# LICENSE.txt in the repository.
|
# LICENSE.txt in the repository.
|
||||||
|
|
||||||
import contextlib
|
import contextlib
|
||||||
|
import datetime
|
||||||
import itertools
|
import itertools
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
|
@ -287,3 +288,34 @@ def test_txn_with_urls_with_fmts(rt):
|
||||||
f'<{DEFAULT_RT_URL}{statement_path}>',
|
f'<{DEFAULT_RT_URL}{statement_path}>',
|
||||||
'[stmt.txt]',
|
'[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
|
||||||
|
|
Loading…
Reference in a new issue