1from geopy.exc import GeocoderParseError
2
3try:
4    import pytz
5    pytz_available = True
6except ImportError:
7    pytz_available = False
8
9
10__all__ = (
11    "Timezone",
12)
13
14
15def ensure_pytz_is_installed():
16    if not pytz_available:
17        raise ImportError(
18            'pytz must be installed in order to locate timezones. '
19            'If geopy has been installed with `pip`, then pytz can be '
20            'installed with `pip install "geopy[timezone]"`.'
21        )
22
23
24def from_timezone_name(timezone_name, raw):
25    ensure_pytz_is_installed()
26    try:
27        pytz_timezone = pytz.timezone(timezone_name)
28    except pytz.UnknownTimeZoneError:
29        raise GeocoderParseError(
30            "pytz could not parse the timezone identifier (%s) "
31            "returned by the service." % timezone_name
32        )
33    except KeyError:
34        raise GeocoderParseError(
35            "geopy could not find a timezone in this response: %s" %
36            raw
37        )
38    return Timezone(pytz_timezone, raw)
39
40
41def from_fixed_gmt_offset(gmt_offset_hours, raw):
42    ensure_pytz_is_installed()
43    pytz_timezone = pytz.FixedOffset(gmt_offset_hours * 60)
44    return Timezone(pytz_timezone, raw)
45
46
47class Timezone:
48    """
49    Contains a parsed response for a timezone request, which is
50    implemented in few geocoders which provide such lookups.
51    """
52
53    __slots__ = ("_pytz_timezone", "_raw")
54
55    def __init__(self, pytz_timezone, raw):
56        self._pytz_timezone = pytz_timezone
57        self._raw = raw
58
59    @property
60    def pytz_timezone(self):
61        """
62        pytz timezone instance.
63
64        :rtype: :class:`pytz.tzinfo.BaseTzInfo`
65        """
66        return self._pytz_timezone
67
68    @property
69    def raw(self):
70        """
71        Timezone's raw, unparsed geocoder response. For details on this,
72        consult the service's documentation.
73
74        :rtype: dict
75        """
76        return self._raw
77
78    def __str__(self):
79        return str(self._pytz_timezone)
80
81    def __repr__(self):
82        return "Timezone(%s)" % repr(self.pytz_timezone)
83
84    def __getstate__(self):
85        return self._pytz_timezone, self._raw
86
87    def __setstate__(self, state):
88        self._pytz_timezone, self._raw = state
89
90    def __eq__(self, other):
91        return (
92            isinstance(other, Timezone) and
93            self._pytz_timezone == other._pytz_timezone and
94            self.raw == other.raw
95        )
96
97    def __ne__(self, other):
98        return not (self == other)
99