mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-07 05:31:15 -07:00
Update tzlocal to 2.0.0
This commit is contained in:
parent
b9a80d06e4
commit
2917b609c3
6 changed files with 166 additions and 174 deletions
|
@ -1,6 +1,47 @@
|
||||||
Changes
|
Changes
|
||||||
=======
|
=======
|
||||||
|
|
||||||
|
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.1 (2017-12-01)
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
@ -38,9 +79,6 @@ Changes
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
- Ensure closing of subprocess on OS X (ayalash)
|
- Ensure closing of subprocess on OS X (ayalash)
|
||||||
DOING: Implementing feedback on the unsubscribe button
|
|
||||||
DOING: Investigating remaining issues with DOCX export
|
|
||||||
BLOCKERS: None
|
|
||||||
|
|
||||||
- Removed unused imports (jwilk)
|
- Removed unused imports (jwilk)
|
||||||
|
|
||||||
|
|
|
@ -1,134 +0,0 @@
|
||||||
import mock
|
|
||||||
import os
|
|
||||||
import pytz
|
|
||||||
import sys
|
|
||||||
import tzlocal.unix
|
|
||||||
import unittest
|
|
||||||
|
|
||||||
from datetime import datetime
|
|
||||||
|
|
||||||
|
|
||||||
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_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))
|
|
||||||
|
|
||||||
def test_get_reload(self):
|
|
||||||
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):
|
|
||||||
with self.assertRaises(pytz.exceptions.UnknownTimeZoneError):
|
|
||||||
tz = tzlocal.unix._get_localzone(_root=os.path.join(self.path, 'test_data'))
|
|
||||||
|
|
||||||
if sys.platform == 'win32':
|
|
||||||
|
|
||||||
import tzlocal.win32
|
|
||||||
class TzWin32Tests(unittest.TestCase):
|
|
||||||
|
|
||||||
def test_win32(self):
|
|
||||||
tzlocal.win32.get_localzone()
|
|
||||||
|
|
||||||
else:
|
|
||||||
|
|
||||||
class TzWin32Tests(unittest.TestCase):
|
|
||||||
|
|
||||||
def test_win32_on_unix(self):
|
|
||||||
# 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()
|
|
|
@ -1,15 +1,19 @@
|
||||||
import os
|
import os
|
||||||
import re
|
|
||||||
import pytz
|
import pytz
|
||||||
|
import re
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
from tzlocal import utils
|
||||||
|
|
||||||
_cache_tz = None
|
_cache_tz = None
|
||||||
|
|
||||||
|
|
||||||
def _tz_from_env(tzenv):
|
def _tz_from_env(tzenv):
|
||||||
if tzenv[0] == ':':
|
if tzenv[0] == ':':
|
||||||
tzenv = tzenv[1:]
|
tzenv = tzenv[1:]
|
||||||
|
|
||||||
# TZ specifies a file
|
# TZ specifies a file
|
||||||
if os.path.exists(tzenv):
|
if os.path.isabs(tzenv) and os.path.exists(tzenv):
|
||||||
with open(tzenv, 'rb') as tzfile:
|
with open(tzenv, 'rb') as tzfile:
|
||||||
return pytz.tzfile.build_tzinfo('local', tzfile)
|
return pytz.tzfile.build_tzinfo('local', tzfile)
|
||||||
|
|
||||||
|
@ -48,56 +52,85 @@ def _get_localzone(_root='/'):
|
||||||
if tzenv:
|
if tzenv:
|
||||||
return 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
|
# Now look for distribution specific configuration files
|
||||||
# that contain the timezone name.
|
# that contain the timezone name.
|
||||||
for configfile in ('etc/timezone', 'var/db/zoneinfo'):
|
for configfile in ('etc/timezone', 'var/db/zoneinfo'):
|
||||||
tzpath = os.path.join(_root, configfile)
|
tzpath = os.path.join(_root, configfile)
|
||||||
if os.path.exists(tzpath):
|
try:
|
||||||
with open(tzpath, 'rb') as tzfile:
|
with open(tzpath, 'rb') as tzfile:
|
||||||
data = tzfile.read()
|
data = tzfile.read()
|
||||||
|
|
||||||
# Issue #3 was that /etc/timezone was a zoneinfo file.
|
# Issue #3 was that /etc/timezone was a zoneinfo file.
|
||||||
# That's a misconfiguration, but we need to handle it gracefully:
|
# That's a misconfiguration, but we need to handle it gracefully:
|
||||||
if data[:5] == 'TZif2':
|
if data[:5] == b'TZif2':
|
||||||
continue
|
continue
|
||||||
|
|
||||||
etctz = data.strip().decode()
|
etctz = data.strip().decode()
|
||||||
# Get rid of host definitions and comments:
|
if not etctz:
|
||||||
if ' ' in etctz:
|
# Empty file, skip
|
||||||
etctz, dummy = etctz.split(' ', 1)
|
continue
|
||||||
if '#' in etctz:
|
for etctz in data.decode().splitlines():
|
||||||
etctz, dummy = etctz.split('#', 1)
|
# Get rid of host definitions and comments:
|
||||||
return pytz.timezone(etctz.replace(' ', '_'))
|
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,
|
# CentOS has a ZONE setting in /etc/sysconfig/clock,
|
||||||
# OpenSUSE has a TIMEZONE setting in /etc/sysconfig/clock and
|
# OpenSUSE has a TIMEZONE setting in /etc/sysconfig/clock and
|
||||||
# Gentoo has a TIMEZONE setting in /etc/conf.d/clock
|
# Gentoo has a TIMEZONE setting in /etc/conf.d/clock
|
||||||
# We look through these files for a timezone:
|
# We look through these files for a timezone:
|
||||||
|
|
||||||
zone_re = re.compile('\s*ZONE\s*=\s*\"')
|
zone_re = re.compile(r'\s*ZONE\s*=\s*\"')
|
||||||
timezone_re = re.compile('\s*TIMEZONE\s*=\s*\"')
|
timezone_re = re.compile(r'\s*TIMEZONE\s*=\s*\"')
|
||||||
end_re = re.compile('\"')
|
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)
|
tzpath = os.path.join(_root, filename)
|
||||||
if not os.path.exists(tzpath):
|
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
|
continue
|
||||||
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
|
|
||||||
return pytz.timezone(etctz.replace(' ', '_'))
|
|
||||||
|
|
||||||
# systemd distributions use symlinks that include the zone name,
|
# systemd distributions use symlinks that include the zone name,
|
||||||
# see manpage of localtime(5) and timedatectl(1)
|
# see manpage of localtime(5) and timedatectl(1)
|
||||||
|
@ -122,15 +155,18 @@ def _get_localzone(_root='/'):
|
||||||
with open(tzpath, 'rb') as tzfile:
|
with open(tzpath, 'rb') as tzfile:
|
||||||
return pytz.tzfile.build_tzinfo('local', tzfile)
|
return pytz.tzfile.build_tzinfo('local', tzfile)
|
||||||
|
|
||||||
raise pytz.UnknownTimeZoneError('Can not find any timezone configuration')
|
warnings.warn('Can not find any timezone configuration, defaulting to UTC.')
|
||||||
|
return pytz.utc
|
||||||
|
|
||||||
def get_localzone():
|
def get_localzone():
|
||||||
"""Get the computers configured local timezone, if any."""
|
"""Get the computers configured local timezone, if any."""
|
||||||
global _cache_tz
|
global _cache_tz
|
||||||
if _cache_tz is None:
|
if _cache_tz is None:
|
||||||
_cache_tz = _get_localzone()
|
_cache_tz = _get_localzone()
|
||||||
|
|
||||||
return _cache_tz
|
return _cache_tz
|
||||||
|
|
||||||
|
|
||||||
def reload_localzone():
|
def reload_localzone():
|
||||||
"""Reload the cached localzone. You need to call this if the timezone has changed."""
|
"""Reload the cached localzone. You need to call this if the timezone has changed."""
|
||||||
global _cache_tz
|
global _cache_tz
|
||||||
|
|
38
lib/tzlocal/utils.py
Normal file
38
lib/tzlocal/utils.py
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import datetime
|
||||||
|
|
||||||
|
|
||||||
|
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.
|
||||||
|
"""
|
||||||
|
import time
|
||||||
|
if time.daylight and time.localtime().tm_isdst > 0:
|
||||||
|
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)
|
|
@ -3,11 +3,14 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
import winreg
|
import winreg
|
||||||
|
|
||||||
from tzlocal.windows_tz import win_tz
|
|
||||||
import pytz
|
import pytz
|
||||||
|
|
||||||
|
from tzlocal.windows_tz import win_tz
|
||||||
|
from tzlocal import utils
|
||||||
|
|
||||||
_cache_tz = None
|
_cache_tz = None
|
||||||
|
|
||||||
|
|
||||||
def valuestodict(key):
|
def valuestodict(key):
|
||||||
"""Convert a registry key's values to a dictionary."""
|
"""Convert a registry key's values to a dictionary."""
|
||||||
dict = {}
|
dict = {}
|
||||||
|
@ -17,6 +20,7 @@ def valuestodict(key):
|
||||||
dict[data[0]] = data[1]
|
dict[data[0]] = data[1]
|
||||||
return dict
|
return dict
|
||||||
|
|
||||||
|
|
||||||
def get_localzone_name():
|
def get_localzone_name():
|
||||||
# Windows is special. It has unique time zone names (in several
|
# Windows is special. It has unique time zone names (in several
|
||||||
# meanings of the word) available, but unfortunately, they can be
|
# meanings of the word) available, but unfortunately, they can be
|
||||||
|
@ -81,15 +85,20 @@ def get_localzone_name():
|
||||||
|
|
||||||
return timezone
|
return timezone
|
||||||
|
|
||||||
|
|
||||||
def get_localzone():
|
def get_localzone():
|
||||||
"""Returns the zoneinfo-based tzinfo object that matches the Windows-configured timezone."""
|
"""Returns the zoneinfo-based tzinfo object that matches the Windows-configured timezone."""
|
||||||
global _cache_tz
|
global _cache_tz
|
||||||
if _cache_tz is None:
|
if _cache_tz is None:
|
||||||
_cache_tz = pytz.timezone(get_localzone_name())
|
_cache_tz = pytz.timezone(get_localzone_name())
|
||||||
|
|
||||||
|
utils.assert_tz_offset(_cache_tz)
|
||||||
return _cache_tz
|
return _cache_tz
|
||||||
|
|
||||||
|
|
||||||
def reload_localzone():
|
def reload_localzone():
|
||||||
"""Reload the cached localzone. You need to call this if the timezone has changed."""
|
"""Reload the cached localzone. You need to call this if the timezone has changed."""
|
||||||
global _cache_tz
|
global _cache_tz
|
||||||
_cache_tz = pytz.timezone(get_localzone_name())
|
_cache_tz = pytz.timezone(get_localzone_name())
|
||||||
|
utils.assert_tz_offset(_cache_tz)
|
||||||
return _cache_tz
|
return _cache_tz
|
||||||
|
|
|
@ -99,10 +99,12 @@ win_tz = {'AUS Central Standard Time': 'Australia/Darwin',
|
||||||
'Saint Pierre Standard Time': 'America/Miquelon',
|
'Saint Pierre Standard Time': 'America/Miquelon',
|
||||||
'Sakhalin Standard Time': 'Asia/Sakhalin',
|
'Sakhalin Standard Time': 'Asia/Sakhalin',
|
||||||
'Samoa Standard Time': 'Pacific/Apia',
|
'Samoa Standard Time': 'Pacific/Apia',
|
||||||
|
'Sao Tome Standard Time': 'Africa/Sao_Tome',
|
||||||
'Saratov Standard Time': 'Europe/Saratov',
|
'Saratov Standard Time': 'Europe/Saratov',
|
||||||
'Singapore Standard Time': 'Asia/Singapore',
|
'Singapore Standard Time': 'Asia/Singapore',
|
||||||
'South Africa Standard Time': 'Africa/Johannesburg',
|
'South Africa Standard Time': 'Africa/Johannesburg',
|
||||||
'Sri Lanka Standard Time': 'Asia/Colombo',
|
'Sri Lanka Standard Time': 'Asia/Colombo',
|
||||||
|
'Sudan Standard Time': 'Africa/Khartoum',
|
||||||
'Syria Standard Time': 'Asia/Damascus',
|
'Syria Standard Time': 'Asia/Damascus',
|
||||||
'Taipei Standard Time': 'Asia/Taipei',
|
'Taipei Standard Time': 'Asia/Taipei',
|
||||||
'Tasmania Standard Time': 'Australia/Hobart',
|
'Tasmania Standard Time': 'Australia/Hobart',
|
||||||
|
@ -164,7 +166,7 @@ tz_win = {'Africa/Abidjan': 'Greenwich Standard Time',
|
||||||
'Africa/Johannesburg': 'South Africa Standard Time',
|
'Africa/Johannesburg': 'South Africa Standard Time',
|
||||||
'Africa/Juba': 'E. Africa Standard Time',
|
'Africa/Juba': 'E. Africa Standard Time',
|
||||||
'Africa/Kampala': 'E. Africa Standard Time',
|
'Africa/Kampala': 'E. Africa Standard Time',
|
||||||
'Africa/Khartoum': 'E. Africa Standard Time',
|
'Africa/Khartoum': 'Sudan Standard Time',
|
||||||
'Africa/Kigali': 'South Africa Standard Time',
|
'Africa/Kigali': 'South Africa Standard Time',
|
||||||
'Africa/Kinshasa': 'W. Central Africa Standard Time',
|
'Africa/Kinshasa': 'W. Central Africa Standard Time',
|
||||||
'Africa/Lagos': 'W. Central Africa Standard Time',
|
'Africa/Lagos': 'W. Central Africa Standard Time',
|
||||||
|
@ -185,7 +187,7 @@ tz_win = {'Africa/Abidjan': 'Greenwich Standard Time',
|
||||||
'Africa/Nouakchott': 'Greenwich Standard Time',
|
'Africa/Nouakchott': 'Greenwich Standard Time',
|
||||||
'Africa/Ouagadougou': 'Greenwich Standard Time',
|
'Africa/Ouagadougou': 'Greenwich Standard Time',
|
||||||
'Africa/Porto-Novo': 'W. Central Africa Standard Time',
|
'Africa/Porto-Novo': 'W. Central Africa Standard Time',
|
||||||
'Africa/Sao_Tome': 'Greenwich Standard Time',
|
'Africa/Sao_Tome': 'Sao Tome Standard Time',
|
||||||
'Africa/Timbuktu': 'Greenwich Standard Time',
|
'Africa/Timbuktu': 'Greenwich Standard Time',
|
||||||
'Africa/Tripoli': 'Libya Standard Time',
|
'Africa/Tripoli': 'Libya Standard Time',
|
||||||
'Africa/Tunis': 'W. Central Africa Standard Time',
|
'Africa/Tunis': 'W. Central Africa Standard Time',
|
||||||
|
@ -285,7 +287,7 @@ tz_win = {'Africa/Abidjan': 'Greenwich Standard Time',
|
||||||
'America/Mendoza': 'Argentina Standard Time',
|
'America/Mendoza': 'Argentina Standard Time',
|
||||||
'America/Menominee': 'Central Standard Time',
|
'America/Menominee': 'Central Standard Time',
|
||||||
'America/Merida': 'Central Standard Time (Mexico)',
|
'America/Merida': 'Central Standard Time (Mexico)',
|
||||||
'America/Metlakatla': 'Alaskan Standard Time',
|
'America/Metlakatla': 'Pacific Standard Time',
|
||||||
'America/Mexico_City': 'Central Standard Time (Mexico)',
|
'America/Mexico_City': 'Central Standard Time (Mexico)',
|
||||||
'America/Miquelon': 'Saint Pierre Standard Time',
|
'America/Miquelon': 'Saint Pierre Standard Time',
|
||||||
'America/Moncton': 'Atlantic Standard Time',
|
'America/Moncton': 'Atlantic Standard Time',
|
||||||
|
@ -345,7 +347,7 @@ tz_win = {'Africa/Abidjan': 'Greenwich Standard Time',
|
||||||
'America/Winnipeg': 'Central Standard Time',
|
'America/Winnipeg': 'Central Standard Time',
|
||||||
'America/Yakutat': 'Alaskan Standard Time',
|
'America/Yakutat': 'Alaskan Standard Time',
|
||||||
'America/Yellowknife': 'Mountain Standard Time',
|
'America/Yellowknife': 'Mountain Standard Time',
|
||||||
'Antarctica/Casey': 'Central Pacific Standard Time',
|
'Antarctica/Casey': 'W. Australia Standard Time',
|
||||||
'Antarctica/Davis': 'SE Asia Standard Time',
|
'Antarctica/Davis': 'SE Asia Standard Time',
|
||||||
'Antarctica/DumontDUrville': 'West Pacific Standard Time',
|
'Antarctica/DumontDUrville': 'West Pacific Standard Time',
|
||||||
'Antarctica/Macquarie': 'Central Pacific Standard Time',
|
'Antarctica/Macquarie': 'Central Pacific Standard Time',
|
||||||
|
@ -386,7 +388,7 @@ tz_win = {'Africa/Abidjan': 'Greenwich Standard Time',
|
||||||
'Asia/Dili': 'Tokyo Standard Time',
|
'Asia/Dili': 'Tokyo Standard Time',
|
||||||
'Asia/Dubai': 'Arabian Standard Time',
|
'Asia/Dubai': 'Arabian Standard Time',
|
||||||
'Asia/Dushanbe': 'West Asia Standard Time',
|
'Asia/Dushanbe': 'West Asia Standard Time',
|
||||||
'Asia/Famagusta': 'Turkey Standard Time',
|
'Asia/Famagusta': 'GTB Standard Time',
|
||||||
'Asia/Gaza': 'West Bank Standard Time',
|
'Asia/Gaza': 'West Bank Standard Time',
|
||||||
'Asia/Harbin': 'China Standard Time',
|
'Asia/Harbin': 'China Standard Time',
|
||||||
'Asia/Hebron': 'West Bank Standard Time',
|
'Asia/Hebron': 'West Bank Standard Time',
|
||||||
|
@ -421,7 +423,8 @@ tz_win = {'Africa/Abidjan': 'Greenwich Standard Time',
|
||||||
'Asia/Pontianak': 'SE Asia Standard Time',
|
'Asia/Pontianak': 'SE Asia Standard Time',
|
||||||
'Asia/Pyongyang': 'North Korea Standard Time',
|
'Asia/Pyongyang': 'North Korea Standard Time',
|
||||||
'Asia/Qatar': 'Arab Standard Time',
|
'Asia/Qatar': 'Arab Standard Time',
|
||||||
'Asia/Qyzylorda': 'Central Asia Standard Time',
|
'Asia/Qostanay': 'Central Asia Standard Time',
|
||||||
|
'Asia/Qyzylorda': 'West Asia Standard Time',
|
||||||
'Asia/Rangoon': 'Myanmar Standard Time',
|
'Asia/Rangoon': 'Myanmar Standard Time',
|
||||||
'Asia/Riyadh': 'Arab Standard Time',
|
'Asia/Riyadh': 'Arab Standard Time',
|
||||||
'Asia/Saigon': 'SE Asia Standard Time',
|
'Asia/Saigon': 'SE Asia Standard Time',
|
||||||
|
@ -530,6 +533,7 @@ tz_win = {'Africa/Abidjan': 'Greenwich Standard Time',
|
||||||
'Etc/GMT-7': 'SE Asia Standard Time',
|
'Etc/GMT-7': 'SE Asia Standard Time',
|
||||||
'Etc/GMT-8': 'Singapore Standard Time',
|
'Etc/GMT-8': 'Singapore Standard Time',
|
||||||
'Etc/GMT-9': 'Tokyo Standard Time',
|
'Etc/GMT-9': 'Tokyo Standard Time',
|
||||||
|
'Etc/UCT': 'UTC',
|
||||||
'Etc/UTC': 'UTC',
|
'Etc/UTC': 'UTC',
|
||||||
'Europe/Amsterdam': 'W. Europe Standard Time',
|
'Europe/Amsterdam': 'W. Europe Standard Time',
|
||||||
'Europe/Andorra': 'W. Europe Standard Time',
|
'Europe/Andorra': 'W. Europe Standard Time',
|
||||||
|
@ -673,6 +677,7 @@ tz_win = {'Africa/Abidjan': 'Greenwich Standard Time',
|
||||||
'ROK': 'Korea Standard Time',
|
'ROK': 'Korea Standard Time',
|
||||||
'Singapore': 'Singapore Standard Time',
|
'Singapore': 'Singapore Standard Time',
|
||||||
'Turkey': 'Turkey Standard Time',
|
'Turkey': 'Turkey Standard Time',
|
||||||
|
'UCT': 'UTC',
|
||||||
'US/Alaska': 'Alaskan Standard Time',
|
'US/Alaska': 'Alaskan Standard Time',
|
||||||
'US/Aleutian': 'Aleutian Standard Time',
|
'US/Aleutian': 'Aleutian Standard Time',
|
||||||
'US/Arizona': 'US Mountain Standard Time',
|
'US/Arizona': 'US Mountain Standard Time',
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue