pax_global_header00006660000000000000000000000064136551730110014514gustar00rootroot0000000000000052 comment=e780424e8b4dd2054d5d483f5f5b85dd45b53e39 tzlocal-2.1/000077500000000000000000000000001365517301100130265ustar00rootroot00000000000000tzlocal-2.1/.gitignore000066400000000000000000000000431365517301100150130ustar00rootroot00000000000000*.pyc *.wpr *.wpu *.egg-info *.egg tzlocal-2.1/.travis.yml000066400000000000000000000002531365517301100151370ustar00rootroot00000000000000os: - linux language: python python: - "2.7" - "3.6" - "3.7" - "3.8" - "nightly" # command to run tests install: # Nothing needed script: python setup.py test tzlocal-2.1/CHANGES.txt000066400000000000000000000104721365517301100146430ustar00rootroot00000000000000Changes ======= 2.1 (2020-05-08) ---------------- - No changes. 2.1b1 (2020-02-08) ------------------ - The is_dst flag is wrong for Europe/Dublin on some Unix releases. I changed to another way of determining if DST is in effect or not. - Added support for Python 3.7 and 3.8. Dropped 3.5 although it still works. 2.0.0 (2019-07-23) ------------------ - No differences since 2.0.0b3 Major differences since 1.5.1 ............................. - When no time zone configuration can be find, tzlocal now return UTC. This is a major difference from 1.x, where an exception would be raised. This change is because Docker images often have no configuration at all, and the unix utilities will then default to UTC, so we follow that. - If tzlocal on Unix finds a timezone name in a /etc config file, then tzlocal now verifies that the timezone it fouds has the same offset as the local computer is configured with. If it doesn't, something is configured incorrectly. (Victor Torres, regebro) - Get timezone via Termux `getprop` wrapper on Android. It's not officially supported because we can't test it, but at least we make an effort. (Jean Jordaan) Minor differences and bug fixes ............................... - Skip comment lines when parsing /etc/timezone. (Edward Betts) - Don't load timezone from current directory. (Gabriel Corona) - Now verifies that the config files actually contain something before reading them. (Zackary Welch, regebro) - Got rid of a BytesWarning (Mickaël Schoentgen) - Now handles if config file paths exists, but are directories. - Moved tests out from distributions - Support wheels 1.5.1 (2017-12-01) ------------------ - 1.5 had a bug that slipped through testing, fixed that, increased test coverage. 1.5 (2017-11-30) ---------------- - No longer treats macOS as special, but as a unix. - get_windows_info.py is renamed to update_windows_mappings.py - Windows mappings now also contain mappings from deprecated zoneinfo names. (Preston-Landers, regebro) 1.4 (2017-04-18) ---------------- - I use MIT on my other projects, so relicensing. 1.4b1 (2017-04-14) ------------------ - Dropping support for Python versions nobody uses (2.5, 3.1, 3.2), adding 3.6 Python 3.1 and 3.2 still works, 2.5 has been broken for some time. - Ayalash's OS X fix didn't work on Python 2.7, fixed that. 1.3.2 (2017-04-12) ------------------ - Ensure closing of subprocess on OS X (ayalash) - Removed unused imports (jwilk) - Closes stdout and stderr to get rid of ResourceWarnings (johnwquarles) - Updated Windows timezones (axil) 1.3 (2016-10-15) ---------------- - #34: Added support for /var/db/zoneinfo 1.2.2 (2016-03-02) ------------------ - #30: Fixed a bug on OS X. 1.2.1 (2016-02-28) ------------------ - Tests failed if TZ was set in the environment. (EdwardBetts) - Replaces os.popen() with subprocess.Popen() for OS X to handle when systemsetup doesn't exist. (mckabi, cewing) 1.2 (2015-06-14) ---------------- - Systemd stores no time zone name, forcing us to look at the name of the file that localtime symlinks to. (cameris) 1.1.2 (2014-10-18) ------------------ - Timezones that has 3 items did not work on Mac OS X. (Marc Van Olmen) - Now doesn't fail if the TZ environment variable isn't an Olsen time zone. - Some timezones on Windows can apparently be empty (perhaps the are deleted). Now these are ignored. (Xiaokun Zhu) 1.1.1 (2014-01-29) ------------------ - I forgot to add Etc/UTC as an alias for Etc/GMT. 1.1 (2014-01-28) ---------------- - Adding better support for OS X. - Added support to map from tzdata/Olsen names to Windows names. (Thanks to Benjamen Meyer). 1.0 (2013-05-29) ---------------- - Fixed some more cases where spaces needs replacing with underscores. - Better handling of misconfigured /etc/timezone. - Better error message on Windows if we can't find a timezone at all. 0.3 (2012-09-13) ---------------- - Windows 7 support. - Python 2.5 supported; because it only needed a __future__ import. - Python 3.3 tested, it worked. - Got rid of relative imports, because I don't actually like them, so I don't know why I used them in the first place. - For each Windows zone, use the default zoneinfo zone, not the last one. 0.2 (2012-09-12) ---------------- - Python 3 support. 0.1 (2012-09-11) ---------------- - Initial release. tzlocal-2.1/LICENSE.txt000066400000000000000000000020441365517301100146510ustar00rootroot00000000000000Copyright 2011-2017 Lennart Regebro Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. tzlocal-2.1/MANIFEST.in000066400000000000000000000001401365517301100145570ustar00rootroot00000000000000include *.py include *.rst include *.txt recursive-include tests/test_data * include tests/*.py tzlocal-2.1/README.rst000066400000000000000000000057461365517301100145310ustar00rootroot00000000000000tzlocal ======= This Python module returns a ``tzinfo`` object with the local timezone information under Unix and Win-32. It requires ``pytz``, and returns ``pytz`` ``tzinfo`` objects. This module attempts to fix a glaring hole in ``pytz``, that there is no way to get the local timezone information, unless you know the zoneinfo name, and under several Linux distros that's hard or impossible to figure out. Also, with Windows different timezone system using pytz isn't of much use unless you separately configure the zoneinfo timezone name. With ``tzlocal`` you only need to call ``get_localzone()`` and you will get a ``tzinfo`` object with the local time zone info. On some Unices you will still not get to know what the timezone name is, but you don't need that when you have the tzinfo file. However, if the timezone name is readily available it will be used. Supported systems ----------------- These are the systems that are in theory supported: * Windows 2000 and later * Any unix-like system with a ``/etc/localtime`` or ``/usr/local/etc/localtime`` If you have one of the above systems and it does not work, it's a bug. Please report it. Please note that if you getting a time zone called ``local``, this is not a bug, it's actually the main feature of ``tzlocal``, that even if your system does NOT have a configuration file with the zoneinfo name of your time zone, it will still work. You can also use ``tzlocal`` to get the name of your local timezone, but only if your system is configured to make that possible. ``tzlocal`` looks for the timezone name in ``/etc/timezone``, ``/var/db/zoneinfo``, ``/etc/sysconfig/clock`` and ``/etc/conf.d/clock``. If your ``/etc/localtime`` is a symlink it can also extract the name from that symlink. If you need the name of your local time zone, then please make sure your system is properly configured to allow that. If it isn't configured, tzlocal will default to UTC. Usage ----- Load the local timezone: >>> from tzlocal import get_localzone >>> tz = get_localzone() >>> tz Create a local datetime: >>> from datetime import datetime >>> dt = tz.localize(datetime(2015, 4, 10, 7, 22)) >>> dt datetime.datetime(2015, 4, 10, 7, 22, tzinfo=) Lookup another timezone with `pytz`: >>> import pytz >>> eastern = pytz.timezone('US/Eastern') Convert the datetime: >>> dt.astimezone(eastern) datetime.datetime(2015, 4, 10, 1, 22, tzinfo=) Maintainer ---------- * Lennart Regebro, regebro@gmail.com Contributors ------------ * Marc Van Olmen * Benjamen Meyer * Manuel Ebert * Xiaokun Zhu * Cameris * Edward Betts * McK KIM * Cris Ewing * Ayala Shachar * Lev Maximov * Jakub Wilk * John Quarles * Preston Landers * Victor Torres * Jean Jordaan * Zackary Welch * Mickaël Schoentgen * Gabriel Corona (Sorry if I forgot someone) License ------- * MIT https://opensource.org/licenses/MIT tzlocal-2.1/setup.cfg000066400000000000000000000000761365517301100146520ustar00rootroot00000000000000[check-manifest] ignore=spiny.conf [bdist_wheel] universal=1 tzlocal-2.1/setup.py000066400000000000000000000026761365517301100145530ustar00rootroot00000000000000from setuptools import setup, find_packages from io import open version = '2.1' with open("README.rst", 'rt', encoding='UTF-8') as file: long_description = file.read() + '\n\n' with open("CHANGES.txt", 'rt', encoding='UTF-8') as file: long_description += file.read() setup(name='tzlocal', version=version, description="tzinfo object for the local timezone", long_description=long_description, classifiers=[ 'Development Status :: 5 - Production/Stable', 'License :: OSI Approved :: MIT License', 'Operating System :: Microsoft :: Windows', 'Operating System :: Unix', 'Operating System :: MacOS :: MacOS X', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.6', 'Programming Language :: Python :: 3.7', 'Programming Language :: Python :: 3.8', ], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers keywords='timezone pytz', author='Lennart Regebro', author_email='regebro@gmail.com', url='https://github.com/regebro/tzlocal', license="MIT", packages=find_packages(exclude=['ez_setup', 'examples', 'tests']), include_package_data=True, zip_safe=True, install_requires=[ 'pytz', ], tests_require=[ 'mock', ], test_suite='tests', ) tzlocal-2.1/spiny.conf000066400000000000000000000002511365517301100150350ustar00rootroot00000000000000[spiny] environments=python2.5 python2.6 python2.7 python3.1 python3.2 python3.3 python3.4 tzlocal-2.1/tests/000077500000000000000000000000001365517301100141705ustar00rootroot00000000000000tzlocal-2.1/tests/__init__.py000066400000000000000000000000001365517301100162670ustar00rootroot00000000000000tzlocal-2.1/tests/test_data/000077500000000000000000000000001365517301100161405ustar00rootroot00000000000000tzlocal-2.1/tests/test_data/Harare000066400000000000000000000002351365517301100172650ustar00rootroot00000000000000TZif2‚FÇd LMTCATTZif2ÿÿÿÿ‚FÇd LMTCAT CAT-2 tzlocal-2.1/tests/test_data/localtime/000077500000000000000000000000001365517301100201115ustar00rootroot00000000000000tzlocal-2.1/tests/test_data/localtime/etc/000077500000000000000000000000001365517301100206645ustar00rootroot00000000000000tzlocal-2.1/tests/test_data/localtime/etc/localtime000066400000000000000000000002351365517301100225600ustar00rootroot00000000000000TZif2‚FÇd LMTCATTZif2ÿÿÿÿ‚FÇd LMTCAT CAT-2 tzlocal-2.1/tests/test_data/symlink_localtime/000077500000000000000000000000001365517301100216575ustar00rootroot00000000000000tzlocal-2.1/tests/test_data/symlink_localtime/etc/000077500000000000000000000000001365517301100224325ustar00rootroot00000000000000tzlocal-2.1/tests/test_data/symlink_localtime/etc/localtime000077700000000000000000000000001365517301100326102../usr/share/zoneinfo/Africa/Harareustar00rootroot00000000000000tzlocal-2.1/tests/test_data/symlink_localtime/usr/000077500000000000000000000000001365517301100224705ustar00rootroot00000000000000tzlocal-2.1/tests/test_data/symlink_localtime/usr/share/000077500000000000000000000000001365517301100235725ustar00rootroot00000000000000tzlocal-2.1/tests/test_data/symlink_localtime/usr/share/zoneinfo/000077500000000000000000000000001365517301100254215ustar00rootroot00000000000000tzlocal-2.1/tests/test_data/symlink_localtime/usr/share/zoneinfo/Africa/000077500000000000000000000000001365517301100266065ustar00rootroot00000000000000tzlocal-2.1/tests/test_data/symlink_localtime/usr/share/zoneinfo/Africa/Harare000066400000000000000000000002351365517301100277330ustar00rootroot00000000000000TZif2‚FÇd LMTCATTZif2ÿÿÿÿ‚FÇd LMTCAT CAT-2 tzlocal-2.1/tests/test_data/timezone/000077500000000000000000000000001365517301100177725ustar00rootroot00000000000000tzlocal-2.1/tests/test_data/timezone/etc/000077500000000000000000000000001365517301100205455ustar00rootroot00000000000000tzlocal-2.1/tests/test_data/timezone/etc/timezone000066400000000000000000000001011365517301100223120ustar00rootroot00000000000000Africa/Harare# We allow comments. It's unusual, but has happened tzlocal-2.1/tests/test_data/timezone_setting/000077500000000000000000000000001365517301100215275ustar00rootroot00000000000000tzlocal-2.1/tests/test_data/timezone_setting/etc/000077500000000000000000000000001365517301100223025ustar00rootroot00000000000000tzlocal-2.1/tests/test_data/timezone_setting/etc/conf.d/000077500000000000000000000000001365517301100234515ustar00rootroot00000000000000tzlocal-2.1/tests/test_data/timezone_setting/etc/conf.d/clock000066400000000000000000000000331365517301100244630ustar00rootroot00000000000000TIMEZONE = "Africa/Harare" tzlocal-2.1/tests/test_data/top_line_comment/000077500000000000000000000000001365517301100214735ustar00rootroot00000000000000tzlocal-2.1/tests/test_data/top_line_comment/etc/000077500000000000000000000000001365517301100222465ustar00rootroot00000000000000tzlocal-2.1/tests/test_data/top_line_comment/etc/timezone000066400000000000000000000000461365517301100240230ustar00rootroot00000000000000# Comment on first line Africa/Harare tzlocal-2.1/tests/test_data/vardbzoneinfo/000077500000000000000000000000001365517301100210065ustar00rootroot00000000000000tzlocal-2.1/tests/test_data/vardbzoneinfo/etc/000077500000000000000000000000001365517301100215615ustar00rootroot00000000000000tzlocal-2.1/tests/test_data/vardbzoneinfo/etc/timezone000066400000000000000000000000011365517301100233250ustar00rootroot00000000000000 tzlocal-2.1/tests/test_data/vardbzoneinfo/var/000077500000000000000000000000001365517301100215765ustar00rootroot00000000000000tzlocal-2.1/tests/test_data/vardbzoneinfo/var/db/000077500000000000000000000000001365517301100221635ustar00rootroot00000000000000tzlocal-2.1/tests/test_data/vardbzoneinfo/var/db/zoneinfo000066400000000000000000000001201365517301100237260ustar00rootroot00000000000000Africa/Harare localhost # The host is not a part of the format, but is allowed. tzlocal-2.1/tests/test_data/zone_setting/000077500000000000000000000000001365517301100206505ustar00rootroot00000000000000tzlocal-2.1/tests/test_data/zone_setting/etc/000077500000000000000000000000001365517301100214235ustar00rootroot00000000000000tzlocal-2.1/tests/test_data/zone_setting/etc/sysconfig/000077500000000000000000000000001365517301100234275ustar00rootroot00000000000000tzlocal-2.1/tests/test_data/zone_setting/etc/sysconfig/clock000066400000000000000000000000251365517301100244420ustar00rootroot00000000000000ZONE="Africa/Harare" tzlocal-2.1/tests/tests.py000066400000000000000000000143031365517301100157050ustar00rootroot00000000000000import mock import os import pytz import sys import tzlocal.unix import unittest from datetime import datetime try: from cStringIO import StringIO # Python 2 except ImportError: from io import StringIO # Python 3 from tzlocal import utils class TzLocalTests(unittest.TestCase): def setUp(self): if 'TZ' in os.environ: del os.environ['TZ'] self.path = os.path.split(__file__)[0] def test_env(self): tz_harare = tzlocal.unix._tz_from_env(':Africa/Harare') self.assertEqual(tz_harare.zone, 'Africa/Harare') # Some Unices allow this as well, so we must allow it: tz_harare = tzlocal.unix._tz_from_env('Africa/Harare') self.assertEqual(tz_harare.zone, 'Africa/Harare') tz_local = tzlocal.unix._tz_from_env(':' + os.path.join(self.path, 'test_data', 'Harare')) self.assertEqual(tz_local.zone, 'local') # Make sure the local timezone is the same as the Harare one above. # We test this with a past date, so that we don't run into future changes # of the Harare timezone. dt = datetime(2012, 1, 1, 5) self.assertEqual(tz_harare.localize(dt), tz_local.localize(dt)) # Non-zoneinfo timezones are not supported in the TZ environment. self.assertRaises(pytz.UnknownTimeZoneError, tzlocal.unix._tz_from_env, 'GMT+03:00') # Test the _try function os.environ['TZ'] = 'Africa/Harare' tz_harare = tzlocal.unix._try_tz_from_env() self.assertEqual(tz_harare.zone, 'Africa/Harare') # With a zone that doesn't exist os.environ['TZ'] = 'Just Nonsense' tz_harare = tzlocal.unix._try_tz_from_env() self.assertIsNone(tz_harare) def test_timezone(self): # Most versions of Ubuntu tz = tzlocal.unix._get_localzone(_root=os.path.join(self.path, 'test_data', 'timezone')) self.assertEqual(tz.zone, 'Africa/Harare') def test_timezone_top_line_comment(self): tz = tzlocal.unix._get_localzone(_root=os.path.join(self.path, 'test_data', 'top_line_comment')) self.assertEqual(tz.zone, 'Africa/Harare') def test_zone_setting(self): # A ZONE setting in /etc/sysconfig/clock, f ex CentOS tz = tzlocal.unix._get_localzone(_root=os.path.join(self.path, 'test_data', 'zone_setting')) self.assertEqual(tz.zone, 'Africa/Harare') def test_timezone_setting(self): # A ZONE setting in /etc/conf.d/clock, f ex Gentoo tz = tzlocal.unix._get_localzone(_root=os.path.join(self.path, 'test_data', 'timezone_setting')) self.assertEqual(tz.zone, 'Africa/Harare') def test_symlink_localtime(self): # A ZONE setting in the target path of a symbolic linked localtime, f ex systemd distributions tz = tzlocal.unix._get_localzone(_root=os.path.join(self.path, 'test_data', 'symlink_localtime')) self.assertEqual(tz.zone, 'Africa/Harare') def test_vardbzoneinfo_setting(self): # A ZONE setting in /etc/conf.d/clock, f ex Gentoo tz = tzlocal.unix._get_localzone(_root=os.path.join(self.path, 'test_data', 'vardbzoneinfo')) self.assertEqual(tz.zone, 'Africa/Harare') def test_only_localtime(self): tz = tzlocal.unix._get_localzone(_root=os.path.join(self.path, 'test_data', 'localtime')) self.assertEqual(tz.zone, 'local') dt = datetime(2012, 1, 1, 5) self.assertEqual(pytz.timezone('Africa/Harare').localize(dt), tz.localize(dt)) @mock.patch('tzlocal.utils.assert_tz_offset') def test_get_reload(self, atomock): # Clear any cached zone tzlocal.unix._cache_tz = None os.environ['TZ'] = 'Africa/Harare' tz_harare = tzlocal.unix.get_localzone() self.assertEqual(tz_harare.zone, 'Africa/Harare') # Changing the TZ makes no difference, because it's cached os.environ['TZ'] = 'Africa/Johannesburg' tz_harare = tzlocal.unix.get_localzone() self.assertEqual(tz_harare.zone, 'Africa/Harare') # So we reload it tz_harare = tzlocal.unix.reload_localzone() self.assertEqual(tz_harare.zone, 'Africa/Johannesburg') def test_fail(self): out = StringIO() stderr = sys.stderr try: sys.stderr = out tz = tzlocal.unix._get_localzone( _root=os.path.join(self.path, 'test_data')) finally: sys.stderr = stderr self.assertEqual(tz, pytz.utc) self.assertIn('Can not find any timezone configuration', out.getvalue()) def test_assert_tz_offset(self): # The local zone should be the local zone: local = tzlocal.get_localzone() tzlocal.utils.assert_tz_offset(local) # Get a non local zone. Let's use Chatham, population 600. other = pytz.timezone('Pacific/Chatham') with self.assertRaises(ValueError): tzlocal.utils.assert_tz_offset(other) if sys.platform == 'win32': import tzlocal.win32 class TzWin32Tests(unittest.TestCase): def test_win32(self): tzlocal.win32.get_localzone() else: class TzWin32Tests(unittest.TestCase): @mock.patch('tzlocal.utils.assert_tz_offset') def test_win32_on_unix(self, atomock): # Yes, winreg is all mocked out, but this test means we at least # catch syntax errors, etc. winreg = mock.MagicMock() winreg.OpenKey = mock.MagicMock() winreg.OpenKey.close = mock.MagicMock() winreg.QueryInfoKey = mock.MagicMock(return_value=(1, 1)) winreg.EnumValue = mock.MagicMock( return_value=('TimeZoneKeyName','Belarus Standard Time')) winreg.EnumKey = mock.Mock(return_value='Bahia Standard Time') sys.modules['winreg'] = winreg import tzlocal.win32 tz = tzlocal.win32.get_localzone() self.assertEqual(tz.zone, 'Europe/Minsk') tzlocal.win32.valuestodict = mock.Mock(return_value={ 'StandardName': 'Mocked Standard Time', 'Std': 'Mocked Standard Time', }) tz = tzlocal.win32.reload_localzone() self.assertEqual(tz.zone, 'America/Bahia') if __name__ == '__main__': unittest.main() tzlocal-2.1/tzlocal/000077500000000000000000000000001365517301100144765ustar00rootroot00000000000000tzlocal-2.1/tzlocal/__init__.py000066400000000000000000000002501365517301100166040ustar00rootroot00000000000000import sys if sys.platform == 'win32': from tzlocal.win32 import get_localzone, reload_localzone else: from tzlocal.unix import get_localzone, reload_localzone tzlocal-2.1/tzlocal/unix.py000066400000000000000000000136561365517301100160460ustar00rootroot00000000000000import os import pytz import re import warnings from tzlocal import utils _cache_tz = None 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 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.""" tzenv = _try_tz_from_env() if tzenv: return tzenv # Are we under Termux on Android? if os.path.exists('/system/bin/getprop'): import subprocess 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. for configfile in ('etc/timezone', 'var/db/zoneinfo'): tzpath = os.path.join(_root, configfile) try: with open(tzpath, 'rb') as tzfile: data = tzfile.read() # 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 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 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 except IOError: # File doesn't exist or is a directory continue # CentOS has a ZONE setting in /etc/sysconfig/clock, # OpenSUSE has a TIMEZONE setting in /etc/sysconfig/clock and # 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('\"') for filename in ('etc/sysconfig/clock', 'etc/conf.d/clock'): tzpath = os.path.join(_root, filename) try: with open(tzpath, 'rt') as tzfile: data = tzfile.readlines() for line in data: # Look for the ZONE= setting. match = zone_re.match(line) if match is None: # No ZONE= setting. Look for the TIMEZONE= setting. match = timezone_re.match(line) if match is not None: # Some setting existed line = line[match.end():] etctz = line[:end_re.search(line).start()] # We found a timezone 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: # 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') if os.path.exists(tzpath) and os.path.islink(tzpath): tzpath = os.path.realpath(tzpath) start = tzpath.find("/")+1 while start != 0: tzpath = tzpath[start:] try: return pytz.timezone(tzpath) except pytz.UnknownTimeZoneError: pass start = tzpath.find("/")+1 # 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: 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() return _cache_tz def reload_localzone(): """Reload the cached localzone. You need to call this if the timezone has changed.""" global _cache_tz _cache_tz = _get_localzone() return _cache_tz tzlocal-2.1/tzlocal/utils.py000066400000000000000000000032341365517301100162120ustar00rootroot00000000000000# -*- coding: utf-8 -*- import time import datetime import calendar def get_system_offset(): """Get system's timezone offset using built-in library time. For the Timezone constants (altzone, daylight, timezone, and tzname), the value is determined by the timezone rules in effect at module load time or the last time tzset() is called and may be incorrect for times in the past. To keep compatibility with Windows, we're always importing time module here. """ localtime = calendar.timegm(time.localtime()) gmtime = calendar.timegm(time.gmtime()) offset = gmtime - localtime # We could get the localtime and gmtime on either side of a second switch # 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 else: return -time.timezone def get_tz_offset(tz): """Get timezone's offset using built-in function datetime.utcoffset().""" return int(datetime.datetime.now(tz).utcoffset().total_seconds()) def assert_tz_offset(tz): """Assert that system's timezone offset equals to the timezone offset found. If they don't match, we probably have a misconfiguration, for example, an incorrect timezone set in /etc/timezone file in systemd distributions.""" tz_offset = get_tz_offset(tz) system_offset = get_system_offset() if 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) tzlocal-2.1/tzlocal/win32.py000066400000000000000000000063011365517301100160120ustar00rootroot00000000000000try: import _winreg as winreg except ImportError: import winreg import pytz from tzlocal.windows_tz import win_tz from tzlocal import utils _cache_tz = None def valuestodict(key): """Convert a registry key's values to a dictionary.""" dict = {} size = winreg.QueryInfoKey(key)[1] for i in range(size): data = winreg.EnumValue(key, i) dict[data[0]] = data[1] return dict 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. handle = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) TZLOCALKEYNAME = r"SYSTEM\CurrentControlSet\Control\TimeZoneInformation" localtz = winreg.OpenKey(handle, TZLOCALKEYNAME) keyvalues = valuestodict(localtz) localtz.Close() 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] else: # 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: # Nope, that didn't work. Try adding "Standard Time", # it seems to work a lot of times: timezone = win_tz.get(tzkeyname + " Standard Time") # Return what we have. if timezone is None: raise pytz.UnknownTimeZoneError('Can not find timezone ' + tzkeyname) return timezone 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 = 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 _cache_tz = pytz.timezone(get_localzone_name()) utils.assert_tz_offset(_cache_tz) return _cache_tz tzlocal-2.1/tzlocal/windows_tz.py000066400000000000000000000753211365517301100172670ustar00rootroot00000000000000# This file is autogenerated by the update_windows_mapping.py script # Do not edit. win_tz = {'AUS Central Standard Time': 'Australia/Darwin', 'AUS Eastern Standard Time': 'Australia/Sydney', 'Afghanistan Standard Time': 'Asia/Kabul', 'Alaskan Standard Time': 'America/Anchorage', 'Aleutian Standard Time': 'America/Adak', 'Altai Standard Time': 'Asia/Barnaul', 'Arab Standard Time': 'Asia/Riyadh', 'Arabian Standard Time': 'Asia/Dubai', 'Arabic Standard Time': 'Asia/Baghdad', 'Argentina Standard Time': 'America/Buenos_Aires', 'Astrakhan Standard Time': 'Europe/Astrakhan', 'Atlantic Standard Time': 'America/Halifax', 'Aus Central W. Standard Time': 'Australia/Eucla', 'Azerbaijan Standard Time': 'Asia/Baku', 'Azores Standard Time': 'Atlantic/Azores', 'Bahia Standard Time': 'America/Bahia', 'Bangladesh Standard Time': 'Asia/Dhaka', 'Belarus Standard Time': 'Europe/Minsk', 'Bougainville Standard Time': 'Pacific/Bougainville', 'Canada Central Standard Time': 'America/Regina', 'Cape Verde Standard Time': 'Atlantic/Cape_Verde', 'Caucasus Standard Time': 'Asia/Yerevan', 'Cen. Australia Standard Time': 'Australia/Adelaide', 'Central America Standard Time': 'America/Guatemala', 'Central Asia Standard Time': 'Asia/Almaty', 'Central Brazilian Standard Time': 'America/Cuiaba', 'Central Europe Standard Time': 'Europe/Budapest', 'Central European Standard Time': 'Europe/Warsaw', 'Central Pacific Standard Time': 'Pacific/Guadalcanal', 'Central Standard Time': 'America/Chicago', 'Central Standard Time (Mexico)': 'America/Mexico_City', 'Chatham Islands Standard Time': 'Pacific/Chatham', 'China Standard Time': 'Asia/Shanghai', 'Cuba Standard Time': 'America/Havana', 'Dateline Standard Time': 'Etc/GMT+12', 'E. Africa Standard Time': 'Africa/Nairobi', 'E. Australia Standard Time': 'Australia/Brisbane', 'E. Europe Standard Time': 'Europe/Chisinau', 'E. South America Standard Time': 'America/Sao_Paulo', 'Easter Island Standard Time': 'Pacific/Easter', 'Eastern Standard Time': 'America/New_York', 'Eastern Standard Time (Mexico)': 'America/Cancun', 'Egypt Standard Time': 'Africa/Cairo', 'Ekaterinburg Standard Time': 'Asia/Yekaterinburg', 'FLE Standard Time': 'Europe/Kiev', 'Fiji Standard Time': 'Pacific/Fiji', 'GMT Standard Time': 'Europe/London', 'GTB Standard Time': 'Europe/Bucharest', 'Georgian Standard Time': 'Asia/Tbilisi', 'Greenland Standard Time': 'America/Godthab', 'Greenwich Standard Time': 'Atlantic/Reykjavik', 'Haiti Standard Time': 'America/Port-au-Prince', 'Hawaiian Standard Time': 'Pacific/Honolulu', 'India Standard Time': 'Asia/Calcutta', 'Iran Standard Time': 'Asia/Tehran', 'Israel Standard Time': 'Asia/Jerusalem', 'Jordan Standard Time': 'Asia/Amman', 'Kaliningrad Standard Time': 'Europe/Kaliningrad', 'Korea Standard Time': 'Asia/Seoul', 'Libya Standard Time': 'Africa/Tripoli', 'Line Islands Standard Time': 'Pacific/Kiritimati', 'Lord Howe Standard Time': 'Australia/Lord_Howe', 'Magadan Standard Time': 'Asia/Magadan', 'Magallanes Standard Time': 'America/Punta_Arenas', 'Marquesas Standard Time': 'Pacific/Marquesas', 'Mauritius Standard Time': 'Indian/Mauritius', 'Middle East Standard Time': 'Asia/Beirut', 'Montevideo Standard Time': 'America/Montevideo', 'Morocco Standard Time': 'Africa/Casablanca', 'Mountain Standard Time': 'America/Denver', 'Mountain Standard Time (Mexico)': 'America/Chihuahua', 'Myanmar Standard Time': 'Asia/Rangoon', 'N. Central Asia Standard Time': 'Asia/Novosibirsk', 'Namibia Standard Time': 'Africa/Windhoek', 'Nepal Standard Time': 'Asia/Katmandu', 'New Zealand Standard Time': 'Pacific/Auckland', 'Newfoundland Standard Time': 'America/St_Johns', 'Norfolk Standard Time': 'Pacific/Norfolk', 'North Asia East Standard Time': 'Asia/Irkutsk', 'North Asia Standard Time': 'Asia/Krasnoyarsk', 'North Korea Standard Time': 'Asia/Pyongyang', 'Omsk Standard Time': 'Asia/Omsk', 'Pacific SA Standard Time': 'America/Santiago', 'Pacific Standard Time': 'America/Los_Angeles', 'Pacific Standard Time (Mexico)': 'America/Tijuana', 'Pakistan Standard Time': 'Asia/Karachi', 'Paraguay Standard Time': 'America/Asuncion', 'Qyzylorda Standard Time': 'Asia/Qyzylorda', 'Romance Standard Time': 'Europe/Paris', 'Russia Time Zone 10': 'Asia/Srednekolymsk', 'Russia Time Zone 11': 'Asia/Kamchatka', 'Russia Time Zone 3': 'Europe/Samara', 'Russian Standard Time': 'Europe/Moscow', 'SA Eastern Standard Time': 'America/Cayenne', 'SA Pacific Standard Time': 'America/Bogota', 'SA Western Standard Time': 'America/La_Paz', 'SE Asia Standard Time': 'Asia/Bangkok', 'Saint Pierre Standard Time': 'America/Miquelon', 'Sakhalin Standard Time': 'Asia/Sakhalin', 'Samoa Standard Time': 'Pacific/Apia', 'Sao Tome Standard Time': 'Africa/Sao_Tome', 'Saratov Standard Time': 'Europe/Saratov', 'Singapore Standard Time': 'Asia/Singapore', 'South Africa Standard Time': 'Africa/Johannesburg', 'Sri Lanka Standard Time': 'Asia/Colombo', 'Sudan Standard Time': 'Africa/Khartoum', 'Syria Standard Time': 'Asia/Damascus', 'Taipei Standard Time': 'Asia/Taipei', 'Tasmania Standard Time': 'Australia/Hobart', 'Tocantins Standard Time': 'America/Araguaina', 'Tokyo Standard Time': 'Asia/Tokyo', 'Tomsk Standard Time': 'Asia/Tomsk', 'Tonga Standard Time': 'Pacific/Tongatapu', 'Transbaikal Standard Time': 'Asia/Chita', 'Turkey Standard Time': 'Europe/Istanbul', 'Turks And Caicos Standard Time': 'America/Grand_Turk', 'US Eastern Standard Time': 'America/Indianapolis', 'US Mountain Standard Time': 'America/Phoenix', 'UTC': 'Etc/GMT', 'UTC+12': 'Etc/GMT-12', 'UTC+13': 'Etc/GMT-13', 'UTC-02': 'Etc/GMT+2', 'UTC-08': 'Etc/GMT+8', 'UTC-09': 'Etc/GMT+9', 'UTC-11': 'Etc/GMT+11', 'Ulaanbaatar Standard Time': 'Asia/Ulaanbaatar', 'Venezuela Standard Time': 'America/Caracas', 'Vladivostok Standard Time': 'Asia/Vladivostok', 'Volgograd Standard Time': 'Europe/Volgograd', 'W. Australia Standard Time': 'Australia/Perth', 'W. Central Africa Standard Time': 'Africa/Lagos', 'W. Europe Standard Time': 'Europe/Berlin', 'W. Mongolia Standard Time': 'Asia/Hovd', 'West Asia Standard Time': 'Asia/Tashkent', 'West Bank Standard Time': 'Asia/Hebron', 'West Pacific Standard Time': 'Pacific/Port_Moresby', 'Yakutsk Standard Time': 'Asia/Yakutsk'} # Old name for the win_tz variable: tz_names = win_tz tz_win = {'Africa/Abidjan': 'Greenwich Standard Time', 'Africa/Accra': 'Greenwich Standard Time', 'Africa/Addis_Ababa': 'E. Africa Standard Time', 'Africa/Algiers': 'W. Central Africa Standard Time', 'Africa/Asmera': 'E. Africa Standard Time', 'Africa/Bamako': 'Greenwich Standard Time', 'Africa/Bangui': 'W. Central Africa Standard Time', 'Africa/Banjul': 'Greenwich Standard Time', 'Africa/Bissau': 'Greenwich Standard Time', 'Africa/Blantyre': 'South Africa Standard Time', 'Africa/Brazzaville': 'W. Central Africa Standard Time', 'Africa/Bujumbura': 'South Africa Standard Time', 'Africa/Cairo': 'Egypt Standard Time', 'Africa/Casablanca': 'Morocco Standard Time', 'Africa/Ceuta': 'Romance Standard Time', 'Africa/Conakry': 'Greenwich Standard Time', 'Africa/Dakar': 'Greenwich Standard Time', 'Africa/Dar_es_Salaam': 'E. Africa Standard Time', 'Africa/Djibouti': 'E. Africa Standard Time', 'Africa/Douala': 'W. Central Africa Standard Time', 'Africa/El_Aaiun': 'Morocco Standard Time', 'Africa/Freetown': 'Greenwich Standard Time', 'Africa/Gaborone': 'South Africa Standard Time', 'Africa/Harare': 'South Africa Standard Time', 'Africa/Johannesburg': 'South Africa 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', 'Africa/Kinshasa': 'W. Central Africa Standard Time', 'Africa/Lagos': 'W. Central Africa Standard Time', 'Africa/Libreville': 'W. Central Africa Standard Time', 'Africa/Lome': 'Greenwich Standard Time', 'Africa/Luanda': 'W. Central Africa Standard Time', 'Africa/Lubumbashi': 'South Africa Standard Time', 'Africa/Lusaka': 'South Africa Standard Time', 'Africa/Malabo': 'W. Central Africa Standard Time', 'Africa/Maputo': 'South Africa Standard Time', 'Africa/Maseru': 'South Africa Standard Time', 'Africa/Mbabane': 'South Africa Standard Time', 'Africa/Mogadishu': 'E. Africa Standard Time', 'Africa/Monrovia': 'Greenwich Standard Time', 'Africa/Nairobi': 'E. Africa Standard Time', 'Africa/Ndjamena': 'W. Central Africa Standard Time', 'Africa/Niamey': 'W. Central Africa Standard Time', 'Africa/Nouakchott': 'Greenwich Standard Time', 'Africa/Ouagadougou': 'Greenwich Standard Time', 'Africa/Porto-Novo': 'W. Central Africa Standard Time', 'Africa/Sao_Tome': 'Sao Tome Standard Time', 'Africa/Timbuktu': 'Greenwich Standard Time', 'Africa/Tripoli': 'Libya Standard Time', 'Africa/Tunis': 'W. Central Africa Standard Time', 'Africa/Windhoek': 'Namibia Standard Time', 'America/Adak': 'Aleutian Standard Time', 'America/Anchorage': 'Alaskan Standard Time', 'America/Anguilla': 'SA Western Standard Time', 'America/Antigua': 'SA Western Standard Time', 'America/Araguaina': 'Tocantins Standard Time', 'America/Argentina/La_Rioja': 'Argentina Standard Time', 'America/Argentina/Rio_Gallegos': 'Argentina Standard Time', 'America/Argentina/Salta': 'Argentina Standard Time', 'America/Argentina/San_Juan': 'Argentina Standard Time', 'America/Argentina/San_Luis': 'Argentina Standard Time', 'America/Argentina/Tucuman': 'Argentina Standard Time', 'America/Argentina/Ushuaia': 'Argentina Standard Time', 'America/Aruba': 'SA Western Standard Time', 'America/Asuncion': 'Paraguay Standard Time', 'America/Atka': 'Aleutian Standard Time', 'America/Bahia': 'Bahia Standard Time', 'America/Bahia_Banderas': 'Central Standard Time (Mexico)', 'America/Barbados': 'SA Western Standard Time', 'America/Belem': 'SA Eastern Standard Time', 'America/Belize': 'Central America Standard Time', 'America/Blanc-Sablon': 'SA Western Standard Time', 'America/Boa_Vista': 'SA Western Standard Time', 'America/Bogota': 'SA Pacific Standard Time', 'America/Boise': 'Mountain Standard Time', 'America/Buenos_Aires': 'Argentina Standard Time', 'America/Cambridge_Bay': 'Mountain Standard Time', 'America/Campo_Grande': 'Central Brazilian Standard Time', 'America/Cancun': 'Eastern Standard Time (Mexico)', 'America/Caracas': 'Venezuela Standard Time', 'America/Catamarca': 'Argentina Standard Time', 'America/Cayenne': 'SA Eastern Standard Time', 'America/Cayman': 'SA Pacific Standard Time', 'America/Chicago': 'Central Standard Time', 'America/Chihuahua': 'Mountain Standard Time (Mexico)', 'America/Coral_Harbour': 'SA Pacific Standard Time', 'America/Cordoba': 'Argentina Standard Time', 'America/Costa_Rica': 'Central America Standard Time', 'America/Creston': 'US Mountain Standard Time', 'America/Cuiaba': 'Central Brazilian Standard Time', 'America/Curacao': 'SA Western 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', 'America/Dominica': 'SA Western Standard Time', 'America/Edmonton': 'Mountain Standard Time', 'America/Eirunepe': 'SA Pacific Standard Time', 'America/El_Salvador': 'Central America Standard Time', 'America/Ensenada': 'Pacific Standard Time (Mexico)', 'America/Fort_Nelson': 'US Mountain Standard Time', 'America/Fortaleza': 'SA Eastern Standard Time', 'America/Glace_Bay': 'Atlantic Standard Time', 'America/Godthab': 'Greenland Standard Time', 'America/Goose_Bay': 'Atlantic Standard Time', 'America/Grand_Turk': 'Turks And Caicos Standard Time', 'America/Grenada': 'SA Western Standard Time', 'America/Guadeloupe': 'SA Western Standard Time', 'America/Guatemala': 'Central America Standard Time', 'America/Guayaquil': 'SA Pacific Standard Time', 'America/Guyana': 'SA Western Standard Time', 'America/Halifax': 'Atlantic Standard Time', 'America/Havana': 'Cuba Standard Time', 'America/Hermosillo': 'US Mountain Standard Time', 'America/Indiana/Knox': 'Central Standard Time', 'America/Indiana/Marengo': 'US Eastern Standard Time', 'America/Indiana/Petersburg': 'Eastern Standard Time', 'America/Indiana/Tell_City': 'Central Standard Time', 'America/Indiana/Vevay': 'US Eastern Standard Time', 'America/Indiana/Vincennes': 'Eastern Standard Time', 'America/Indiana/Winamac': 'Eastern Standard Time', 'America/Indianapolis': 'US Eastern Standard Time', 'America/Inuvik': 'Mountain Standard Time', 'America/Iqaluit': 'Eastern Standard Time', 'America/Jamaica': 'SA Pacific Standard Time', 'America/Jujuy': 'Argentina Standard Time', 'America/Juneau': 'Alaskan Standard Time', 'America/Kentucky/Monticello': 'Eastern Standard Time', 'America/Knox_IN': 'Central Standard Time', 'America/Kralendijk': 'SA Western Standard Time', 'America/La_Paz': 'SA Western Standard Time', 'America/Lima': 'SA Pacific Standard Time', 'America/Los_Angeles': 'Pacific Standard Time', 'America/Louisville': 'Eastern Standard Time', 'America/Lower_Princes': 'SA Western Standard Time', 'America/Maceio': 'SA Eastern Standard Time', 'America/Managua': 'Central America Standard Time', 'America/Manaus': 'SA Western Standard Time', 'America/Marigot': 'SA Western Standard Time', 'America/Martinique': 'SA Western Standard Time', 'America/Matamoros': 'Central Standard Time', 'America/Mazatlan': 'Mountain Standard Time (Mexico)', 'America/Mendoza': 'Argentina Standard Time', 'America/Menominee': 'Central Standard Time', 'America/Merida': 'Central Standard Time (Mexico)', 'America/Metlakatla': 'Alaskan Standard Time', 'America/Mexico_City': 'Central Standard Time (Mexico)', 'America/Miquelon': 'Saint Pierre Standard Time', 'America/Moncton': 'Atlantic Standard Time', 'America/Monterrey': 'Central Standard Time (Mexico)', 'America/Montevideo': 'Montevideo Standard Time', 'America/Montreal': 'Eastern Standard Time', 'America/Montserrat': 'SA Western Standard Time', 'America/Nassau': 'Eastern Standard Time', 'America/New_York': 'Eastern Standard Time', 'America/Nipigon': 'Eastern Standard Time', 'America/Nome': 'Alaskan Standard Time', 'America/Noronha': 'UTC-02', 'America/North_Dakota/Beulah': 'Central Standard Time', 'America/North_Dakota/Center': 'Central Standard Time', 'America/North_Dakota/New_Salem': 'Central Standard Time', 'America/Ojinaga': 'Mountain Standard Time', 'America/Panama': 'SA Pacific Standard Time', 'America/Pangnirtung': 'Eastern Standard Time', 'America/Paramaribo': 'SA Eastern Standard Time', 'America/Phoenix': 'US Mountain Standard Time', 'America/Port-au-Prince': 'Haiti Standard Time', 'America/Port_of_Spain': 'SA Western Standard Time', 'America/Porto_Acre': 'SA Pacific Standard Time', 'America/Porto_Velho': 'SA Western Standard Time', 'America/Puerto_Rico': 'SA Western Standard Time', 'America/Punta_Arenas': 'Magallanes Standard Time', 'America/Rainy_River': 'Central Standard Time', 'America/Rankin_Inlet': 'Central Standard Time', 'America/Recife': 'SA Eastern Standard Time', 'America/Regina': 'Canada Central Standard Time', 'America/Resolute': 'Central Standard Time', 'America/Rio_Branco': 'SA Pacific Standard Time', 'America/Santa_Isabel': 'Pacific Standard Time (Mexico)', 'America/Santarem': 'SA Eastern Standard Time', 'America/Santiago': 'Pacific SA Standard Time', 'America/Santo_Domingo': 'SA Western Standard Time', 'America/Sao_Paulo': 'E. South America Standard Time', 'America/Scoresbysund': 'Azores Standard Time', 'America/Shiprock': 'Mountain Standard Time', 'America/Sitka': 'Alaskan Standard Time', 'America/St_Barthelemy': 'SA Western Standard Time', 'America/St_Johns': 'Newfoundland Standard Time', 'America/St_Kitts': 'SA Western Standard Time', 'America/St_Lucia': 'SA Western Standard Time', 'America/St_Thomas': 'SA Western Standard Time', 'America/St_Vincent': 'SA Western Standard Time', 'America/Swift_Current': 'Canada Central Standard Time', 'America/Tegucigalpa': 'Central America Standard Time', 'America/Thule': 'Atlantic Standard Time', 'America/Thunder_Bay': 'Eastern Standard Time', 'America/Tijuana': 'Pacific Standard Time (Mexico)', 'America/Toronto': 'Eastern Standard Time', 'America/Tortola': 'SA Western Standard Time', 'America/Vancouver': 'Pacific Standard Time', 'America/Virgin': 'SA Western Standard Time', 'America/Whitehorse': 'Pacific Standard Time', 'America/Winnipeg': 'Central Standard Time', 'America/Yakutat': 'Alaskan Standard Time', 'America/Yellowknife': 'Mountain Standard Time', 'Antarctica/Casey': 'Singapore Standard Time', 'Antarctica/Davis': 'SE Asia Standard Time', 'Antarctica/DumontDUrville': 'West Pacific 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', 'Antarctica/Rothera': 'SA Eastern Standard Time', 'Antarctica/South_Pole': 'New Zealand Standard Time', 'Antarctica/Syowa': 'E. Africa Standard Time', 'Antarctica/Vostok': 'Central Asia Standard Time', 'Arctic/Longyearbyen': 'W. Europe Standard Time', 'Asia/Aden': 'Arab Standard Time', 'Asia/Almaty': 'Central Asia Standard Time', 'Asia/Amman': 'Jordan Standard Time', 'Asia/Anadyr': 'Russia Time Zone 11', 'Asia/Aqtau': 'West Asia Standard Time', 'Asia/Aqtobe': 'West Asia Standard Time', 'Asia/Ashgabat': 'West Asia Standard Time', 'Asia/Ashkhabad': 'West Asia Standard Time', 'Asia/Atyrau': 'West Asia Standard Time', 'Asia/Baghdad': 'Arabic Standard Time', 'Asia/Bahrain': 'Arab Standard Time', 'Asia/Baku': 'Azerbaijan Standard Time', 'Asia/Bangkok': 'SE Asia Standard Time', 'Asia/Barnaul': 'Altai Standard Time', 'Asia/Beirut': 'Middle East Standard Time', 'Asia/Bishkek': 'Central Asia Standard Time', 'Asia/Brunei': 'Singapore Standard Time', 'Asia/Calcutta': 'India Standard Time', 'Asia/Chita': 'Transbaikal Standard Time', 'Asia/Choibalsan': 'Ulaanbaatar Standard Time', 'Asia/Chongqing': 'China Standard Time', 'Asia/Chungking': 'China Standard Time', 'Asia/Colombo': 'Sri Lanka Standard Time', 'Asia/Dacca': 'Bangladesh Standard Time', 'Asia/Damascus': 'Syria Standard Time', 'Asia/Dhaka': 'Bangladesh Standard Time', 'Asia/Dili': 'Tokyo Standard Time', 'Asia/Dubai': 'Arabian Standard Time', 'Asia/Dushanbe': 'West Asia Standard Time', 'Asia/Famagusta': 'GTB Standard Time', 'Asia/Gaza': 'West Bank Standard Time', 'Asia/Harbin': 'China Standard Time', 'Asia/Hebron': 'West Bank Standard Time', 'Asia/Hong_Kong': 'China Standard Time', 'Asia/Hovd': 'W. Mongolia Standard Time', 'Asia/Irkutsk': 'North Asia East Standard Time', 'Asia/Jakarta': 'SE Asia Standard Time', 'Asia/Jayapura': 'Tokyo Standard Time', 'Asia/Jerusalem': 'Israel Standard Time', 'Asia/Kabul': 'Afghanistan Standard Time', 'Asia/Kamchatka': 'Russia Time Zone 11', 'Asia/Karachi': 'Pakistan Standard Time', 'Asia/Kashgar': 'Central Asia Standard Time', 'Asia/Katmandu': 'Nepal Standard Time', 'Asia/Khandyga': 'Yakutsk Standard Time', 'Asia/Krasnoyarsk': 'North Asia Standard Time', 'Asia/Kuala_Lumpur': 'Singapore Standard Time', 'Asia/Kuching': 'Singapore Standard Time', 'Asia/Kuwait': 'Arab Standard Time', 'Asia/Macao': 'China Standard Time', 'Asia/Macau': 'China Standard Time', 'Asia/Magadan': 'Magadan Standard Time', 'Asia/Makassar': 'Singapore Standard Time', 'Asia/Manila': 'Singapore Standard Time', 'Asia/Muscat': 'Arabian Standard Time', 'Asia/Nicosia': 'GTB Standard Time', 'Asia/Novokuznetsk': 'North Asia Standard Time', 'Asia/Novosibirsk': 'N. Central Asia Standard Time', 'Asia/Omsk': 'Omsk Standard Time', 'Asia/Oral': 'West Asia Standard Time', 'Asia/Phnom_Penh': 'SE Asia Standard Time', 'Asia/Pontianak': 'SE Asia Standard Time', 'Asia/Pyongyang': 'North Korea Standard Time', 'Asia/Qatar': 'Arab Standard Time', 'Asia/Qostanay': 'Central Asia Standard Time', 'Asia/Qyzylorda': 'Qyzylorda Standard Time', 'Asia/Rangoon': 'Myanmar Standard Time', 'Asia/Riyadh': 'Arab Standard Time', 'Asia/Saigon': 'SE Asia Standard Time', 'Asia/Sakhalin': 'Sakhalin Standard Time', 'Asia/Samarkand': 'West Asia Standard Time', 'Asia/Seoul': 'Korea Standard Time', 'Asia/Shanghai': 'China Standard Time', 'Asia/Singapore': 'Singapore Standard Time', 'Asia/Srednekolymsk': 'Russia Time Zone 10', 'Asia/Taipei': 'Taipei Standard Time', 'Asia/Tashkent': 'West Asia Standard Time', 'Asia/Tbilisi': 'Georgian Standard Time', 'Asia/Tehran': 'Iran Standard Time', 'Asia/Tel_Aviv': 'Israel Standard Time', 'Asia/Thimbu': 'Bangladesh Standard Time', 'Asia/Thimphu': 'Bangladesh Standard Time', 'Asia/Tokyo': 'Tokyo Standard Time', 'Asia/Tomsk': 'Tomsk Standard Time', 'Asia/Ujung_Pandang': 'Singapore Standard Time', 'Asia/Ulaanbaatar': 'Ulaanbaatar Standard Time', 'Asia/Ulan_Bator': 'Ulaanbaatar Standard Time', 'Asia/Urumqi': 'Central Asia Standard Time', 'Asia/Ust-Nera': 'Vladivostok Standard Time', 'Asia/Vientiane': 'SE Asia Standard Time', 'Asia/Vladivostok': 'Vladivostok Standard Time', 'Asia/Yakutsk': 'Yakutsk Standard Time', 'Asia/Yekaterinburg': 'Ekaterinburg Standard Time', 'Asia/Yerevan': 'Caucasus Standard Time', 'Atlantic/Azores': 'Azores Standard Time', 'Atlantic/Bermuda': 'Atlantic Standard Time', 'Atlantic/Canary': 'GMT Standard Time', 'Atlantic/Cape_Verde': 'Cape Verde Standard Time', 'Atlantic/Faeroe': 'GMT Standard Time', 'Atlantic/Jan_Mayen': 'W. Europe Standard Time', 'Atlantic/Madeira': 'GMT Standard Time', 'Atlantic/Reykjavik': 'Greenwich Standard Time', 'Atlantic/South_Georgia': 'UTC-02', 'Atlantic/St_Helena': 'Greenwich Standard Time', 'Atlantic/Stanley': 'SA Eastern Standard Time', 'Australia/ACT': 'AUS Eastern Standard Time', 'Australia/Adelaide': 'Cen. Australia Standard Time', 'Australia/Brisbane': 'E. Australia Standard Time', 'Australia/Broken_Hill': 'Cen. Australia Standard Time', 'Australia/Canberra': 'AUS Eastern Standard Time', 'Australia/Currie': 'Tasmania Standard Time', 'Australia/Darwin': 'AUS Central Standard Time', 'Australia/Eucla': 'Aus Central W. Standard Time', 'Australia/Hobart': 'Tasmania Standard Time', 'Australia/LHI': 'Lord Howe Standard Time', 'Australia/Lindeman': 'E. Australia Standard Time', 'Australia/Lord_Howe': 'Lord Howe Standard Time', 'Australia/Melbourne': 'AUS Eastern Standard Time', 'Australia/NSW': 'AUS Eastern Standard Time', 'Australia/North': 'AUS Central Standard Time', 'Australia/Perth': 'W. Australia Standard Time', 'Australia/Queensland': 'E. Australia Standard Time', 'Australia/South': 'Cen. Australia Standard Time', 'Australia/Sydney': 'AUS Eastern Standard Time', 'Australia/Tasmania': 'Tasmania Standard Time', 'Australia/Victoria': 'AUS Eastern Standard Time', 'Australia/West': 'W. Australia Standard Time', 'Australia/Yancowinna': 'Cen. Australia Standard Time', 'Brazil/Acre': 'SA Pacific Standard Time', 'Brazil/DeNoronha': 'UTC-02', 'Brazil/East': 'E. South America Standard Time', 'Brazil/West': 'SA Western Standard Time', 'CST6CDT': 'Central Standard Time', 'Canada/Atlantic': 'Atlantic Standard Time', 'Canada/Central': 'Central Standard Time', 'Canada/Eastern': 'Eastern Standard Time', 'Canada/Mountain': 'Mountain Standard Time', 'Canada/Newfoundland': 'Newfoundland Standard Time', 'Canada/Pacific': 'Pacific Standard Time', 'Canada/Saskatchewan': 'Canada Central Standard Time', 'Canada/Yukon': 'Pacific Standard Time', 'Chile/Continental': 'Pacific SA Standard Time', 'Chile/EasterIsland': 'Easter Island Standard Time', 'Cuba': 'Cuba Standard Time', 'EST5EDT': 'Eastern Standard Time', 'Egypt': 'Egypt Standard Time', 'Eire': 'GMT Standard Time', 'Etc/GMT': 'UTC', 'Etc/GMT+1': 'Cape Verde Standard Time', 'Etc/GMT+10': 'Hawaiian Standard Time', 'Etc/GMT+11': 'UTC-11', 'Etc/GMT+12': 'Dateline Standard Time', 'Etc/GMT+2': 'UTC-02', 'Etc/GMT+3': 'SA Eastern Standard Time', 'Etc/GMT+4': 'SA Western Standard Time', 'Etc/GMT+5': 'SA Pacific Standard Time', 'Etc/GMT+6': 'Central America Standard Time', 'Etc/GMT+7': 'US Mountain Standard Time', 'Etc/GMT+8': 'UTC-08', 'Etc/GMT+9': 'UTC-09', 'Etc/GMT-1': 'W. Central Africa Standard Time', 'Etc/GMT-10': 'West Pacific Standard Time', 'Etc/GMT-11': 'Central Pacific Standard Time', 'Etc/GMT-12': 'UTC+12', 'Etc/GMT-13': 'UTC+13', 'Etc/GMT-14': 'Line Islands Standard Time', 'Etc/GMT-2': 'South Africa Standard Time', 'Etc/GMT-3': 'E. Africa Standard Time', 'Etc/GMT-4': 'Arabian Standard Time', 'Etc/GMT-5': 'West Asia Standard Time', 'Etc/GMT-6': 'Central Asia Standard Time', 'Etc/GMT-7': 'SE Asia Standard Time', 'Etc/GMT-8': 'Singapore Standard Time', 'Etc/GMT-9': 'Tokyo Standard Time', 'Etc/UCT': 'UTC', 'Etc/UTC': 'UTC', 'Europe/Amsterdam': 'W. Europe Standard Time', 'Europe/Andorra': 'W. Europe Standard Time', 'Europe/Astrakhan': 'Astrakhan Standard Time', 'Europe/Athens': 'GTB Standard Time', 'Europe/Belfast': 'GMT Standard Time', 'Europe/Belgrade': 'Central Europe Standard Time', 'Europe/Berlin': 'W. Europe Standard Time', 'Europe/Bratislava': 'Central Europe Standard Time', 'Europe/Brussels': 'Romance Standard Time', 'Europe/Bucharest': 'GTB Standard Time', 'Europe/Budapest': 'Central Europe Standard Time', 'Europe/Busingen': 'W. Europe Standard Time', 'Europe/Chisinau': 'E. Europe Standard Time', 'Europe/Copenhagen': 'Romance Standard Time', 'Europe/Dublin': 'GMT Standard Time', 'Europe/Gibraltar': 'W. Europe Standard Time', 'Europe/Guernsey': 'GMT Standard Time', 'Europe/Helsinki': 'FLE Standard Time', 'Europe/Isle_of_Man': 'GMT Standard Time', 'Europe/Istanbul': 'Turkey Standard Time', 'Europe/Jersey': 'GMT Standard Time', 'Europe/Kaliningrad': 'Kaliningrad Standard Time', 'Europe/Kiev': 'FLE Standard Time', 'Europe/Kirov': 'Russian Standard Time', 'Europe/Lisbon': 'GMT Standard Time', 'Europe/Ljubljana': 'Central Europe Standard Time', 'Europe/London': 'GMT Standard Time', 'Europe/Luxembourg': 'W. Europe Standard Time', 'Europe/Madrid': 'Romance Standard Time', 'Europe/Malta': 'W. Europe Standard Time', 'Europe/Mariehamn': 'FLE Standard Time', 'Europe/Minsk': 'Belarus Standard Time', 'Europe/Monaco': 'W. Europe Standard Time', 'Europe/Moscow': 'Russian Standard Time', 'Europe/Oslo': 'W. Europe Standard Time', 'Europe/Paris': 'Romance Standard Time', 'Europe/Podgorica': 'Central Europe Standard Time', 'Europe/Prague': 'Central Europe Standard Time', 'Europe/Riga': 'FLE Standard Time', 'Europe/Rome': 'W. Europe Standard Time', 'Europe/Samara': 'Russia Time Zone 3', 'Europe/San_Marino': 'W. Europe Standard Time', 'Europe/Sarajevo': 'Central European Standard Time', 'Europe/Saratov': 'Saratov Standard Time', 'Europe/Simferopol': 'Russian Standard Time', 'Europe/Skopje': 'Central European Standard Time', 'Europe/Sofia': 'FLE Standard Time', 'Europe/Stockholm': 'W. Europe Standard Time', 'Europe/Tallinn': 'FLE Standard Time', 'Europe/Tirane': 'Central Europe Standard Time', 'Europe/Tiraspol': 'E. Europe Standard Time', 'Europe/Ulyanovsk': 'Astrakhan Standard Time', 'Europe/Uzhgorod': 'FLE Standard Time', 'Europe/Vaduz': 'W. Europe Standard Time', 'Europe/Vatican': 'W. Europe Standard Time', 'Europe/Vienna': 'W. Europe Standard Time', 'Europe/Vilnius': 'FLE Standard Time', 'Europe/Volgograd': 'Volgograd Standard Time', 'Europe/Warsaw': 'Central European Standard Time', 'Europe/Zagreb': 'Central European Standard Time', 'Europe/Zaporozhye': 'FLE Standard Time', 'Europe/Zurich': 'W. Europe Standard Time', 'GB': 'GMT Standard Time', 'GB-Eire': 'GMT Standard Time', 'GMT+0': 'UTC', 'GMT-0': 'UTC', 'GMT0': 'UTC', 'Greenwich': 'UTC', 'Hongkong': 'China Standard Time', 'Iceland': 'Greenwich Standard Time', 'Indian/Antananarivo': 'E. Africa Standard Time', 'Indian/Chagos': 'Central Asia Standard Time', 'Indian/Christmas': 'SE Asia Standard Time', 'Indian/Cocos': 'Myanmar Standard Time', 'Indian/Comoro': 'E. Africa Standard Time', 'Indian/Kerguelen': 'West Asia Standard Time', 'Indian/Mahe': 'Mauritius Standard Time', 'Indian/Maldives': 'West Asia Standard Time', 'Indian/Mauritius': 'Mauritius Standard Time', 'Indian/Mayotte': 'E. Africa Standard Time', 'Indian/Reunion': 'Mauritius Standard Time', 'Iran': 'Iran Standard Time', 'Israel': 'Israel Standard Time', 'Jamaica': 'SA Pacific Standard Time', 'Japan': 'Tokyo Standard Time', 'Kwajalein': 'UTC+12', 'Libya': 'Libya Standard Time', 'MST7MDT': 'Mountain Standard Time', 'Mexico/BajaNorte': 'Pacific Standard Time (Mexico)', 'Mexico/BajaSur': 'Mountain Standard Time (Mexico)', 'Mexico/General': 'Central Standard Time (Mexico)', 'NZ': 'New Zealand Standard Time', 'NZ-CHAT': 'Chatham Islands Standard Time', 'Navajo': 'Mountain Standard Time', 'PRC': 'China Standard Time', 'PST8PDT': 'Pacific Standard Time', 'Pacific/Apia': 'Samoa Standard Time', 'Pacific/Auckland': 'New Zealand Standard Time', 'Pacific/Bougainville': 'Bougainville Standard Time', 'Pacific/Chatham': 'Chatham Islands Standard Time', 'Pacific/Easter': 'Easter Island Standard Time', 'Pacific/Efate': 'Central Pacific Standard Time', 'Pacific/Enderbury': 'UTC+13', 'Pacific/Fakaofo': 'UTC+13', 'Pacific/Fiji': 'Fiji Standard Time', 'Pacific/Funafuti': 'UTC+12', 'Pacific/Galapagos': 'Central America Standard Time', 'Pacific/Gambier': 'UTC-09', 'Pacific/Guadalcanal': 'Central Pacific Standard Time', 'Pacific/Guam': 'West Pacific Standard Time', 'Pacific/Honolulu': 'Hawaiian Standard Time', 'Pacific/Johnston': 'Hawaiian Standard Time', 'Pacific/Kiritimati': 'Line Islands Standard Time', 'Pacific/Kosrae': 'Central Pacific Standard Time', 'Pacific/Kwajalein': 'UTC+12', 'Pacific/Majuro': 'UTC+12', 'Pacific/Marquesas': 'Marquesas Standard Time', 'Pacific/Midway': 'UTC-11', 'Pacific/Nauru': 'UTC+12', 'Pacific/Niue': 'UTC-11', 'Pacific/Norfolk': 'Norfolk Standard Time', 'Pacific/Noumea': 'Central Pacific Standard Time', 'Pacific/Pago_Pago': 'UTC-11', 'Pacific/Palau': 'Tokyo Standard Time', 'Pacific/Pitcairn': 'UTC-08', 'Pacific/Ponape': 'Central Pacific Standard Time', 'Pacific/Port_Moresby': 'West Pacific Standard Time', 'Pacific/Rarotonga': 'Hawaiian Standard Time', 'Pacific/Saipan': 'West Pacific Standard Time', 'Pacific/Samoa': 'UTC-11', 'Pacific/Tahiti': 'Hawaiian Standard Time', 'Pacific/Tarawa': 'UTC+12', 'Pacific/Tongatapu': 'Tonga Standard Time', 'Pacific/Truk': 'West Pacific Standard Time', 'Pacific/Wake': 'UTC+12', 'Pacific/Wallis': 'UTC+12', 'Poland': 'Central European Standard Time', 'Portugal': 'GMT Standard Time', 'ROC': 'Taipei Standard Time', 'ROK': 'Korea Standard Time', 'Singapore': 'Singapore Standard Time', 'Turkey': 'Turkey Standard Time', 'UCT': 'UTC', 'US/Alaska': 'Alaskan Standard Time', 'US/Aleutian': 'Aleutian Standard Time', 'US/Arizona': 'US Mountain Standard Time', 'US/Central': 'Central Standard Time', 'US/Eastern': 'Eastern Standard Time', 'US/Hawaii': 'Hawaiian Standard Time', 'US/Indiana-Starke': 'Central Standard Time', 'US/Michigan': 'Eastern Standard Time', 'US/Mountain': 'Mountain Standard Time', 'US/Pacific': 'Pacific Standard Time', 'US/Samoa': 'UTC-11', 'UTC': 'UTC', 'Universal': 'UTC', 'W-SU': 'Russian Standard Time', 'Zulu': 'UTC'} tzlocal-2.1/update_windows_mappings.py000077500000000000000000000063661365517301100203500ustar00rootroot00000000000000#!/usr/bin/env python3 # This script generates the mapping between MS Windows timezone names and # tzdata/Olsen timezone names, by retrieving a file: # http://unicode.org/cldr/data/common/supplemental/supplementalData.xml # and parsing it, and from this generating the file windows_tz.py. # # It must be run with Python 3. import ftplib import logging from io import BytesIO from pprint import pprint import tarfile from urllib.parse import urlparse from urllib.request import urlopen from xml.dom import minidom WIN_ZONES_URL = 'https://raw.githubusercontent.com/unicode-org/cldr/master/common/supplemental/windowsZones.xml' ZONEINFO_URL = 'ftp://ftp.iana.org/tz/tzdata-latest.tar.gz' logging.basicConfig(level=logging.INFO) log = logging.getLogger() def update_old_names(): """Fetches the list of old tz names and returns a mapping""" url = urlparse(ZONEINFO_URL) log.info('Connecting to %s' % url.netloc) ftp = ftplib.FTP(url.netloc) ftp.login() gzfile = BytesIO() log.info('Fetching zoneinfo database') ftp.retrbinary('RETR ' + url.path, gzfile.write) gzfile.seek(0) log.info('Extracting backwards data') archive = tarfile.open(mode="r:gz", fileobj=gzfile) backward = {} for line in archive.extractfile('backward').readlines(): if line[0] == '#': continue if len(line.strip()) == 0: continue parts = line.split() if parts[0] != b'Link': continue backward[parts[2].decode('ascii')] = parts[1].decode('ascii') return backward def update_windows_zones(): backward = update_old_names() log.info('Fetching Windows mapping info from unicode.org') source = urlopen(WIN_ZONES_URL).read() dom = minidom.parseString(source) for element in dom.getElementsByTagName('mapTimezones'): if element.getAttribute('type') == 'windows': break log.info('Making windows mapping') win_tz = {} tz_win = {} for mapping in element.getElementsByTagName('mapZone'): if mapping.getAttribute('territory') == '001': win_tz[mapping.getAttribute('other')] = mapping.getAttribute('type').split(' ')[0] if win_tz[mapping.getAttribute('other')].startswith('Etc'): print (win_tz[mapping.getAttribute('other')], mapping.getAttribute('type').split(' ')[0]) for tz_name in mapping.getAttribute('type').split(' '): tz_win[tz_name] = mapping.getAttribute('other') log.info('Adding backwards data') # Map in the backwards compatible zone names for backward_compat_name, standard_name in backward.items(): win_zone = tz_win.get(standard_name, None) if win_zone: tz_win[backward_compat_name] = win_zone # Etc/UTC is a common but non-standard alias for Etc/GMT: tz_win['Etc/UTC'] = 'UTC' log.info('Writing mapping') with open('tzlocal/windows_tz.py', "wt") as out: out.write("# This file is autogenerated by the update_windows_mapping.py script\n" "# Do not edit.\nwin_tz = ") pprint(win_tz, out) out.write("\n# Old name for the win_tz variable:\ntz_names = win_tz\n\ntz_win = ") pprint(tz_win, out) log.info('Done') if __name__ == '__main__': update_windows_zones()