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 _extract_info(self, stanza): time_ = stanza.getTag('time') if not time_: self._log.warning('No time node: %s', stanza) return None tzo = time_.getTag('tzo').getData() if not tzo: self._log.warning('Wrong tzo node: %s', stanza) return None remote_tz = create_tzinfo(tz_string=tzo) if remote_tz is None: self._log.warning('Wrong tzo node: %s', stanza) return None utc_time = time_.getTag('utc').getData() date_time = parse_datetime(utc_time, check_utc=True) if date_time is None: self._log.warning('Wrong timezone definition: %s %s', utc_time, stanza.getFrom()) return None date_time = date_time.astimezone(remote_tz) return date_time.strftime('%c %Z')
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)
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 _parse_public_key(jid, item): pub_key = item.getTag('pubkey', namespace=Namespace.OPENPGP) if pub_key is None: raise ValueError('pubkey node missing') date = parse_datetime(pub_key.getAttr('date'), epoch=True) data = pub_key.getTag('data') if data is None: raise ValueError('data node missing') try: key = b64decode(data.getData(), return_type=bytes) except Exception as error: raise ValueError(f'decoding error: {error}') return PGPPublicKey(jid, key, date)
def _process_idle(self, _client, stanza, properties): idle_tag = stanza.getTag('idle', namespace=Namespace.IDLE) if idle_tag is None: return since = idle_tag.getAttr('since') if since is None: self._log.warning('No since attr in idle node') self._log.warning(stanza) return timestamp = parse_datetime(since, convert='utc', epoch=True) if timestamp is None: self._log.warning('Invalid timestamp received: %s', since) self._log.warning(stanza) properties.idle_timestamp = timestamp
def _parse_keylist(jid, item): keylist_node = item.getTag('public-keys-list', namespace=Namespace.OPENPGP) if keylist_node is None: raise ValueError('public-keys-list node missing') metadata = keylist_node.getTags('pubkey-metadata') if not metadata: return None data = [] for key in metadata: fingerprint = key.getAttr('v4-fingerprint') date = key.getAttr('date') if fingerprint is None or date is None: raise ValueError('Invalid metadata node') timestamp = parse_datetime(date, epoch=True) if timestamp is None: raise ValueError('Invalid date timestamp: %s' % date) data.append(PGPKeyMetadata(jid, fingerprint, timestamp)) return data
def parse_delay(stanza, epoch=True, convert='utc', from_=None, not_from=None): ''' Returns the first valid delay timestamp that matches :param epoch: Returns the timestamp as epoch :param convert: Converts the timestamp to either utc or local :param from_: Matches only delays that have the according from attr set :param not_from: Matches only delays that have the according from attr not set ''' delays = stanza.getTags('delay', namespace=Namespace.DELAY2) for delay in delays: stamp = delay.getAttr('stamp') if stamp is None: log.warning('Invalid timestamp received: %s', stamp) log.warning(stanza) continue delay_from = delay.getAttr('from') if from_ is not None: if delay_from not in from_: continue if not_from is not None: if delay_from in not_from: continue timestamp = parse_datetime(stamp, check_utc=True, epoch=epoch, convert=convert) if timestamp is None: log.warning('Invalid timestamp received: %s', stamp) log.warning(stanza) continue return timestamp
def _parse_response(response): time_ = response.getTag('time') if not time_: raise MalformedStanzaError('time node missing', response) tzo = time_.getTagData('tzo') if not tzo: raise MalformedStanzaError('tzo node or data missing', response) remote_tz = create_tzinfo(tz_string=tzo) if remote_tz is None: raise MalformedStanzaError('invalid tzo data', response) utc_time = time_.getTagData('utc') if not utc_time: raise MalformedStanzaError('utc node or data missing', response) date_time = parse_datetime(utc_time, check_utc=True) if date_time is None: raise MalformedStanzaError('invalid timezone definition', response) date_time = date_time.astimezone(remote_tz) return date_time.strftime('%c %Z')
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()))