Refactor parse_datetime and add unit test

This commit is contained in:
Philipp Hörist 2018-11-17 13:21:05 +01:00
parent 31e75823fd
commit 00c7715c01
2 changed files with 129 additions and 4 deletions

View File

@ -16,7 +16,10 @@
import re import re
import time import time
from datetime import datetime, timedelta, timezone, tzinfo from datetime import datetime
from datetime import timedelta
from datetime import timezone
from datetime import tzinfo
PATTERN_DATETIME = re.compile( PATTERN_DATETIME = re.compile(
@ -91,6 +94,10 @@ class LocalTimezone(tzinfo):
return tt.tm_isdst > 0 return tt.tm_isdst > 0
def create_tzinfo(hours=0, minutes=0):
return timezone(timedelta(hours=hours, minutes=minutes))
def parse_datetime(timestring, check_utc=False, def parse_datetime(timestring, check_utc=False,
convert='utc', epoch=False): convert='utc', epoch=False):
''' '''
@ -133,11 +140,30 @@ def parse_datetime(timestring, check_utc=False,
except ValueError: except ValueError:
pass pass
else: else:
if not check_utc and convert == 'utc': if check_utc:
if convert != 'utc':
raise ValueError(
'check_utc can only be used with convert="utc"')
date_time.replace(tzinfo=timezone.utc)
if epoch:
return date_time.timestamp()
return date_time
if convert == 'utc':
date_time = date_time.astimezone(timezone.utc) date_time = date_time.astimezone(timezone.utc)
if epoch:
return date_time.timestamp()
return date_time
if epoch:
# epoch is always UTC, use convert='utc' or check_utc=True
raise ValueError(
'epoch not available while converting to local')
if convert == 'local': if convert == 'local':
date_time = date_time.astimezone(LocalTimezone()) date_time = date_time.astimezone(LocalTimezone())
if epoch: return date_time
return date_time.timestamp()
# convert=None
return date_time return date_time
return None return None

View File

@ -0,0 +1,99 @@
import unittest
from datetime import datetime
from datetime import timezone
from datetime import timedelta
from gajim.common.modules.date_and_time import parse_datetime
from gajim.common.modules.date_and_time import LocalTimezone
from gajim.common.modules.date_and_time import create_tzinfo
class TestDateTime(unittest.TestCase):
def test_convert_to_utc(self):
strings = {
# Valid UTC strings and fractions
'2017-11-05T01:41:20Z': 1509846080.0,
'2017-11-05T01:41:20.123Z': 1509846080.123,
'2017-11-05T01:41:20.123123123+00:00': 1509846080.123123,
'2017-11-05T01:41:20.123123123123123-00:00': 1509846080.123123,
# Invalid strings
'2017-11-05T01:41:20Z+05:00': None,
'2017-11-05T01:41:20+0000': None,
'2017-11-05T01:41:20-0000': None,
# Valid strings with offset
'2017-11-05T01:41:20-05:00': 1509864080.0,
'2017-11-05T01:41:20+05:00': 1509828080.0,
}
strings2 = {
# Valid strings with offset
'2017-11-05T01:41:20-05:00': datetime(2017, 11, 5, 1, 41, 20, 0, create_tzinfo(hours=-5)),
'2017-11-05T01:41:20+05:00': datetime(2017, 11, 5, 1, 41, 20, 0, create_tzinfo(hours=5)),
}
for time_string, expected_value in strings.items():
result = parse_datetime(time_string, convert='utc', epoch=True)
self.assertEqual(result, expected_value)
for time_string, expected_value in strings2.items():
result = parse_datetime(time_string, convert='utc')
self.assertEqual(result, expected_value.astimezone(timezone.utc))
def test_convert_to_local(self):
strings = {
# Valid UTC strings and fractions
'2017-11-05T01:41:20Z': datetime(2017, 11, 5, 1, 41, 20, 0, timezone.utc),
'2017-11-05T01:41:20.123Z': datetime(2017, 11, 5, 1, 41, 20, 123000, timezone.utc),
'2017-11-05T01:41:20.123123123+00:00': datetime(2017, 11, 5, 1, 41, 20, 123123, timezone.utc),
'2017-11-05T01:41:20.123123123123123-00:00': datetime(2017, 11, 5, 1, 41, 20, 123123, timezone.utc),
# Valid strings with offset
'2017-11-05T01:41:20-05:00': datetime(2017, 11, 5, 1, 41, 20, 0, create_tzinfo(hours=-5)),
'2017-11-05T01:41:20+05:00': datetime(2017, 11, 5, 1, 41, 20, 0, create_tzinfo(hours=5)),
}
for time_string, expected_value in strings.items():
result = parse_datetime(time_string, convert='local')
self.assertEqual(result, expected_value.astimezone(LocalTimezone()))
def test_no_convert(self):
strings = {
# Valid UTC strings and fractions
'2017-11-05T01:41:20Z': timedelta(0),
'2017-11-05T01:41:20.123Z': timedelta(0),
'2017-11-05T01:41:20.123123123+00:00': timedelta(0),
'2017-11-05T01:41:20.123123123123123-00:00': timedelta(0),
# Valid strings with offset
'2017-11-05T01:41:20-05:00': timedelta(hours=-5),
'2017-11-05T01:41:20+05:00': timedelta(hours=5),
}
for time_string, expected_value in strings.items():
result = parse_datetime(time_string, convert=None)
self.assertEqual(result.utcoffset(), expected_value)
def test_check_utc(self):
strings = {
# Valid UTC strings and fractions
'2017-11-05T01:41:20Z': 1509846080.0,
'2017-11-05T01:41:20.123Z': 1509846080.123,
'2017-11-05T01:41:20.123123123+00:00': 1509846080.123123,
'2017-11-05T01:41:20.123123123123123-00:00': 1509846080.123123,
# Valid strings with offset
'2017-11-05T01:41:20-05:00': None,
'2017-11-05T01:41:20+05:00': None,
}
for time_string, expected_value in strings.items():
result = parse_datetime(
time_string, check_utc=True, epoch=True)
self.assertEqual(result, expected_value)