diff --git a/lib/pytz_deprecation_shim/__init__.py b/lib/pytz_deprecation_shim/__init__.py deleted file mode 100644 index 8b451620..00000000 --- a/lib/pytz_deprecation_shim/__init__.py +++ /dev/null @@ -1,34 +0,0 @@ -__all__ = [ - "AmbiguousTimeError", - "NonExistentTimeError", - "InvalidTimeError", - "UnknownTimeZoneError", - "PytzUsageWarning", - "FixedOffset", - "UTC", - "utc", - "build_tzinfo", - "timezone", - "fixed_offset_timezone", - "wrap_zone", -] - -from . import helpers -from ._exceptions import ( - AmbiguousTimeError, - InvalidTimeError, - NonExistentTimeError, - PytzUsageWarning, - UnknownTimeZoneError, -) -from ._impl import ( - UTC, - build_tzinfo, - fixed_offset_timezone, - timezone, - wrap_zone, -) - -# Compatibility aliases -utc = UTC -FixedOffset = fixed_offset_timezone diff --git a/lib/pytz_deprecation_shim/_common.py b/lib/pytz_deprecation_shim/_common.py deleted file mode 100644 index ace322e9..00000000 --- a/lib/pytz_deprecation_shim/_common.py +++ /dev/null @@ -1,13 +0,0 @@ -import sys - -_PYTZ_IMPORTED = False - - -def pytz_imported(): - """Detects whether or not pytz has been imported without importing pytz.""" - global _PYTZ_IMPORTED - - if not _PYTZ_IMPORTED and "pytz" in sys.modules: - _PYTZ_IMPORTED = True - - return _PYTZ_IMPORTED diff --git a/lib/pytz_deprecation_shim/_compat.py b/lib/pytz_deprecation_shim/_compat.py deleted file mode 100644 index 5b734592..00000000 --- a/lib/pytz_deprecation_shim/_compat.py +++ /dev/null @@ -1,15 +0,0 @@ -import sys - -if sys.version_info[0] == 2: - from . import _compat_py2 as _compat_impl -else: - from . import _compat_py3 as _compat_impl - -UTC = _compat_impl.UTC -get_timezone = _compat_impl.get_timezone -get_timezone_file = _compat_impl.get_timezone_file -get_fixed_offset_zone = _compat_impl.get_fixed_offset_zone -is_ambiguous = _compat_impl.is_ambiguous -is_imaginary = _compat_impl.is_imaginary -enfold = _compat_impl.enfold -get_fold = _compat_impl.get_fold diff --git a/lib/pytz_deprecation_shim/_compat_py2.py b/lib/pytz_deprecation_shim/_compat_py2.py deleted file mode 100644 index f473d267..00000000 --- a/lib/pytz_deprecation_shim/_compat_py2.py +++ /dev/null @@ -1,43 +0,0 @@ -from datetime import timedelta - -from dateutil import tz - -UTC = tz.UTC - - -def get_timezone(key): - if not key: - raise KeyError("Unknown time zone: %s" % key) - - try: - rv = tz.gettz(key) - except Exception: - rv = None - - if rv is None or not isinstance(rv, (tz.tzutc, tz.tzfile)): - raise KeyError("Unknown time zone: %s" % key) - - return rv - - -def get_timezone_file(f, key=None): - return tz.tzfile(f) - - -def get_fixed_offset_zone(offset): - return tz.tzoffset(None, timedelta(minutes=offset)) - - -def is_ambiguous(dt): - return tz.datetime_ambiguous(dt) - - -def is_imaginary(dt): - return not tz.datetime_exists(dt) - - -enfold = tz.enfold - - -def get_fold(dt): - return getattr(dt, "fold", 0) diff --git a/lib/pytz_deprecation_shim/_compat_py3.py b/lib/pytz_deprecation_shim/_compat_py3.py deleted file mode 100644 index 8881abac..00000000 --- a/lib/pytz_deprecation_shim/_compat_py3.py +++ /dev/null @@ -1,58 +0,0 @@ -# Note: This file could use Python 3-only syntax, but at the moment this breaks -# the coverage job on Python 2. Until we make it so that coverage can ignore -# this file only on Python 2, we'll have to stick to 2/3-compatible syntax. -try: - import zoneinfo -except ImportError: - from backports import zoneinfo - -import datetime - -UTC = datetime.timezone.utc - - -def get_timezone(key): - try: - return zoneinfo.ZoneInfo(key) - except (ValueError, OSError): - # TODO: Use `from e` when this file can use Python 3 syntax - raise KeyError(key) - - -def get_timezone_file(f, key=None): - return zoneinfo.ZoneInfo.from_file(f, key=key) - - -def get_fixed_offset_zone(offset): - return datetime.timezone(datetime.timedelta(minutes=offset)) - - -def is_imaginary(dt): - dt_rt = dt.astimezone(UTC).astimezone(dt.tzinfo) - - return not (dt == dt_rt) - - -def is_ambiguous(dt): - if is_imaginary(dt): - return False - - wall_0 = dt - wall_1 = dt.replace(fold=not dt.fold) - - # Ambiguous datetimes can only exist if the offset changes, so we don't - # actually have to check whether dst() or tzname() are different. - same_offset = wall_0.utcoffset() == wall_1.utcoffset() - - return not same_offset - - -def enfold(dt, fold=1): - if dt.fold != fold: - return dt.replace(fold=fold) - else: - return dt - - -def get_fold(dt): - return dt.fold diff --git a/lib/pytz_deprecation_shim/_exceptions.py b/lib/pytz_deprecation_shim/_exceptions.py deleted file mode 100644 index 58d7af0a..00000000 --- a/lib/pytz_deprecation_shim/_exceptions.py +++ /dev/null @@ -1,75 +0,0 @@ -from ._common import pytz_imported - - -class PytzUsageWarning(RuntimeWarning): - """Warning raised when accessing features specific to ``pytz``'s interface. - - This warning is used to direct users of ``pytz``-specific features like the - ``localize`` and ``normalize`` methods towards using the standard - ``tzinfo`` interface, so that these shims can be replaced with one of the - underlying libraries they are wrapping. - """ - - -class UnknownTimeZoneError(KeyError): - """Raised when no time zone is found for a specified key.""" - - -class InvalidTimeError(Exception): - """The base class for exceptions related to folds and gaps.""" - - -class AmbiguousTimeError(InvalidTimeError): - """Exception raised when ``is_dst=None`` for an ambiguous time (fold).""" - - -class NonExistentTimeError(InvalidTimeError): - """Exception raised when ``is_dst=None`` for a non-existent time (gap).""" - - -PYTZ_BASE_ERROR_MAPPING = {} - - -def _make_pytz_derived_errors( - InvalidTimeError_=InvalidTimeError, - AmbiguousTimeError_=AmbiguousTimeError, - NonExistentTimeError_=NonExistentTimeError, - UnknownTimeZoneError_=UnknownTimeZoneError, -): - if PYTZ_BASE_ERROR_MAPPING or not pytz_imported(): - return - - import pytz - - class InvalidTimeError(InvalidTimeError_, pytz.InvalidTimeError): - pass - - class AmbiguousTimeError(AmbiguousTimeError_, pytz.AmbiguousTimeError): - pass - - class NonExistentTimeError( - NonExistentTimeError_, pytz.NonExistentTimeError - ): - pass - - class UnknownTimeZoneError( - UnknownTimeZoneError_, pytz.UnknownTimeZoneError - ): - pass - - PYTZ_BASE_ERROR_MAPPING.update( - { - InvalidTimeError_: InvalidTimeError, - AmbiguousTimeError_: AmbiguousTimeError, - NonExistentTimeError_: NonExistentTimeError, - UnknownTimeZoneError_: UnknownTimeZoneError, - } - ) - - -def get_exception(exc_type, msg): - _make_pytz_derived_errors() - - out_exc_type = PYTZ_BASE_ERROR_MAPPING.get(exc_type, exc_type) - - return out_exc_type(msg) diff --git a/lib/pytz_deprecation_shim/_impl.py b/lib/pytz_deprecation_shim/_impl.py deleted file mode 100644 index 54430479..00000000 --- a/lib/pytz_deprecation_shim/_impl.py +++ /dev/null @@ -1,296 +0,0 @@ -# -*- coding: utf-8 -*- -import warnings -from datetime import tzinfo - -from . import _compat -from ._exceptions import ( - AmbiguousTimeError, - NonExistentTimeError, - PytzUsageWarning, - UnknownTimeZoneError, - get_exception, -) - -IS_DST_SENTINEL = object() -KEY_SENTINEL = object() - - -def timezone(key, _cache={}): - """Builds an IANA database time zone shim. - - This is the equivalent of ``pytz.timezone``. - - :param key: - A valid key from the IANA time zone database. - - :raises UnknownTimeZoneError: - If an unknown value is passed, this will raise an exception that can be - caught by :exc:`pytz_deprecation_shim.UnknownTimeZoneError` or - ``pytz.UnknownTimeZoneError``. Like - :exc:`zoneinfo.ZoneInfoNotFoundError`, both of those are subclasses of - :exc:`KeyError`. - """ - instance = _cache.get(key, None) - if instance is None: - if len(key) == 3 and key.lower() == "utc": - instance = _cache.setdefault(key, UTC) - else: - try: - zone = _compat.get_timezone(key) - except KeyError: - raise get_exception(UnknownTimeZoneError, key) - instance = _cache.setdefault(key, wrap_zone(zone, key=key)) - - return instance - - -def fixed_offset_timezone(offset, _cache={}): - """Builds a fixed offset time zone shim. - - This is the equivalent of ``pytz.FixedOffset``. An alias is available as - ``pytz_deprecation_shim.FixedOffset`` as well. - - :param offset: - A fixed offset from UTC, in minutes. This must be in the range ``-1439 - <= offset <= 1439``. - - :raises ValueError: - For offsets whose absolute value is greater than or equal to 24 hours. - - :return: - A shim time zone. - """ - if not (-1440 < offset < 1440): - raise ValueError("absolute offset is too large", offset) - - instance = _cache.get(offset, None) - if instance is None: - if offset == 0: - instance = _cache.setdefault(offset, UTC) - else: - zone = _compat.get_fixed_offset_zone(offset) - instance = _cache.setdefault(offset, wrap_zone(zone, key=None)) - - return instance - - -def build_tzinfo(zone, fp): - """Builds a shim object from a TZif file. - - This is a shim for ``pytz.build_tzinfo``. Given a value to use as the zone - IANA key and a file-like object containing a valid TZif file (i.e. - conforming to :rfc:`8536`), this builds a time zone object and wraps it in - a shim class. - - The argument names are chosen to match those in ``pytz.build_tzinfo``. - - :param zone: - A string to be used as the time zone object's IANA key. - - :param fp: - A readable file-like object emitting bytes, pointing to a valid TZif - file. - - :return: - A shim time zone. - """ - zone_file = _compat.get_timezone_file(fp) - - return wrap_zone(zone_file, key=zone) - - -def wrap_zone(tz, key=KEY_SENTINEL, _cache={}): - """Wrap an existing time zone object in a shim class. - - This is likely to be useful if you would like to work internally with - non-``pytz`` zones, but you expose an interface to callers relying on - ``pytz``'s interface. It may also be useful for passing non-``pytz`` zones - to libraries expecting to use ``pytz``'s interface. - - :param tz: - A :pep:`495`-compatible time zone, such as those provided by - :mod:`dateutil.tz` or :mod:`zoneinfo`. - - :param key: - The value for the IANA time zone key. This is optional for ``zoneinfo`` - zones, but required for ``dateutil.tz`` zones. - - :return: - A shim time zone. - """ - if key is KEY_SENTINEL: - key = getattr(tz, "key", KEY_SENTINEL) - - if key is KEY_SENTINEL: - raise TypeError( - "The `key` argument is required when wrapping zones that do not " - + "have a `key` attribute." - ) - - instance = _cache.get((id(tz), key), None) - if instance is None: - instance = _cache.setdefault((id(tz), key), _PytzShimTimezone(tz, key)) - - return instance - - -class _PytzShimTimezone(tzinfo): - # Add instance variables for _zone and _key because this will make error - # reporting with partially-initialized _BasePytzShimTimezone objects - # work better. - _zone = None - _key = None - - def __init__(self, zone, key): - self._key = key - self._zone = zone - - def utcoffset(self, dt): - return self._zone.utcoffset(dt) - - def dst(self, dt): - return self._zone.dst(dt) - - def tzname(self, dt): - return self._zone.tzname(dt) - - def fromutc(self, dt): - # The default fromutc implementation only works if tzinfo is "self" - dt_base = dt.replace(tzinfo=self._zone) - dt_out = self._zone.fromutc(dt_base) - - return dt_out.replace(tzinfo=self) - - def __str__(self): - if self._key is not None: - return str(self._key) - else: - return repr(self) - - def __repr__(self): - return "%s(%s, %s)" % ( - self.__class__.__name__, - repr(self._zone), - repr(self._key), - ) - - def unwrap_shim(self): - """Returns the underlying class that the shim is a wrapper for. - - This is a shim-specific method equivalent to - :func:`pytz_deprecation_shim.helpers.upgrade_tzinfo`. It is provided as - a method to allow end-users to upgrade shim timezones without requiring - an explicit dependency on ``pytz_deprecation_shim``, e.g.: - - .. code-block:: python - - if getattr(tz, "unwrap_shim", None) is None: - tz = tz.unwrap_shim() - """ - return self._zone - - @property - def zone(self): - warnings.warn( - "The zone attribute is specific to pytz's interface; " - + "please migrate to a new time zone provider. " - + "For more details on how to do so, see %s" - % PYTZ_MIGRATION_GUIDE_URL, - PytzUsageWarning, - stacklevel=2, - ) - - return self._key - - def localize(self, dt, is_dst=IS_DST_SENTINEL): - warnings.warn( - "The localize method is no longer necessary, as this " - + "time zone supports the fold attribute (PEP 495). " - + "For more details on migrating to a PEP 495-compliant " - + "implementation, see %s" % PYTZ_MIGRATION_GUIDE_URL, - PytzUsageWarning, - stacklevel=2, - ) - - if dt.tzinfo is not None: - raise ValueError("Not naive datetime (tzinfo is already set)") - - dt_out = dt.replace(tzinfo=self) - - if is_dst is IS_DST_SENTINEL: - return dt_out - - dt_ambiguous = _compat.is_ambiguous(dt_out) - dt_imaginary = ( - _compat.is_imaginary(dt_out) if not dt_ambiguous else False - ) - - if is_dst is None: - if dt_imaginary: - raise get_exception( - NonExistentTimeError, dt.replace(tzinfo=None) - ) - - if dt_ambiguous: - raise get_exception(AmbiguousTimeError, dt.replace(tzinfo=None)) - - elif dt_ambiguous or dt_imaginary: - # Start by normalizing the folds; dt_out may have fold=0 or fold=1, - # but we need to know the DST offset on both sides anyway, so we - # will get one datetime representing each side of the fold, then - # decide which one we're going to return. - if _compat.get_fold(dt_out): - dt_enfolded = dt_out - dt_out = _compat.enfold(dt_out, fold=0) - else: - dt_enfolded = _compat.enfold(dt_out, fold=1) - - # Now we want to decide whether the fold=0 or fold=1 represents - # what pytz would return for `is_dst=True` - enfolded_dst = bool(dt_enfolded.dst()) - if bool(dt_out.dst()) == enfolded_dst: - # If this is not a transition between standard time and - # daylight saving time, pytz will consider the larger offset - # the DST offset. - enfolded_dst = dt_enfolded.utcoffset() > dt_out.utcoffset() - - # The default we've established is that dt_out is fold=0; swap it - # for the fold=1 datetime if is_dst == True and the enfolded side - # is DST or if is_dst == False and the enfolded side is *not* DST. - if is_dst == enfolded_dst: - dt_out = dt_enfolded - - return dt_out - - def normalize(self, dt): - warnings.warn( - "The normalize method is no longer necessary, as this " - + "time zone supports the fold attribute (PEP 495). " - + "For more details on migrating to a PEP 495-compliant " - + "implementation, see %s" % PYTZ_MIGRATION_GUIDE_URL, - PytzUsageWarning, - stacklevel=2, - ) - - if dt.tzinfo is None: - raise ValueError("Naive time - no tzinfo set") - - if dt.tzinfo is self: - return dt - - return dt.astimezone(self) - - def __copy__(self): - return self - - def __deepcopy__(self, memo=None): - return self - - def __reduce__(self): - return wrap_zone, (self._zone, self._key) - - -UTC = wrap_zone(_compat.UTC, "UTC") -PYTZ_MIGRATION_GUIDE_URL = ( - "https://pytz-deprecation-shim.readthedocs.io/en/latest/migration.html" -) diff --git a/lib/pytz_deprecation_shim/helpers.py b/lib/pytz_deprecation_shim/helpers.py deleted file mode 100644 index 6b05b130..00000000 --- a/lib/pytz_deprecation_shim/helpers.py +++ /dev/null @@ -1,90 +0,0 @@ -""" -This module contains helper functions to ease the transition from ``pytz`` to -another :pep:`495`-compatible library. -""" -from . import _common, _compat -from ._impl import _PytzShimTimezone - -_PYTZ_BASE_CLASSES = None - - -def is_pytz_zone(tz): - """Check if a time zone is a ``pytz`` time zone. - - This will only import ``pytz`` if it has already been imported, and does - not rely on the existence of the ``localize`` or ``normalize`` methods - (since the shim classes also have these methods, but are not ``pytz`` - zones). - """ - - # If pytz is not in sys.modules, then we will assume the time zone is not a - # pytz zone. It is possible that someone has manipulated sys.modules to - # remove pytz, but that's the kind of thing that causes all kinds of other - # problems anyway, so we'll call that an unsupported configuration. - if not _common.pytz_imported(): - return False - - if _PYTZ_BASE_CLASSES is None: - _populate_pytz_base_classes() - - return isinstance(tz, _PYTZ_BASE_CLASSES) - - -def upgrade_tzinfo(tz): - """Convert a ``pytz`` or shim timezone into its modern equivalent. - - The shim classes are thin wrappers around :mod:`zoneinfo` or - :mod:`dateutil.tz` implementations of the :class:`datetime.tzinfo` base - class. This function removes the shim and returns the underlying "upgraded" - time zone. - - When passed a ``pytz`` zone (not a shim), this returns the non-``pytz`` - equivalent. This may fail if ``pytz`` is using a data source incompatible - with the upgraded provider's data source, or if the ``pytz`` zone was built - from a file rather than an IANA key. - - When passed an object that is not a shim or a ``pytz`` zone, this returns - the original object. - - :param tz: - A :class:`datetime.tzinfo` object. - - :raises KeyError: - If a ``pytz`` zone is passed to the function with no equivalent in the - :pep:`495`-compatible library's version of the Olson database. - - :return: - A :pep:`495`-compatible equivalent of any ``pytz`` or shim - class, or the original object. - """ - if isinstance(tz, _PytzShimTimezone): - return tz._zone - - if is_pytz_zone(tz): - if tz.zone is None: - # This is a fixed offset zone - offset = tz.utcoffset(None) - offset_minutes = offset.total_seconds() / 60 - - return _compat.get_fixed_offset_zone(offset_minutes) - - if tz.zone == "UTC": - return _compat.UTC - - return _compat.get_timezone(tz.zone) - - return tz - - -def _populate_pytz_base_classes(): - import pytz - from pytz.tzinfo import BaseTzInfo - - base_classes = (BaseTzInfo, pytz._FixedOffset) - - # In releases prior to 2018.4, pytz.UTC was not a subclass of BaseTzInfo - if not isinstance(pytz.UTC, BaseTzInfo): # pragma: nocover - base_classes = base_classes + (type(pytz.UTC),) - - global _PYTZ_BASE_CLASSES - _PYTZ_BASE_CLASSES = base_classes diff --git a/lib/tzdata/__init__.py b/lib/tzdata/__init__.py index 07c7b3a2..4fd76c37 100644 --- a/lib/tzdata/__init__.py +++ b/lib/tzdata/__init__.py @@ -1,6 +1,6 @@ # IANA versions like 2020a are not valid PEP 440 identifiers; the recommended # way to translate the version is to use YYYY.n where `n` is a 0-based index. -__version__ = "2021.5" +__version__ = "2021.2.post0" # This exposes the original IANA version number. -IANA_VERSION = "2021e" +IANA_VERSION = "2021b" diff --git a/lib/tzdata/zoneinfo/Asia/Gaza b/lib/tzdata/zoneinfo/Asia/Gaza index ccc57c9c..58e9fdf4 100644 Binary files a/lib/tzdata/zoneinfo/Asia/Gaza and b/lib/tzdata/zoneinfo/Asia/Gaza differ diff --git a/lib/tzdata/zoneinfo/Asia/Hebron b/lib/tzdata/zoneinfo/Asia/Hebron index 906d8d5c..aeda06b5 100644 Binary files a/lib/tzdata/zoneinfo/Asia/Hebron and b/lib/tzdata/zoneinfo/Asia/Hebron differ diff --git a/lib/tzdata/zoneinfo/Atlantic/Jan_Mayen b/lib/tzdata/zoneinfo/Atlantic/Jan_Mayen index dfc50957..465546bd 100644 Binary files a/lib/tzdata/zoneinfo/Atlantic/Jan_Mayen and b/lib/tzdata/zoneinfo/Atlantic/Jan_Mayen differ diff --git a/lib/tzdata/zoneinfo/Pacific/Fiji b/lib/tzdata/zoneinfo/Pacific/Fiji index 8b2dd52b..e3934e42 100644 Binary files a/lib/tzdata/zoneinfo/Pacific/Fiji and b/lib/tzdata/zoneinfo/Pacific/Fiji differ diff --git a/lib/tzdata/zoneinfo/tzdata.zi b/lib/tzdata/zoneinfo/tzdata.zi index 1948c725..fa3ebc23 100644 --- a/lib/tzdata/zoneinfo/tzdata.zi +++ b/lib/tzdata/zoneinfo/tzdata.zi @@ -1,4 +1,4 @@ -# version 2021e +# version 2021b # This zic input file is in the public domain. R d 1916 o - Jun 14 23s 1 S R d 1916 1919 - O Su>=1 23s 0 - @@ -43,16 +43,6 @@ Z Africa/Ndjamena 1:0:12 - LMT 1912 1 - WAT Z Africa/Abidjan -0:16:8 - LMT 1912 0 - GMT -L Africa/Abidjan Africa/Accra -L Africa/Abidjan Africa/Bamako -L Africa/Abidjan Africa/Banjul -L Africa/Abidjan Africa/Conakry -L Africa/Abidjan Africa/Dakar -L Africa/Abidjan Africa/Freetown -L Africa/Abidjan Africa/Lome -L Africa/Abidjan Africa/Nouakchott -L Africa/Abidjan Africa/Ouagadougou -L Africa/Abidjan Atlantic/St_Helena R K 1940 o - Jul 15 0 1 S R K 1940 o - O 1 0 0 - R K 1941 o - Ap 15 0 1 S @@ -96,15 +86,6 @@ Z Africa/Nairobi 2:27:16 - LMT 1908 May 2:30 - +0230 1936 D 31 24 2:45 - +0245 1942 Jul 31 24 3 - EAT -L Africa/Nairobi Africa/Addis_Ababa -L Africa/Nairobi Africa/Asmara -L Africa/Nairobi Africa/Dar_es_Salaam -L Africa/Nairobi Africa/Djibouti -L Africa/Nairobi Africa/Kampala -L Africa/Nairobi Africa/Mogadishu -L Africa/Nairobi Indian/Antananarivo -L Africa/Nairobi Indian/Comoro -L Africa/Nairobi Indian/Mayotte Z Africa/Monrovia -0:43:8 - LMT 1882 -0:43:8 - MMT 1919 Mar -0:44:30 - MMT 1972 Ja 7 @@ -335,13 +316,6 @@ Z Africa/El_Aaiun -0:52:48 - LMT 1934 1 M +01/+00 Z Africa/Maputo 2:10:20 - LMT 1903 Mar 2 - CAT -L Africa/Maputo Africa/Blantyre -L Africa/Maputo Africa/Bujumbura -L Africa/Maputo Africa/Gaborone -L Africa/Maputo Africa/Harare -L Africa/Maputo Africa/Kigali -L Africa/Maputo Africa/Lubumbashi -L Africa/Maputo Africa/Lusaka R NA 1994 o - Mar 21 0 -1 WAT R NA 1994 2017 - S Su>=1 2 0 CAT R NA 1995 2017 - Ap Su>=1 2 -1 WAT @@ -356,15 +330,6 @@ Z Africa/Lagos 0:13:35 - LMT 1905 Jul 0:13:35 - LMT 1914 0:30 - +0030 1919 S 1 - WAT -L Africa/Lagos Africa/Bangui -L Africa/Lagos Africa/Brazzaville -L Africa/Lagos Africa/Douala -L Africa/Lagos Africa/Kinshasa -L Africa/Lagos Africa/Libreville -L Africa/Lagos Africa/Luanda -L Africa/Lagos Africa/Malabo -L Africa/Lagos Africa/Niamey -L Africa/Lagos Africa/Porto-Novo Z Indian/Reunion 3:41:52 - LMT 1911 Jun 4 - +04 Z Africa/Sao_Tome 0:26:56 - LMT 1884 @@ -379,8 +344,6 @@ R SA 1943 1944 - Mar Su>=15 2 0 - Z Africa/Johannesburg 1:52 - LMT 1892 F 8 1:30 - SAST 1903 Mar 2 SA SAST -L Africa/Johannesburg Africa/Maseru -L Africa/Johannesburg Africa/Mbabane R SD 1970 o - May 1 0 1 S R SD 1970 1985 - O 15 0 0 - R SD 1971 o - Ap 30 0 1 S @@ -608,7 +571,6 @@ Z Asia/Famagusta 2:15:48 - LMT 1921 N 14 2 E EE%sT 2016 S 8 3 - +03 2017 O 29 1u 2 E EE%sT -L Asia/Nicosia Europe/Nicosia Z Asia/Tbilisi 2:59:11 - LMT 1880 2:59:11 - TBMT 1924 May 2 3 - +03 1957 Mar @@ -1112,8 +1074,7 @@ R P 2016 2018 - O Sa>=24 1 0 - R P 2019 o - Mar 29 0 1 S R P 2019 o - O Sa>=24 0 0 - R P 2020 ma - Mar Sa>=24 0 1 S -R P 2020 o - O 24 1 0 - -R P 2021 ma - O lastF 1 0 - +R P 2020 ma - O Sa>=24 1 0 - Z Asia/Gaza 2:17:52 - LMT 1900 O 2 Z EET/EEST 1948 May 15 2 K EE%sT 1967 Jun 5 @@ -1146,12 +1107,8 @@ Z Asia/Manila -15:56 - LMT 1844 D 31 Z Asia/Qatar 3:26:8 - LMT 1920 4 - +04 1972 Jun 3 - +03 -L Asia/Qatar Asia/Bahrain Z Asia/Riyadh 3:6:52 - LMT 1947 Mar 14 3 - +03 -L Asia/Riyadh Antarctica/Syowa -L Asia/Riyadh Asia/Aden -L Asia/Riyadh Asia/Kuwait Z Asia/Singapore 6:55:25 - LMT 1901 6:55:25 - SMT 1905 Jun 7 - +07 1933 @@ -1221,8 +1178,6 @@ Z Asia/Dushanbe 4:35:12 - LMT 1924 May 2 Z Asia/Bangkok 6:42:4 - LMT 1880 6:42:4 - BMT 1920 Ap 7 - +07 -L Asia/Bangkok Asia/Phnom_Penh -L Asia/Bangkok Asia/Vientiane Z Asia/Ashgabat 3:53:32 - LMT 1924 May 2 4 - +04 1930 Jun 21 5 R +05/+06 1991 Mar 31 2 @@ -1230,7 +1185,6 @@ Z Asia/Ashgabat 3:53:32 - LMT 1924 May 2 5 - +05 Z Asia/Dubai 3:41:12 - LMT 1920 4 - +04 -L Asia/Dubai Asia/Muscat Z Asia/Samarkand 4:27:53 - LMT 1924 May 2 4 - +04 1930 Jun 21 5 - +05 1981 Ap @@ -1419,11 +1373,10 @@ R FJ 2011 o - Mar Su>=1 3 0 - R FJ 2012 2013 - Ja Su>=18 3 0 - R FJ 2014 o - Ja Su>=18 2 0 - R FJ 2014 2018 - N Su>=1 2 1 - -R FJ 2015 2021 - Ja Su>=12 3 0 - +R FJ 2015 ma - Ja Su>=12 3 0 - R FJ 2019 o - N Su>=8 2 1 - R FJ 2020 o - D 20 2 1 - -R FJ 2022 ma - N Su>=8 2 1 - -R FJ 2023 ma - Ja Su>=12 3 0 - +R FJ 2021 ma - N Su>=8 2 1 - Z Pacific/Fiji 11:55:44 - LMT 1915 O 26 12 FJ +12/+13 Z Pacific/Gambier -8:59:48 - LMT 1912 O @@ -1452,7 +1405,6 @@ Z Pacific/Guam -14:21 - LMT 1844 D 31 9 - +09 1944 Jul 31 10 Gu G%sT 2000 D 23 10 - ChST -L Pacific/Guam Pacific/Saipan Z Pacific/Tarawa 11:32:4 - LMT 1901 12 - +12 Z Pacific/Kanton 0 - -00 1937 Au 31 @@ -1545,7 +1497,6 @@ Z Pacific/Auckland 11:39:4 - LMT 1868 N 2 Z Pacific/Chatham 12:13:48 - LMT 1868 N 2 12:15 - +1215 1946 12:45 k +1245/+1345 -L Pacific/Auckland Antarctica/McMurdo R CK 1978 o - N 12 0 0:30 - R CK 1979 1991 - Mar Su>=1 0 0 - R CK 1979 1990 - O lastSu 0 0:30 - @@ -1569,7 +1520,6 @@ Z Pacific/Palau -15:2:4 - LMT 1844 D 31 Z Pacific/Port_Moresby 9:48:40 - LMT 1880 9:48:32 - PMMT 1895 10 - +10 -L Pacific/Port_Moresby Antarctica/DumontDUrville Z Pacific/Bougainville 10:22:16 - LMT 1880 9:48:32 - PMMT 1895 10 - +10 1942 Jul @@ -1582,7 +1532,6 @@ Z Pacific/Pitcairn -8:40:20 - LMT 1901 Z Pacific/Pago_Pago 12:37:12 - LMT 1892 Jul 5 -11:22:48 - LMT 1911 -11 - SST -L Pacific/Pago_Pago Pacific/Midway R WS 2010 o - S lastSu 0 1 - R WS 2011 o - Ap Sa>=1 4 0 - R WS 2011 o - S lastSa 3 1 - @@ -1692,9 +1641,6 @@ Z Europe/London -0:1:15 - LMT 1847 D 1 0s 1 - BST 1971 O 31 2u 0 G %s 1996 0 E GMT/BST -L Europe/London Europe/Jersey -L Europe/London Europe/Guernsey -L Europe/London Europe/Isle_of_Man R IE 1971 o - O 31 2u -1 - R IE 1972 1980 - Mar Su>=16 2u 0 - R IE 1972 1980 - O Su>=23 2u -1 - @@ -1958,7 +1904,6 @@ Z Europe/Helsinki 1:39:49 - LMT 1878 May 31 1:39:49 - HMT 1921 May 2 FI EE%sT 1983 2 E EE%sT -L Europe/Helsinki Europe/Mariehamn R F 1916 o - Jun 14 23s 1 S R F 1916 1919 - O Su>=1 23s 0 - R F 1917 o - Mar 24 23s 1 S @@ -2024,7 +1969,6 @@ Z Europe/Berlin 0:53:28 - LMT 1893 Ap 1 So CE%sT 1946 1 DE CE%sT 1980 1 E CE%sT -L Europe/Zurich Europe/Busingen Z Europe/Gibraltar -0:21:24 - LMT 1880 Au 2 0s 0 G %s 1957 Ap 14 2 1 - CET 1982 @@ -2145,8 +2089,6 @@ Z Europe/Rome 0:49:56 - LMT 1866 D 12 1 c CE%sT 1944 Jun 4 1 I CE%sT 1980 1 E CE%sT -L Europe/Rome Europe/Vatican -L Europe/Rome Europe/San_Marino R LV 1989 1996 - Mar lastSu 2s 1 S R LV 1989 1996 - S lastSu 2s 0 - Z Europe/Riga 1:36:34 - LMT 1880 @@ -2164,7 +2106,6 @@ Z Europe/Riga 1:36:34 - LMT 1880 2 E EE%sT 2000 F 29 2 - EET 2001 Ja 2 2 E EE%sT -L Europe/Zurich Europe/Vaduz Z Europe/Vilnius 1:41:16 - LMT 1880 1:24 - WMT 1917 1:35:36 - KMT 1919 O 10 @@ -2276,7 +2217,6 @@ Z Europe/Oslo 0:43 - LMT 1895 1 c CE%sT 1945 Ap 2 2 1 NO CE%sT 1980 1 E CE%sT -L Europe/Oslo Arctic/Longyearbyen R O 1918 1919 - S 16 2s 0 - R O 1919 o - Ap 15 2s 1 S R O 1944 o - Ap 3 2s 1 S @@ -2646,12 +2586,6 @@ Z Europe/Belgrade 1:22 - LMT 1884 1 1 CEST 1945 S 16 2s 1 - CET 1982 N 27 1 E CE%sT -L Europe/Belgrade Europe/Ljubljana -L Europe/Belgrade Europe/Podgorica -L Europe/Belgrade Europe/Sarajevo -L Europe/Belgrade Europe/Skopje -L Europe/Belgrade Europe/Zagreb -L Europe/Prague Europe/Bratislava R s 1918 o - Ap 15 23 1 S R s 1918 1919 - O 6 24s 0 - R s 1919 o - Ap 6 23 1 S @@ -2779,7 +2713,6 @@ Z Europe/Istanbul 1:55:52 - LMT 1880 2 1 EEST 2015 N 8 1u 2 E EE%sT 2016 S 7 3 - +03 -L Europe/Istanbul Asia/Istanbul Z Europe/Kiev 2:2:4 - LMT 1880 2:2:4 - KMT 1924 May 2 2 - EET 1930 Jun 21 @@ -2955,7 +2888,6 @@ Z America/Phoenix -7:28:18 - LMT 1883 N 18 11:31:42 -7 - MST 1967 -7 u M%sT 1968 Mar 21 -7 - MST -L America/Phoenix America/Creston Z America/Boise -7:44:49 - LMT 1883 N 18 12:15:11 -8 u P%sT 1923 May 13 2 -7 u M%sT 1974 @@ -3254,7 +3186,6 @@ Z America/Toronto -5:17:32 - LMT 1895 -5 C E%sT 1946 -5 t E%sT 1974 -5 C E%sT -L America/Toronto America/Nassau Z America/Thunder_Bay -5:57 - LMT 1895 -6 - CST 1910 -5 - EST 1942 @@ -3705,31 +3636,10 @@ Z America/Managua -5:45:8 - LMT 1890 Z America/Panama -5:18:8 - LMT 1890 -5:19:36 - CMT 1908 Ap 22 -5 - EST -L America/Panama America/Atikokan -L America/Panama America/Cayman Z America/Puerto_Rico -4:24:25 - LMT 1899 Mar 28 12 -4 - AST 1942 May 3 -4 u A%sT 1946 -4 - AST -L America/Puerto_Rico America/Anguilla -L America/Puerto_Rico America/Antigua -L America/Puerto_Rico America/Aruba -L America/Puerto_Rico America/Curacao -L America/Puerto_Rico America/Blanc-Sablon -L America/Puerto_Rico America/Dominica -L America/Puerto_Rico America/Grenada -L America/Puerto_Rico America/Guadeloupe -L America/Puerto_Rico America/Kralendijk -L America/Puerto_Rico America/Lower_Princes -L America/Puerto_Rico America/Marigot -L America/Puerto_Rico America/Montserrat -L America/Puerto_Rico America/Port_of_Spain -L America/Puerto_Rico America/St_Barthelemy -L America/Puerto_Rico America/St_Kitts -L America/Puerto_Rico America/St_Lucia -L America/Puerto_Rico America/St_Thomas -L America/Puerto_Rico America/St_Vincent -L America/Puerto_Rico America/Tortola Z America/Miquelon -3:44:40 - LMT 1911 May 15 -4 - AST 1980 May -3 - -03 1987 @@ -4311,46 +4221,114 @@ Z Etc/GMT+10 -10 - -10 Z Etc/GMT+11 -11 - -11 Z Etc/GMT+12 -12 - -12 Z Factory 0 - -00 +L Africa/Abidjan Africa/Accra +L Africa/Nairobi Africa/Addis_Ababa +L Africa/Nairobi Africa/Asmara L Africa/Nairobi Africa/Asmera +L Africa/Abidjan Africa/Bamako +L Africa/Lagos Africa/Bangui +L Africa/Abidjan Africa/Banjul +L Africa/Maputo Africa/Blantyre +L Africa/Lagos Africa/Brazzaville +L Africa/Maputo Africa/Bujumbura +L Africa/Abidjan Africa/Conakry +L Africa/Abidjan Africa/Dakar +L Africa/Nairobi Africa/Dar_es_Salaam +L Africa/Nairobi Africa/Djibouti +L Africa/Lagos Africa/Douala +L Africa/Abidjan Africa/Freetown +L Africa/Maputo Africa/Gaborone +L Africa/Maputo Africa/Harare +L Africa/Nairobi Africa/Kampala +L Africa/Maputo Africa/Kigali +L Africa/Lagos Africa/Kinshasa +L Africa/Lagos Africa/Libreville +L Africa/Abidjan Africa/Lome +L Africa/Lagos Africa/Luanda +L Africa/Maputo Africa/Lubumbashi +L Africa/Maputo Africa/Lusaka +L Africa/Lagos Africa/Malabo +L Africa/Johannesburg Africa/Maseru +L Africa/Johannesburg Africa/Mbabane +L Africa/Nairobi Africa/Mogadishu +L Africa/Lagos Africa/Niamey +L Africa/Abidjan Africa/Nouakchott +L Africa/Abidjan Africa/Ouagadougou +L Africa/Lagos Africa/Porto-Novo L Africa/Abidjan Africa/Timbuktu +L America/Puerto_Rico America/Anguilla +L America/Puerto_Rico America/Antigua L America/Argentina/Catamarca America/Argentina/ComodRivadavia +L America/Puerto_Rico America/Aruba +L America/Panama America/Atikokan L America/Adak America/Atka +L America/Puerto_Rico America/Blanc-Sablon L America/Argentina/Buenos_Aires America/Buenos_Aires L America/Argentina/Catamarca America/Catamarca +L America/Panama America/Cayman L America/Panama America/Coral_Harbour L America/Argentina/Cordoba America/Cordoba +L America/Phoenix America/Creston +L America/Puerto_Rico America/Curacao +L America/Puerto_Rico America/Dominica L America/Tijuana America/Ensenada L America/Indiana/Indianapolis America/Fort_Wayne L America/Nuuk America/Godthab +L America/Puerto_Rico America/Grenada +L America/Puerto_Rico America/Guadeloupe L America/Indiana/Indianapolis America/Indianapolis L America/Argentina/Jujuy America/Jujuy L America/Indiana/Knox America/Knox_IN +L America/Puerto_Rico America/Kralendijk L America/Kentucky/Louisville America/Louisville +L America/Puerto_Rico America/Lower_Princes +L America/Puerto_Rico America/Marigot L America/Argentina/Mendoza America/Mendoza L America/Toronto America/Montreal +L America/Puerto_Rico America/Montserrat +L America/Toronto America/Nassau +L America/Puerto_Rico America/Port_of_Spain L America/Rio_Branco America/Porto_Acre L America/Argentina/Cordoba America/Rosario L America/Tijuana America/Santa_Isabel L America/Denver America/Shiprock +L America/Puerto_Rico America/St_Barthelemy +L America/Puerto_Rico America/St_Kitts +L America/Puerto_Rico America/St_Lucia +L America/Puerto_Rico America/St_Thomas +L America/Puerto_Rico America/St_Vincent +L America/Puerto_Rico America/Tortola L America/Puerto_Rico America/Virgin +L Pacific/Port_Moresby Antarctica/DumontDUrville +L Pacific/Auckland Antarctica/McMurdo L Pacific/Auckland Antarctica/South_Pole +L Asia/Riyadh Antarctica/Syowa +L Europe/Oslo Arctic/Longyearbyen +L Asia/Riyadh Asia/Aden L Asia/Ashgabat Asia/Ashkhabad +L Asia/Qatar Asia/Bahrain L Asia/Kolkata Asia/Calcutta L Asia/Shanghai Asia/Chongqing L Asia/Shanghai Asia/Chungking L Asia/Dhaka Asia/Dacca L Asia/Shanghai Asia/Harbin +L Europe/Istanbul Asia/Istanbul L Asia/Urumqi Asia/Kashgar L Asia/Kathmandu Asia/Katmandu +L Asia/Riyadh Asia/Kuwait L Asia/Macau Asia/Macao +L Asia/Dubai Asia/Muscat +L Asia/Bangkok Asia/Phnom_Penh L Asia/Yangon Asia/Rangoon L Asia/Ho_Chi_Minh Asia/Saigon L Asia/Jerusalem Asia/Tel_Aviv L Asia/Thimphu Asia/Thimbu L Asia/Makassar Asia/Ujung_Pandang L Asia/Ulaanbaatar Asia/Ulan_Bator +L Asia/Bangkok Asia/Vientiane L Atlantic/Faroe Atlantic/Faeroe -L Europe/Oslo Atlantic/Jan_Mayen +L Europe/Berlin Atlantic/Jan_Mayen +L Africa/Abidjan Atlantic/St_Helena L Australia/Sydney Australia/ACT L Australia/Sydney Australia/Canberra L Australia/Hobart Australia/Currie @@ -4382,7 +4360,22 @@ L Africa/Cairo Egypt L Europe/Dublin Eire L Etc/UTC Etc/UCT L Europe/London Europe/Belfast +L Europe/Prague Europe/Bratislava +L Europe/Zurich Europe/Busingen +L Europe/London Europe/Guernsey +L Europe/London Europe/Isle_of_Man +L Europe/London Europe/Jersey +L Europe/Belgrade Europe/Ljubljana +L Europe/Helsinki Europe/Mariehamn +L Asia/Nicosia Europe/Nicosia +L Europe/Belgrade Europe/Podgorica +L Europe/Rome Europe/San_Marino +L Europe/Belgrade Europe/Sarajevo +L Europe/Belgrade Europe/Skopje L Europe/Chisinau Europe/Tiraspol +L Europe/Zurich Europe/Vaduz +L Europe/Rome Europe/Vatican +L Europe/Belgrade Europe/Zagreb L Europe/London GB L Europe/London GB-Eire L Etc/GMT GMT+0 @@ -4391,6 +4384,9 @@ L Etc/GMT GMT0 L Etc/GMT Greenwich L Asia/Hong_Kong Hongkong L Atlantic/Reykjavik Iceland +L Africa/Nairobi Indian/Antananarivo +L Africa/Nairobi Indian/Comoro +L Africa/Nairobi Indian/Mayotte L Asia/Tehran Iran L Asia/Jerusalem Israel L America/Jamaica Jamaica @@ -4406,7 +4402,9 @@ L America/Denver Navajo L Asia/Shanghai PRC L Pacific/Kanton Pacific/Enderbury L Pacific/Honolulu Pacific/Johnston +L Pacific/Pago_Pago Pacific/Midway L Pacific/Pohnpei Pacific/Ponape +L Pacific/Guam Pacific/Saipan L Pacific/Pago_Pago Pacific/Samoa L Pacific/Chuuk Pacific/Truk L Pacific/Chuuk Pacific/Yap diff --git a/lib/tzdata/zones b/lib/tzdata/zones index e45aaa80..840009ba 100644 --- a/lib/tzdata/zones +++ b/lib/tzdata/zones @@ -2,58 +2,21 @@ Africa/Algiers Atlantic/Cape_Verde Africa/Ndjamena Africa/Abidjan -Africa/Accra -Africa/Bamako -Africa/Banjul -Africa/Conakry -Africa/Dakar -Africa/Freetown -Africa/Lome -Africa/Nouakchott -Africa/Ouagadougou -Atlantic/St_Helena Africa/Cairo Africa/Bissau Africa/Nairobi -Africa/Addis_Ababa -Africa/Asmara -Africa/Dar_es_Salaam -Africa/Djibouti -Africa/Kampala -Africa/Mogadishu -Indian/Antananarivo -Indian/Comoro -Indian/Mayotte Africa/Monrovia Africa/Tripoli Indian/Mauritius Africa/Casablanca Africa/El_Aaiun Africa/Maputo -Africa/Blantyre -Africa/Bujumbura -Africa/Gaborone -Africa/Harare -Africa/Kigali -Africa/Lubumbashi -Africa/Lusaka Africa/Windhoek Africa/Lagos -Africa/Bangui -Africa/Brazzaville -Africa/Douala -Africa/Kinshasa -Africa/Libreville -Africa/Luanda -Africa/Malabo -Africa/Niamey -Africa/Porto-Novo Indian/Reunion Africa/Sao_Tome Indian/Mahe Africa/Johannesburg -Africa/Maseru -Africa/Mbabane Africa/Khartoum Africa/Juba Africa/Tunis @@ -79,7 +42,6 @@ Asia/Taipei Asia/Macau Asia/Nicosia Asia/Famagusta -Europe/Nicosia Asia/Tbilisi Asia/Dili Asia/Kolkata @@ -115,21 +77,14 @@ Asia/Gaza Asia/Hebron Asia/Manila Asia/Qatar -Asia/Bahrain Asia/Riyadh -Antarctica/Syowa -Asia/Aden -Asia/Kuwait Asia/Singapore Asia/Colombo Asia/Damascus Asia/Dushanbe Asia/Bangkok -Asia/Phnom_Penh -Asia/Vientiane Asia/Ashgabat Asia/Dubai -Asia/Muscat Asia/Samarkand Asia/Tashkent Asia/Ho_Chi_Minh @@ -152,7 +107,6 @@ Pacific/Gambier Pacific/Marquesas Pacific/Tahiti Pacific/Guam -Pacific/Saipan Pacific/Tarawa Pacific/Kanton Pacific/Kiritimati @@ -165,17 +119,14 @@ Pacific/Nauru Pacific/Noumea Pacific/Auckland Pacific/Chatham -Antarctica/McMurdo Pacific/Rarotonga Pacific/Niue Pacific/Norfolk Pacific/Palau Pacific/Port_Moresby -Antarctica/DumontDUrville Pacific/Bougainville Pacific/Pitcairn Pacific/Pago_Pago -Pacific/Midway Pacific/Apia Pacific/Guadalcanal Pacific/Fakaofo @@ -185,9 +136,6 @@ Pacific/Wake Pacific/Efate Pacific/Wallis Europe/London -Europe/Jersey -Europe/Guernsey -Europe/Isle_of_Man Europe/Dublin WET CET @@ -208,19 +156,14 @@ America/Nuuk America/Thule Europe/Tallinn Europe/Helsinki -Europe/Mariehamn Europe/Paris Europe/Berlin -Europe/Busingen Europe/Gibraltar Europe/Athens Europe/Budapest Atlantic/Reykjavik Europe/Rome -Europe/Vatican -Europe/San_Marino Europe/Riga -Europe/Vaduz Europe/Vilnius Europe/Luxembourg Europe/Malta @@ -228,7 +171,6 @@ Europe/Chisinau Europe/Monaco Europe/Amsterdam Europe/Oslo -Arctic/Longyearbyen Europe/Warsaw Europe/Lisbon Atlantic/Azores @@ -262,19 +204,12 @@ Asia/Ust-Nera Asia/Kamchatka Asia/Anadyr Europe/Belgrade -Europe/Ljubljana -Europe/Podgorica -Europe/Sarajevo -Europe/Skopje -Europe/Zagreb -Europe/Bratislava Europe/Madrid Africa/Ceuta Atlantic/Canary Europe/Stockholm Europe/Zurich Europe/Istanbul -Asia/Istanbul Europe/Kiev Europe/Uzhgorod Europe/Zaporozhye @@ -301,7 +236,6 @@ America/Nome America/Adak Pacific/Honolulu America/Phoenix -America/Creston America/Boise America/Indiana/Indianapolis America/Indiana/Marengo @@ -321,7 +255,6 @@ America/Halifax America/Glace_Bay America/Moncton America/Toronto -America/Nassau America/Thunder_Bay America/Nipigon America/Rainy_River @@ -366,28 +299,7 @@ America/Jamaica America/Martinique America/Managua America/Panama -America/Atikokan -America/Cayman America/Puerto_Rico -America/Anguilla -America/Antigua -America/Aruba -America/Curacao -America/Blanc-Sablon -America/Dominica -America/Grenada -America/Guadeloupe -America/Kralendijk -America/Lower_Princes -America/Marigot -America/Montserrat -America/Port_of_Spain -America/St_Barthelemy -America/St_Kitts -America/St_Lucia -America/St_Thomas -America/St_Vincent -America/Tortola America/Miquelon America/Grand_Turk America/Argentina/Buenos_Aires @@ -471,46 +383,114 @@ Etc/GMT+10 Etc/GMT+11 Etc/GMT+12 Factory +Africa/Accra +Africa/Addis_Ababa +Africa/Asmara Africa/Asmera +Africa/Bamako +Africa/Bangui +Africa/Banjul +Africa/Blantyre +Africa/Brazzaville +Africa/Bujumbura +Africa/Conakry +Africa/Dakar +Africa/Dar_es_Salaam +Africa/Djibouti +Africa/Douala +Africa/Freetown +Africa/Gaborone +Africa/Harare +Africa/Kampala +Africa/Kigali +Africa/Kinshasa +Africa/Libreville +Africa/Lome +Africa/Luanda +Africa/Lubumbashi +Africa/Lusaka +Africa/Malabo +Africa/Maseru +Africa/Mbabane +Africa/Mogadishu +Africa/Niamey +Africa/Nouakchott +Africa/Ouagadougou +Africa/Porto-Novo Africa/Timbuktu +America/Anguilla +America/Antigua America/Argentina/ComodRivadavia +America/Aruba +America/Atikokan America/Atka +America/Blanc-Sablon America/Buenos_Aires America/Catamarca +America/Cayman America/Coral_Harbour America/Cordoba +America/Creston +America/Curacao +America/Dominica America/Ensenada America/Fort_Wayne America/Godthab +America/Grenada +America/Guadeloupe America/Indianapolis America/Jujuy America/Knox_IN +America/Kralendijk America/Louisville +America/Lower_Princes +America/Marigot America/Mendoza America/Montreal +America/Montserrat +America/Nassau +America/Port_of_Spain America/Porto_Acre America/Rosario America/Santa_Isabel America/Shiprock +America/St_Barthelemy +America/St_Kitts +America/St_Lucia +America/St_Thomas +America/St_Vincent +America/Tortola America/Virgin +Antarctica/DumontDUrville +Antarctica/McMurdo Antarctica/South_Pole +Antarctica/Syowa +Arctic/Longyearbyen +Asia/Aden Asia/Ashkhabad +Asia/Bahrain Asia/Calcutta Asia/Chongqing Asia/Chungking Asia/Dacca Asia/Harbin +Asia/Istanbul Asia/Kashgar Asia/Katmandu +Asia/Kuwait Asia/Macao +Asia/Muscat +Asia/Phnom_Penh Asia/Rangoon Asia/Saigon Asia/Tel_Aviv Asia/Thimbu Asia/Ujung_Pandang Asia/Ulan_Bator +Asia/Vientiane Atlantic/Faeroe Atlantic/Jan_Mayen +Atlantic/St_Helena Australia/ACT Australia/Canberra Australia/Currie @@ -542,7 +522,22 @@ Egypt Eire Etc/UCT Europe/Belfast +Europe/Bratislava +Europe/Busingen +Europe/Guernsey +Europe/Isle_of_Man +Europe/Jersey +Europe/Ljubljana +Europe/Mariehamn +Europe/Nicosia +Europe/Podgorica +Europe/San_Marino +Europe/Sarajevo +Europe/Skopje Europe/Tiraspol +Europe/Vaduz +Europe/Vatican +Europe/Zagreb GB GB-Eire GMT+0 @@ -551,6 +546,9 @@ GMT0 Greenwich Hongkong Iceland +Indian/Antananarivo +Indian/Comoro +Indian/Mayotte Iran Israel Jamaica @@ -566,7 +564,9 @@ Navajo PRC Pacific/Enderbury Pacific/Johnston +Pacific/Midway Pacific/Ponape +Pacific/Saipan Pacific/Samoa Pacific/Truk Pacific/Yap diff --git a/lib/tzlocal/__init__.py b/lib/tzlocal/__init__.py index 98ed04fd..c8196d66 100644 --- a/lib/tzlocal/__init__.py +++ b/lib/tzlocal/__init__.py @@ -1,13 +1,5 @@ import sys - -if sys.platform == "win32": - from tzlocal.win32 import ( - get_localzone, - get_localzone_name, - reload_localzone, - ) # pragma: no cover +if sys.platform == 'win32': + from tzlocal.win32 import get_localzone, reload_localzone else: - from tzlocal.unix import get_localzone, get_localzone_name, reload_localzone - - -__all__ = ["get_localzone", "get_localzone_name", "reload_localzone"] + from tzlocal.unix import get_localzone, reload_localzone diff --git a/lib/tzlocal/unix.py b/lib/tzlocal/unix.py index eaf96d92..8574965a 100644 --- a/lib/tzlocal/unix.py +++ b/lib/tzlocal/unix.py @@ -1,75 +1,97 @@ import os +import pytz import re -import sys import warnings -from datetime import timezone -import pytz_deprecation_shim as pds from tzlocal import utils -if sys.version_info >= (3, 9): - from zoneinfo import ZoneInfo # pragma: no cover -else: - from backports.zoneinfo import ZoneInfo # pragma: no cover - _cache_tz = None -_cache_tz_name = None -def _get_localzone_name(_root="/"): +def _tz_from_env(tzenv): + if tzenv[0] == ':': + tzenv = tzenv[1:] + + # TZ specifies a file + if os.path.isabs(tzenv) and os.path.exists(tzenv): + with open(tzenv, 'rb') as tzfile: + return pytz.tzfile.build_tzinfo('local', tzfile) + + # TZ specifies a zoneinfo zone. + try: + tz = pytz.timezone(tzenv) + # That worked, so we return this: + return tz + except pytz.UnknownTimeZoneError: + raise pytz.UnknownTimeZoneError( + "tzlocal() does not support non-zoneinfo timezones like %s. \n" + "Please use a timezone in the form of Continent/City") + + +def _try_tz_from_env(): + tzenv = os.environ.get('TZ') + if tzenv: + try: + return _tz_from_env(tzenv) + except pytz.UnknownTimeZoneError: + pass + + +def _get_localzone(_root='/'): """Tries to find the local timezone configuration. - This method finds the timezone name, if it can, or it returns None. + This method prefers finding the timezone name and passing that to pytz, + over passing in the localtime file, as in the later case the zoneinfo + name is unknown. The parameter _root makes the function look for files like /etc/localtime beneath the _root directory. This is primarily used by the tests. In normal usage you call the function without parameters.""" - # First try the ENV setting. - tzenv = utils._tz_name_from_env() + tzenv = _try_tz_from_env() if tzenv: return tzenv # Are we under Termux on Android? - if os.path.exists(os.path.join(_root, "system/bin/getprop")): + if os.path.exists('/system/bin/getprop'): import subprocess - - androidtz = ( - subprocess.check_output(["getprop", "persist.sys.timezone"]) - .strip() - .decode() - ) - return androidtz + androidtz = subprocess.check_output(['getprop', 'persist.sys.timezone']).strip().decode() + return pytz.timezone(androidtz) # Now look for distribution specific configuration files # that contain the timezone name. - - # Stick all of them in a dict, to compare later. - found_configs = {} - - for configfile in ("etc/timezone", "var/db/zoneinfo"): + for configfile in ('etc/timezone', 'var/db/zoneinfo'): tzpath = os.path.join(_root, configfile) try: - with open(tzpath, "rt") as tzfile: + with open(tzpath, 'rb') as tzfile: data = tzfile.read() - etctz = data.strip('/ \t\r\n') + # Issue #3 was that /etc/timezone was a zoneinfo file. + # That's a misconfiguration, but we need to handle it gracefully: + if data[:5] == b'TZif2': + continue + + etctz = data.strip().decode() if not etctz: # Empty file, skip continue - for etctz in etctz.splitlines(): + for etctz in data.decode().splitlines(): # Get rid of host definitions and comments: - if " " in etctz: - etctz, dummy = etctz.split(" ", 1) - if "#" in etctz: - etctz, dummy = etctz.split("#", 1) + if ' ' in etctz: + etctz, dummy = etctz.split(' ', 1) + if '#' in etctz: + etctz, dummy = etctz.split('#', 1) if not etctz: continue + tz = pytz.timezone(etctz.replace(' ', '_')) + if _root == '/': + # We are using a file in etc to name the timezone. + # Verify that the timezone specified there is actually used: + utils.assert_tz_offset(tz) + return tz - found_configs[tzpath] = etctz.replace(" ", "_") - - except (IOError, UnicodeDecodeError): - # File doesn't exist or is a directory, or it's a binary file. + except IOError: + # File doesn't exist or is a directory continue # CentOS has a ZONE setting in /etc/sysconfig/clock, @@ -77,14 +99,14 @@ def _get_localzone_name(_root="/"): # Gentoo has a TIMEZONE setting in /etc/conf.d/clock # We look through these files for a timezone: - zone_re = re.compile(r"\s*ZONE\s*=\s*\"") - timezone_re = re.compile(r"\s*TIMEZONE\s*=\s*\"") - end_re = re.compile('"') + zone_re = re.compile(r'\s*ZONE\s*=\s*\"') + timezone_re = re.compile(r'\s*TIMEZONE\s*=\s*\"') + end_re = re.compile('\"') - for filename in ("etc/sysconfig/clock", "etc/conf.d/clock"): + for filename in ('etc/sysconfig/clock', 'etc/conf.d/clock'): tzpath = os.path.join(_root, filename) try: - with open(tzpath, "rt") as tzfile: + with open(tzpath, 'rt') as tzfile: data = tzfile.readlines() for line in data: @@ -96,108 +118,48 @@ def _get_localzone_name(_root="/"): if match is not None: # Some setting existed line = line[match.end():] - etctz = line[: end_re.search(line).start()] + etctz = line[:end_re.search(line).start()] # We found a timezone - found_configs[tzpath] = etctz.replace(" ", "_") + tz = pytz.timezone(etctz.replace(' ', '_')) + if _root == '/': + # We are using a file in etc to name the timezone. + # Verify that the timezone specified there is actually used: + utils.assert_tz_offset(tz) + return tz - except (IOError, UnicodeDecodeError): - # UnicodeDecode handles when clock is symlink to /etc/localtime + except IOError: + # File doesn't exist or is a directory continue # systemd distributions use symlinks that include the zone name, # see manpage of localtime(5) and timedatectl(1) - tzpath = os.path.join(_root, "etc/localtime") + tzpath = os.path.join(_root, 'etc/localtime') if os.path.exists(tzpath) and os.path.islink(tzpath): - etctz = realtzpath = os.path.realpath(tzpath) - start = etctz.find("/") + 1 + tzpath = os.path.realpath(tzpath) + start = tzpath.find("/")+1 while start != 0: - etctz = etctz[start:] + tzpath = tzpath[start:] try: - pds.timezone(etctz) - tzinfo = f"{tzpath} is a symlink to" - found_configs[tzinfo] = etctz.replace(" ", "_") - except pds.UnknownTimeZoneError: + return pytz.timezone(tzpath) + except pytz.UnknownTimeZoneError: pass - start = etctz.find("/") + 1 + start = tzpath.find("/")+1 - if len(found_configs) > 0: - # We found some explicit config of some sort! - if len(found_configs) > 1: - # Uh-oh, multiple configs. See if they match: - unique_tzs = set() - zoneinfo = os.path.join(_root, "usr", "share", "zoneinfo") - directory_depth = len(zoneinfo.split(os.path.sep)) + # No explicit setting existed. Use localtime + for filename in ('etc/localtime', 'usr/local/etc/localtime'): + tzpath = os.path.join(_root, filename) - for tzname in found_configs.values(): - # Look them up in /usr/share/zoneinfo, and find what they - # really point to: - path = os.path.realpath(os.path.join(zoneinfo, *tzname.split("/"))) - real_zone_name = "/".join(path.split(os.path.sep)[directory_depth:]) - unique_tzs.add(real_zone_name) - - if len(unique_tzs) != 1: - message = "Multiple conflicting time zone configurations found:\n" - for key, value in found_configs.items(): - message += f"{key}: {value}\n" - message += "Fix the configuration, or set the time zone in a TZ environment variable.\n" - raise utils.ZoneInfoNotFoundError(message) - - # We found exactly one config! Use it. - return list(found_configs.values())[0] - - -def _get_localzone(_root="/"): - """Creates a timezone object from the timezone name. - - If there is no timezone config, it will try to create a file from the - localtime timezone, and if there isn't one, it will default to UTC. - - The parameter _root makes the function look for files like /etc/localtime - beneath the _root directory. This is primarily used by the tests. - In normal usage you call the function without parameters.""" - - # First try the ENV setting. - tzenv = utils._tz_from_env() - if tzenv: - return tzenv - - tzname = _get_localzone_name(_root) - if tzname is None: - # No explicit setting existed. Use localtime - for filename in ("etc/localtime", "usr/local/etc/localtime"): - tzpath = os.path.join(_root, filename) - - if not os.path.exists(tzpath): - continue - with open(tzpath, "rb") as tzfile: - tz = pds.wrap_zone(ZoneInfo.from_file(tzfile, key="local")) - break - else: - warnings.warn("Can not find any timezone configuration, defaulting to UTC.") - tz = timezone.utc - else: - tz = pds.timezone(tzname) - - if _root == "/": - # We are using a file in etc to name the timezone. - # Verify that the timezone specified there is actually used: - utils.assert_tz_offset(tz) - return tz - - -def get_localzone_name(): - """Get the computers configured local timezone name, if any.""" - global _cache_tz_name - if _cache_tz_name is None: - _cache_tz_name = _get_localzone_name() - - return _cache_tz_name + if not os.path.exists(tzpath): + continue + with open(tzpath, 'rb') as tzfile: + return pytz.tzfile.build_tzinfo('local', tzfile) + warnings.warn('Can not find any timezone configuration, defaulting to UTC.') + return pytz.utc def get_localzone(): """Get the computers configured local timezone, if any.""" - global _cache_tz if _cache_tz is None: _cache_tz = _get_localzone() @@ -207,9 +169,6 @@ def get_localzone(): def reload_localzone(): """Reload the cached localzone. You need to call this if the timezone has changed.""" - global _cache_tz_name global _cache_tz - _cache_tz_name = _get_localzone_name() _cache_tz = _get_localzone() - return _cache_tz diff --git a/lib/tzlocal/utils.py b/lib/tzlocal/utils.py index d3f92420..5a677990 100644 --- a/lib/tzlocal/utils.py +++ b/lib/tzlocal/utils.py @@ -1,24 +1,7 @@ # -*- coding: utf-8 -*- -import os import time import datetime import calendar -import pytz_deprecation_shim as pds - -try: - import zoneinfo # pragma: no cover -except ImportError: - from backports import zoneinfo # pragma: no cover - -from tzlocal import windows_tz - - -class ZoneInfoNotFoundError(pds.UnknownTimeZoneError, zoneinfo.ZoneInfoNotFoundError): - """An exception derived from both pytz and zoneinfo - - This exception will be trappable both by pytz expecting clients and - zoneinfo expecting clients. - """ def get_system_offset(): @@ -38,9 +21,9 @@ def get_system_offset(): # so we check that the difference is less than one minute, because nobody # has that small DST differences. if abs(offset - time.altzone) < 60: - return -time.altzone # pragma: no cover + return -time.altzone else: - return -time.timezone # pragma: no cover + return -time.timezone def get_tz_offset(tz): @@ -56,70 +39,8 @@ def assert_tz_offset(tz): tz_offset = get_tz_offset(tz) system_offset = get_system_offset() if tz_offset != system_offset: - msg = ( - "Timezone offset does not match system offset: {} != {}. " - "Please, check your config files." - ).format(tz_offset, system_offset) + msg = ('Timezone offset does not match system offset: {0} != {1}. ' + 'Please, check your config files.').format( + tz_offset, system_offset + ) raise ValueError(msg) - - -def _tz_name_from_env(tzenv=None): - if tzenv is None: - tzenv = os.environ.get("TZ") - - if not tzenv: - return None - - if tzenv in windows_tz.tz_win: - # Yup, it's a timezone - return tzenv - - if os.path.isabs(tzenv) and os.path.exists(tzenv): - # It's a file specification - parts = tzenv.split(os.sep) - - # Is it a zone info zone? - possible_tz = "/".join(parts[-2:]) - if possible_tz in windows_tz.tz_win: - # Yup, it is - return possible_tz - - # Maybe it's a short one, like UTC? - if parts[-1] in windows_tz.tz_win: - # Indeed - return parts[-1] - - -def _tz_from_env(tzenv=None): - if tzenv is None: - tzenv = os.environ.get("TZ") - - if not tzenv: - return None - - # Some weird format that exists: - if tzenv[0] == ":": - tzenv = tzenv[1:] - - # TZ specifies a file - if os.path.isabs(tzenv) and os.path.exists(tzenv): - # Try to see if we can figure out the name - tzname = _tz_name_from_env(tzenv) - if not tzname: - # Nope, not a standard timezone name, just take the filename - tzname = tzenv.split(os.sep)[-1] - with open(tzenv, "rb") as tzfile: - zone = zoneinfo.ZoneInfo.from_file(tzfile, key=tzname) - return pds.wrap_zone(zone) - - # TZ must specify a zoneinfo zone. - try: - tz = pds.timezone(tzenv) - # That worked, so we return this: - return tz - except pds.UnknownTimeZoneError: - # Nope, it's something like "PST4DST" etc, we can't handle that. - raise ZoneInfoNotFoundError( - "tzlocal() does not support non-zoneinfo timezones like %s. \n" - "Please use a timezone in the form of Continent/City" - ) from None diff --git a/lib/tzlocal/win32.py b/lib/tzlocal/win32.py index 720ab2b7..fcc42a23 100644 --- a/lib/tzlocal/win32.py +++ b/lib/tzlocal/win32.py @@ -1,53 +1,32 @@ -from datetime import datetime -import pytz_deprecation_shim as pds - try: import _winreg as winreg except ImportError: import winreg +import pytz + from tzlocal.windows_tz import win_tz from tzlocal import utils _cache_tz = None -_cache_tz_name = None def valuestodict(key): """Convert a registry key's values to a dictionary.""" - result = {} + dict = {} size = winreg.QueryInfoKey(key)[1] for i in range(size): data = winreg.EnumValue(key, i) - result[data[0]] = data[1] - return result + dict[data[0]] = data[1] + return dict -def _get_dst_info(tz): - # Find the offset for when it doesn't have DST: - dst_offset = std_offset = None - has_dst = False - year = datetime.now().year - for dt in (datetime(year, 1, 1), datetime(year, 6, 1)): - if tz.dst(dt).total_seconds() == 0.0: - # OK, no DST during winter, get this offset - std_offset = tz.utcoffset(dt).total_seconds() - else: - has_dst = True - - return has_dst, std_offset, dst_offset - - -def _get_localzone_name(): +def get_localzone_name(): # Windows is special. It has unique time zone names (in several # meanings of the word) available, but unfortunately, they can be # translated to the language of the operating system, so we need to # do a backwards lookup, by going through all time zones and see which # one matches. - tzenv = utils._tz_name_from_env() - if tzenv: - return tzenv - handle = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) TZLOCALKEYNAME = r"SYSTEM\CurrentControlSet\Control\TimeZoneInformation" @@ -55,16 +34,44 @@ def _get_localzone_name(): keyvalues = valuestodict(localtz) localtz.Close() - if "TimeZoneKeyName" in keyvalues: - # Windows 7 and later + if 'TimeZoneKeyName' in keyvalues: + # Windows 7 (and Vista?) # For some reason this returns a string with loads of NUL bytes at # least on some systems. I don't know if this is a bug somewhere, I # just work around it. - tzkeyname = keyvalues["TimeZoneKeyName"].split("\x00", 1)[0] + tzkeyname = keyvalues['TimeZoneKeyName'].split('\x00', 1)[0] else: - # Don't support XP any longer - raise LookupError("Can not find Windows timezone configuration") + # Windows 2000 or XP + + # This is the localized name: + tzwin = keyvalues['StandardName'] + + # Open the list of timezones to look up the real name: + TZKEYNAME = r"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones" + tzkey = winreg.OpenKey(handle, TZKEYNAME) + + # Now, match this value to Time Zone information + tzkeyname = None + for i in range(winreg.QueryInfoKey(tzkey)[0]): + subkey = winreg.EnumKey(tzkey, i) + sub = winreg.OpenKey(tzkey, subkey) + data = valuestodict(sub) + sub.Close() + try: + if data['Std'] == tzwin: + tzkeyname = subkey + break + except KeyError: + # This timezone didn't have proper configuration. + # Ignore it. + pass + + tzkey.Close() + handle.Close() + + if tzkeyname is None: + raise LookupError('Can not find Windows timezone configuration') timezone = win_tz.get(tzkeyname) if timezone is None: @@ -74,64 +81,24 @@ def _get_localzone_name(): # Return what we have. if timezone is None: - raise utils.ZoneInfoNotFoundError(tzkeyname) - - if keyvalues.get("DynamicDaylightTimeDisabled", 0) == 1: - # DST is disabled, so don't return the timezone name, - # instead return Etc/GMT+offset - - tz = pds.timezone(timezone) - has_dst, std_offset, dst_offset = _get_dst_info(tz) - if not has_dst: - # The DST is turned off in the windows configuration, - # but this timezone doesn't have DST so it doesn't matter - return timezone - - if std_offset is None: - raise utils.ZoneInfoNotFoundError( - f"{tzkeyname} claims to not have a non-DST time!?") - - if std_offset % 3600: - # I can't convert this to an hourly offset - raise utils.ZoneInfoNotFoundError( - f"tzlocal can't support disabling DST in the {timezone} zone.") - - # This has whole hours as offset, return it as Etc/GMT - return f"Etc/GMT{-std_offset//3600:+.0f}" + raise pytz.UnknownTimeZoneError('Can not find timezone ' + tzkeyname) return timezone -def get_localzone_name(): - """Get the zoneinfo timezone name that matches the Windows-configured timezone.""" - global _cache_tz_name - if _cache_tz_name is None: - _cache_tz_name = _get_localzone_name() - - return _cache_tz_name - - def get_localzone(): """Returns the zoneinfo-based tzinfo object that matches the Windows-configured timezone.""" - global _cache_tz if _cache_tz is None: - _cache_tz = pds.timezone(get_localzone_name()) - - if not utils._tz_name_from_env(): - # If the timezone does NOT come from a TZ environment variable, - # verify that it's correct. If it's from the environment, - # we accept it, this is so you can run tests with different timezones. - utils.assert_tz_offset(_cache_tz) + _cache_tz = pytz.timezone(get_localzone_name()) + utils.assert_tz_offset(_cache_tz) return _cache_tz def reload_localzone(): """Reload the cached localzone. You need to call this if the timezone has changed.""" global _cache_tz - global _cache_tz_name - _cache_tz_name = _get_localzone_name() - _cache_tz = pds.timezone(_cache_tz_name) + _cache_tz = pytz.timezone(get_localzone_name()) utils.assert_tz_offset(_cache_tz) return _cache_tz diff --git a/lib/tzlocal/windows_tz.py b/lib/tzlocal/windows_tz.py index 0d285037..86ba807d 100644 --- a/lib/tzlocal/windows_tz.py +++ b/lib/tzlocal/windows_tz.py @@ -104,7 +104,6 @@ win_tz = {'AUS Central Standard Time': 'Australia/Darwin', 'Saratov Standard Time': 'Europe/Saratov', 'Singapore Standard Time': 'Asia/Singapore', 'South Africa Standard Time': 'Africa/Johannesburg', - 'South Sudan Standard Time': 'Africa/Juba', 'Sri Lanka Standard Time': 'Asia/Colombo', 'Sudan Standard Time': 'Africa/Khartoum', 'Syria Standard Time': 'Asia/Damascus', @@ -119,7 +118,7 @@ win_tz = {'AUS Central Standard Time': 'Australia/Darwin', 'Turks And Caicos Standard Time': 'America/Grand_Turk', 'US Eastern Standard Time': 'America/Indianapolis', 'US Mountain Standard Time': 'America/Phoenix', - 'UTC': 'Etc/UTC', + 'UTC': 'Etc/GMT', 'UTC+12': 'Etc/GMT-12', 'UTC+13': 'Etc/GMT-13', 'UTC-02': 'Etc/GMT+2', @@ -137,8 +136,7 @@ win_tz = {'AUS Central Standard Time': 'Australia/Darwin', 'West Asia Standard Time': 'Asia/Tashkent', 'West Bank Standard Time': 'Asia/Hebron', 'West Pacific Standard Time': 'Pacific/Port_Moresby', - 'Yakutsk Standard Time': 'Asia/Yakutsk', - 'Yukon Standard Time': 'America/Whitehorse'} + 'Yakutsk Standard Time': 'Asia/Yakutsk'} # Old name for the win_tz variable: tz_names = win_tz @@ -168,7 +166,7 @@ tz_win = {'Africa/Abidjan': 'Greenwich Standard Time', 'Africa/Gaborone': 'South Africa Standard Time', 'Africa/Harare': 'South Africa Standard Time', 'Africa/Johannesburg': 'South Africa Standard Time', - 'Africa/Juba': 'South Sudan Standard Time', + 'Africa/Juba': 'E. Africa Standard Time', 'Africa/Kampala': 'E. Africa Standard Time', 'Africa/Khartoum': 'Sudan Standard Time', 'Africa/Kigali': 'South Africa Standard Time', @@ -236,8 +234,8 @@ tz_win = {'Africa/Abidjan': 'Greenwich Standard Time', 'America/Creston': 'US Mountain Standard Time', 'America/Cuiaba': 'Central Brazilian Standard Time', 'America/Curacao': 'SA Western Standard Time', - 'America/Danmarkshavn': 'Greenwich Standard Time', - 'America/Dawson': 'Yukon Standard Time', + 'America/Danmarkshavn': 'UTC', + 'America/Dawson': 'Pacific Standard Time', 'America/Dawson_Creek': 'US Mountain Standard Time', 'America/Denver': 'Mountain Standard Time', 'America/Detroit': 'Eastern Standard Time', @@ -347,14 +345,14 @@ tz_win = {'Africa/Abidjan': 'Greenwich Standard Time', 'America/Tortola': 'SA Western Standard Time', 'America/Vancouver': 'Pacific Standard Time', 'America/Virgin': 'SA Western Standard Time', - 'America/Whitehorse': 'Yukon Standard Time', + 'America/Whitehorse': 'Pacific Standard Time', 'America/Winnipeg': 'Central Standard Time', 'America/Yakutat': 'Alaskan Standard Time', 'America/Yellowknife': 'Mountain Standard Time', - 'Antarctica/Casey': 'Central Pacific Standard Time', + 'Antarctica/Casey': 'Singapore Standard Time', 'Antarctica/Davis': 'SE Asia Standard Time', 'Antarctica/DumontDUrville': 'West Pacific Standard Time', - 'Antarctica/Macquarie': 'Tasmania Standard Time', + 'Antarctica/Macquarie': 'Central Pacific Standard Time', 'Antarctica/Mawson': 'West Asia Standard Time', 'Antarctica/McMurdo': 'New Zealand Standard Time', 'Antarctica/Palmer': 'SA Eastern Standard Time', @@ -503,7 +501,7 @@ tz_win = {'Africa/Abidjan': 'Greenwich Standard Time', 'Canada/Newfoundland': 'Newfoundland Standard Time', 'Canada/Pacific': 'Pacific Standard Time', 'Canada/Saskatchewan': 'Canada Central Standard Time', - 'Canada/Yukon': 'Yukon Standard Time', + 'Canada/Yukon': 'Pacific Standard Time', 'Chile/Continental': 'Pacific SA Standard Time', 'Chile/EasterIsland': 'Easter Island Standard Time', 'Cuba': 'Cuba Standard Time',