diff --git a/src/pytz/__init__.py b/src/pytz/__init__.py index 5c05066..2eb8066 100644 --- a/src/pytz/__init__.py +++ b/src/pytz/__init__.py @@ -8,9 +8,11 @@ See the datetime section of the Python Library Reference for information on how to use these modules. ''' -import sys +import collections import datetime import os.path +import re +import sys from pytz.exceptions import AmbiguousTimeError from pytz.exceptions import InvalidTimeError @@ -297,6 +299,52 @@ def _p(*args): _p.__safe_for_unpickling__ = True +def _zone_tab(): + zonetype = collections.namedtuple('Zone', ('code', 'coordinates', 'zone', 'comment')) + with open_resource('zone.tab') as fobj: + for line in fobj: + line = line.decode('UTF-8') + if line.startswith('#'): + continue + pieces = line.split(None, 4) + code, coordinates, zone = pieces[:3] + comment = len(pieces) == 4 and pieces[3] or '' + if zone not in all_timezones_set: + continue + + coordinates = _parse_iso6709(coordinates) + if not coordinates: + continue + lat, lon = coordinates + + yield zonetype(code, (lat, lon), zone, comment) + + +zone_tab = LazyList(_zone_tab()) + + +def _parse_iso6709(iso6709): + match = re.match('^([-+][0-9]+)([-+][0-9]+)$', iso6709) + if not match: + return + return map(_parse_iso6709_coord, match.groups()) + + +def _parse_iso6709_coord(coord): + if len(coord) % 2: + deg = float(coord[:3]) + coord = coord[3:] + else: + deg = float(coord[:4]) + coord = coord[4:] + div = 60 + while coord: + deg += float(coord[:2]) / div + div *= 60 + coord = coord[2:] + return deg + + class _CountryTimezoneDict(LazyDict): """Map ISO 3166 country code to a list of timezone names commonly used in that country. @@ -334,23 +382,10 @@ class _CountryTimezoneDict(LazyDict): return self[iso3166_code] def _fill(self): - data = {} - zone_tab = open_resource('zone.tab') - try: - for line in zone_tab: - line = line.decode('UTF-8') - if line.startswith('#'): - continue - code, coordinates, zone = line.split(None, 4)[:3] - if zone not in all_timezones_set: # noqa - continue - try: - data[code].append(zone) - except KeyError: - data[code] = [zone] - self.data = data - finally: - zone_tab.close() + data = collections.defaultdict(list) + for code, _, zone, _ in zone_tab: + data[code].append(zone) + self.data = data country_timezones = _CountryTimezoneDict()