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 time
import logging
from datetime import datetime
from datetime import timedelta
from datetime import timezone
from datetime import tzinfo
log = logging.getLogger('gajim.c.m.date_and_time')
PATTERN_DATETIME = re.compile(
r'([0-9]{4}-[0-9]{2}-[0-9]{2})'
@ -94,7 +96,30 @@ class LocalTimezone(tzinfo):
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))

View File

@ -15,13 +15,14 @@
# XEP-0202: Entity Time
import logging
import datetime
import time
import nbxmpp
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')
@ -61,8 +62,8 @@ class EntityTime:
log.info('Received: %s %s',
stanza.getFrom(), time_info)
app.nec.push_incoming_event(
TimeResultReceivedEvent(None, conn=self._con,
app.nec.push_incoming_event(NetworkEvent('time-result-received',
conn=self._con,
jid=stanza.getFrom(),
time_info=time_info))
@ -74,42 +75,24 @@ class EntityTime:
return
tzo = time_.getTag('tzo').getData()
if tzo.lower() == 'z':
tzo = '0:0'
try:
tzoh, tzom = tzo.split(':')
except Exception:
if not tzo:
log.warning('Wrong tzo node: %s', stanza)
return
utc_time = time_.getTag('utc').getData()
if utc_time[-1:] == 'Z':
# Remove the trailing 'Z'
utc_time = utc_time[:-1]
elif utc_time[-6:] == "+00:00":
# Remove the trailing "+00:00"
utc_time = utc_time[:-6]
else:
remote_tz = create_tzinfo(tz_string=tzo)
if remote_tz is None:
log.warning('Wrong tzo node: %s', stanza)
return
utc_time = time_.getTag('utc').getData()
date_time = parse_datetime(utc_time, check_utc=True)
if date_time is None:
log.warning('Wrong timezone defintion: %s %s',
utc_time, stanza.getFrom())
return
try:
dtime = datetime.datetime.strptime(utc_time, '%Y-%m-%dT%H:%M:%S')
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')
date_time = date_time.astimezone(remote_tz)
return date_time.strftime('%c %Z')
def _answer_request(self, _con, stanza):
log.info('%s asked for the time', stanza.getFrom())
@ -132,9 +115,5 @@ class EntityTime:
raise nbxmpp.NodeProcessed
class TimeResultReceivedEvent(NetworkIncomingEvent):
name = 'time-result-received'
def get_instance(*args, **kwargs):
return EntityTime(*args, **kwargs), 'EntityTime'