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 | ||||
| # 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 | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										1
									
								
								setup.py
									
										
									
									
									
								
							
							
						
						
									
										1
									
								
								setup.py
									
										
									
									
									
								
							|  | @ -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', | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue
	
	 Brett Smith
						Brett Smith