Improve Entity Time parsing

- Use parse_datetime()
- Improve tzo node validation
This commit is contained in:
Philipp Hörist 2018-11-16 23:11:05 +01:00
parent f40f171ecd
commit d13baed80f
2 changed files with 44 additions and 40 deletions

View File

@ -16,11 +16,13 @@
import re import re
import time import time
import logging
from datetime import datetime from datetime import datetime
from datetime import timedelta from datetime import timedelta
from datetime import timezone from datetime import timezone
from datetime import tzinfo from datetime import tzinfo
log = logging.getLogger('gajim.c.m.date_and_time')
PATTERN_DATETIME = re.compile( PATTERN_DATETIME = re.compile(
r'([0-9]{4}-[0-9]{2}-[0-9]{2})' r'([0-9]{4}-[0-9]{2}-[0-9]{2})'
@ -94,7 +96,30 @@ class LocalTimezone(tzinfo):
return tt.tm_isdst > 0 return tt.tm_isdst > 0
def create_tzinfo(hours=0, minutes=0): def create_tzinfo(hours=0, minutes=0, tz_string=None):
if tz_string is None:
return timezone(timedelta(hours=hours, minutes=minutes))
if tz_string.lower() == 'z':
return timezone.utc
try:
hours, minutes = map(int, tz_string.split(':'))
except Exception:
log.warning('Wrong tz string: %s', tz_string)
return
if hours not in range(-24, 24):
log.warning('Wrong tz string: %s', tz_string)
return
if minutes not in range(0, 59):
log.warning('Wrong tz string: %s', tz_string)
return
if hours in (24, -24) and minutes != 0:
log.warning('Wrong tz string: %s', tz_string)
return
return timezone(timedelta(hours=hours, minutes=minutes)) return timezone(timedelta(hours=hours, minutes=minutes))

View File

@ -15,13 +15,14 @@
# XEP-0202: Entity Time # XEP-0202: Entity Time
import logging import logging
import datetime
import time import time
import nbxmpp import nbxmpp
from gajim.common import app from gajim.common import app
from gajim.common.nec import NetworkIncomingEvent from gajim.common.nec import NetworkEvent
from gajim.common.modules.date_and_time import parse_datetime
from gajim.common.modules.date_and_time import create_tzinfo
log = logging.getLogger('gajim.c.m.entity_time') log = logging.getLogger('gajim.c.m.entity_time')
@ -61,10 +62,10 @@ class EntityTime:
log.info('Received: %s %s', log.info('Received: %s %s',
stanza.getFrom(), time_info) stanza.getFrom(), time_info)
app.nec.push_incoming_event( app.nec.push_incoming_event(NetworkEvent('time-result-received',
TimeResultReceivedEvent(None, conn=self._con, conn=self._con,
jid=stanza.getFrom(), jid=stanza.getFrom(),
time_info=time_info)) time_info=time_info))
@staticmethod @staticmethod
def _extract_info(stanza): def _extract_info(stanza):
@ -74,42 +75,24 @@ class EntityTime:
return return
tzo = time_.getTag('tzo').getData() tzo = time_.getTag('tzo').getData()
if tzo.lower() == 'z': if not tzo:
tzo = '0:0'
try:
tzoh, tzom = tzo.split(':')
except Exception:
log.warning('Wrong tzo node: %s', stanza) log.warning('Wrong tzo node: %s', stanza)
return return
utc_time = time_.getTag('utc').getData()
if utc_time[-1:] == 'Z': remote_tz = create_tzinfo(tz_string=tzo)
# Remove the trailing 'Z' if remote_tz is None:
utc_time = utc_time[:-1] log.warning('Wrong tzo node: %s', stanza)
elif utc_time[-6:] == "+00:00": return
# Remove the trailing "+00:00"
utc_time = utc_time[:-6] utc_time = time_.getTag('utc').getData()
else: date_time = parse_datetime(utc_time, check_utc=True)
if date_time is None:
log.warning('Wrong timezone defintion: %s %s', log.warning('Wrong timezone defintion: %s %s',
utc_time, stanza.getFrom()) utc_time, stanza.getFrom())
return return
try: date_time = date_time.astimezone(remote_tz)
dtime = datetime.datetime.strptime(utc_time, '%Y-%m-%dT%H:%M:%S') return date_time.strftime('%c %Z')
except ValueError:
try:
dtime = datetime.datetime.strptime(utc_time,
'%Y-%m-%dT%H:%M:%S.%f')
except ValueError as error:
log.warning('Wrong time format: %s %s',
error, stanza.getFrom())
return
utc = datetime.timezone(datetime.timedelta(0))
dtime = dtime.replace(tzinfo=utc)
utc_offset = datetime.timedelta(hours=int(tzoh), minutes=int(tzom))
contact_tz = datetime.timezone(utc_offset, "remote timezone")
return dtime.astimezone(contact_tz).strftime('%c')
def _answer_request(self, _con, stanza): def _answer_request(self, _con, stanza):
log.info('%s asked for the time', stanza.getFrom()) log.info('%s asked for the time', stanza.getFrom())
@ -132,9 +115,5 @@ class EntityTime:
raise nbxmpp.NodeProcessed raise nbxmpp.NodeProcessed
class TimeResultReceivedEvent(NetworkIncomingEvent):
name = 'time-result-received'
def get_instance(*args, **kwargs): def get_instance(*args, **kwargs):
return EntityTime(*args, **kwargs), 'EntityTime' return EntityTime(*args, **kwargs), 'EntityTime'