Updated pytz to fix #1350

pull/1311/head^2
morpheus65535 4 years ago
parent 04fd39bc8a
commit 0803f419e4

@ -22,8 +22,8 @@ from pytz.tzfile import build_tzinfo
# The IANA (nee Olson) database is updated several times a year.
OLSON_VERSION = '2019c'
VERSION = '2019.3' # pip compatible version number.
OLSON_VERSION = '2021a'
VERSION = '2021.1' # pip compatible version number.
__version__ = VERSION
OLSEN_VERSION = OLSON_VERSION # Old releases had this misspelling
@ -34,7 +34,7 @@ __all__ = [
'NonExistentTimeError', 'UnknownTimeZoneError',
'all_timezones', 'all_timezones_set',
'common_timezones', 'common_timezones_set',
'BaseTzInfo',
'BaseTzInfo', 'FixedOffset',
]
@ -111,6 +111,13 @@ def open_resource(name):
def resource_exists(name):
"""Return true if the given resource exists"""
try:
if os.environ.get('PYTZ_SKIPEXISTSCHECK', ''):
# In "standard" distributions, we can assume that
# all the listed timezones are present. As an
# import-speed optimization, you can set the
# PYTZ_SKIPEXISTSCHECK flag to skip checking
# for the presence of the resource file on disk.
return True
open_resource(name).close()
return True
except IOError:
@ -263,8 +270,8 @@ def _UTC():
module global.
These examples belong in the UTC class above, but it is obscured; or in
the README.txt, but we are not depending on Python 2.4 so integrating
the README.txt examples with the unit tests is not trivial.
the README.rst, but we are not depending on Python 2.4 so integrating
the README.rst examples with the unit tests is not trivial.
>>> import datetime, pickle
>>> dt = datetime.datetime(2005, 3, 1, 14, 13, 21, tzinfo=utc)
@ -683,6 +690,7 @@ all_timezones = \
'America/North_Dakota/Beulah',
'America/North_Dakota/Center',
'America/North_Dakota/New_Salem',
'America/Nuuk',
'America/Ojinaga',
'America/Panama',
'America/Pangnirtung',
@ -1210,7 +1218,6 @@ common_timezones = \
'America/Fort_Nelson',
'America/Fortaleza',
'America/Glace_Bay',
'America/Godthab',
'America/Goose_Bay',
'America/Grand_Turk',
'America/Grenada',
@ -1264,6 +1271,7 @@ common_timezones = \
'America/North_Dakota/Beulah',
'America/North_Dakota/Center',
'America/North_Dakota/New_Salem',
'America/Nuuk',
'America/Ojinaga',
'America/Panama',
'America/Pangnirtung',
@ -1412,7 +1420,6 @@ common_timezones = \
'Australia/Adelaide',
'Australia/Brisbane',
'Australia/Broken_Hill',
'Australia/Currie',
'Australia/Darwin',
'Australia/Eucla',
'Australia/Hobart',

@ -8,7 +8,11 @@ __all__ = [
]
class UnknownTimeZoneError(KeyError):
class Error(Exception):
'''Base class for all exceptions raised by the pytz library'''
class UnknownTimeZoneError(KeyError, Error):
'''Exception raised when pytz is passed an unknown timezone.
>>> isinstance(UnknownTimeZoneError(), LookupError)
@ -20,11 +24,18 @@ class UnknownTimeZoneError(KeyError):
>>> isinstance(UnknownTimeZoneError(), KeyError)
True
And also a subclass of pytz.exceptions.Error, as are other pytz
exceptions.
>>> isinstance(UnknownTimeZoneError(), Error)
True
'''
pass
class InvalidTimeError(Exception):
class InvalidTimeError(Error):
'''Base class for invalid time exceptions.'''

@ -0,0 +1,34 @@
# -*- coding: ascii -*-
from doctest import DocFileSuite
import unittest
import os.path
import sys
THIS_DIR = os.path.dirname(__file__)
README = os.path.join(THIS_DIR, os.pardir, os.pardir, 'README.rst')
class DocumentationTestCase(unittest.TestCase):
def test_readme_encoding(self):
'''Confirm the README.rst is ASCII.'''
f = open(README, 'rb')
try:
f.read().decode('ASCII')
finally:
f.close()
def test_suite():
"For the Z3 test runner"
return unittest.TestSuite((
DocumentationTestCase('test_readme_encoding'),
DocFileSuite(os.path.join(os.pardir, os.pardir, 'README.rst'))))
if __name__ == '__main__':
sys.path.insert(
0, os.path.abspath(os.path.join(THIS_DIR, os.pardir, os.pardir))
)
unittest.main(defaultTest='test_suite')

@ -0,0 +1,315 @@
from operator import (
eq, ge, gt, le, lt, ne, add, concat, not_, sub, and_, or_, xor
)
import os.path
import sys
import unittest
import warnings
if __name__ == '__main__':
# Only munge path if invoked as a script. Testrunners should have setup
# the paths already
sys.path.insert(0, os.path.abspath(os.path.join(os.pardir, os.pardir)))
from pytz.lazy import LazyList, LazySet
class LazyListTestCase(unittest.TestCase):
initial_data = [3, 2, 1]
def setUp(self):
self.base = [3, 2, 1]
self.lesser = [2, 1, 0]
self.greater = [4, 3, 2]
self.lazy = LazyList(iter(list(self.base)))
def test_unary_ops(self):
unary_ops = [str, repr, len, bool, not_]
try:
unary_ops.append(unicode)
except NameError:
pass # unicode no longer exists in Python 3.
for op in unary_ops:
self.assertEqual(
op(self.lazy),
op(self.base), str(op))
def test_binary_ops(self):
binary_ops = [eq, ge, gt, le, lt, ne, add, concat]
try:
binary_ops.append(cmp)
except NameError:
pass # cmp no longer exists in Python 3.
for op in binary_ops:
self.assertEqual(
op(self.lazy, self.lazy),
op(self.base, self.base), str(op))
for other in [self.base, self.lesser, self.greater]:
self.assertEqual(
op(self.lazy, other),
op(self.base, other), '%s %s' % (op, other))
self.assertEqual(
op(other, self.lazy),
op(other, self.base), '%s %s' % (op, other))
# Multiplication
self.assertEqual(self.lazy * 3, self.base * 3)
self.assertEqual(3 * self.lazy, 3 * self.base)
# Contains
self.assertTrue(2 in self.lazy)
self.assertFalse(42 in self.lazy)
def test_iadd(self):
self.lazy += [1]
self.base += [1]
self.assertEqual(self.lazy, self.base)
def test_bool(self):
self.assertTrue(bool(self.lazy))
self.assertFalse(bool(LazyList()))
self.assertFalse(bool(LazyList(iter([]))))
def test_hash(self):
self.assertRaises(TypeError, hash, self.lazy)
def test_isinstance(self):
self.assertTrue(isinstance(self.lazy, list))
self.assertFalse(isinstance(self.lazy, tuple))
def test_callable(self):
try:
callable
except NameError:
return # No longer exists with Python 3.
self.assertFalse(callable(self.lazy))
def test_append(self):
self.base.append('extra')
self.lazy.append('extra')
self.assertEqual(self.lazy, self.base)
def test_count(self):
self.assertEqual(self.lazy.count(2), 1)
def test_index(self):
self.assertEqual(self.lazy.index(2), 1)
def test_extend(self):
self.base.extend([6, 7])
self.lazy.extend([6, 7])
self.assertEqual(self.lazy, self.base)
def test_insert(self):
self.base.insert(0, 'ping')
self.lazy.insert(0, 'ping')
self.assertEqual(self.lazy, self.base)
def test_pop(self):
self.assertEqual(self.lazy.pop(), self.base.pop())
self.assertEqual(self.lazy, self.base)
def test_remove(self):
self.base.remove(2)
self.lazy.remove(2)
self.assertEqual(self.lazy, self.base)
def test_reverse(self):
self.base.reverse()
self.lazy.reverse()
self.assertEqual(self.lazy, self.base)
def test_reversed(self):
self.assertEqual(list(reversed(self.lazy)), list(reversed(self.base)))
def test_sort(self):
self.base.sort()
self.assertNotEqual(self.lazy, self.base, 'Test data already sorted')
self.lazy.sort()
self.assertEqual(self.lazy, self.base)
def test_sorted(self):
self.assertEqual(sorted(self.lazy), sorted(self.base))
def test_getitem(self):
for idx in range(-len(self.base), len(self.base)):
self.assertEqual(self.lazy[idx], self.base[idx])
def test_setitem(self):
for idx in range(-len(self.base), len(self.base)):
self.base[idx] = idx + 1000
self.assertNotEqual(self.lazy, self.base)
self.lazy[idx] = idx + 1000
self.assertEqual(self.lazy, self.base)
def test_delitem(self):
del self.base[0]
self.assertNotEqual(self.lazy, self.base)
del self.lazy[0]
self.assertEqual(self.lazy, self.base)
del self.base[-2]
self.assertNotEqual(self.lazy, self.base)
del self.lazy[-2]
self.assertEqual(self.lazy, self.base)
def test_iter(self):
self.assertEqual(list(iter(self.lazy)), list(iter(self.base)))
def test_getslice(self):
for i in range(-len(self.base), len(self.base)):
for j in range(-len(self.base), len(self.base)):
for step in [-1, 1]:
self.assertEqual(self.lazy[i:j:step], self.base[i:j:step])
def test_setslice(self):
for i in range(-len(self.base), len(self.base)):
for j in range(-len(self.base), len(self.base)):
for step in [-1, 1]:
replacement = range(0, len(self.base[i:j:step]))
self.base[i:j:step] = replacement
self.lazy[i:j:step] = replacement
self.assertEqual(self.lazy, self.base)
def test_delslice(self):
del self.base[0:1]
del self.lazy[0:1]
self.assertEqual(self.lazy, self.base)
del self.base[-1:1:-1]
del self.lazy[-1:1:-1]
self.assertEqual(self.lazy, self.base)
class LazySetTestCase(unittest.TestCase):
initial_data = set([3, 2, 1])
def setUp(self):
self.base = set([3, 2, 1])
self.lazy = LazySet(iter(set(self.base)))
def test_unary_ops(self):
# These ops just need to work.
unary_ops = [str, repr]
try:
unary_ops.append(unicode)
except NameError:
pass # unicode no longer exists in Python 3.
for op in unary_ops:
op(self.lazy) # These ops just need to work.
# These ops should return identical values as a real set.
unary_ops = [len, bool, not_]
for op in unary_ops:
self.assertEqual(
op(self.lazy),
op(self.base), '%s(lazy) == %r' % (op, op(self.lazy)))
def test_binary_ops(self):
binary_ops = [eq, ge, gt, le, lt, ne, sub, and_, or_, xor]
try:
binary_ops.append(cmp)
except NameError:
pass # cmp no longer exists in Python 3.
for op in binary_ops:
self.assertEqual(
op(self.lazy, self.lazy),
op(self.base, self.base), str(op))
self.assertEqual(
op(self.lazy, self.base),
op(self.base, self.base), str(op))
self.assertEqual(
op(self.base, self.lazy),
op(self.base, self.base), str(op))
# Contains
self.assertTrue(2 in self.lazy)
self.assertFalse(42 in self.lazy)
def test_iops(self):
try:
iops = [isub, iand, ior, ixor]
except NameError:
return # Don't exist in older Python versions.
for op in iops:
# Mutating operators, so make fresh copies.
lazy = LazySet(self.base)
base = self.base.copy()
op(lazy, set([1]))
op(base, set([1]))
self.assertEqual(lazy, base, str(op))
def test_bool(self):
self.assertTrue(bool(self.lazy))
self.assertFalse(bool(LazySet()))
self.assertFalse(bool(LazySet(iter([]))))
def test_hash(self):
self.assertRaises(TypeError, hash, self.lazy)
def test_isinstance(self):
self.assertTrue(isinstance(self.lazy, set))
def test_callable(self):
try:
callable
except NameError:
return # No longer exists with Python 3.
self.assertFalse(callable(self.lazy))
def test_add(self):
self.base.add('extra')
self.lazy.add('extra')
self.assertEqual(self.lazy, self.base)
def test_copy(self):
self.assertEqual(self.lazy.copy(), self.base)
def test_method_ops(self):
ops = [
'difference', 'intersection', 'isdisjoint',
'issubset', 'issuperset', 'symmetric_difference', 'union',
'difference_update', 'intersection_update',
'symmetric_difference_update', 'update']
for op in ops:
if not hasattr(set, op):
continue # Not in this version of Python.
# Make a copy, as some of the ops are mutating.
lazy = LazySet(set(self.base))
base = set(self.base)
self.assertEqual(
getattr(lazy, op)(set([1])),
getattr(base, op)(set([1])), op)
self.assertEqual(lazy, base, op)
def test_discard(self):
self.base.discard(1)
self.assertNotEqual(self.lazy, self.base)
self.lazy.discard(1)
self.assertEqual(self.lazy, self.base)
def test_pop(self):
self.assertEqual(self.lazy.pop(), self.base.pop())
self.assertEqual(self.lazy, self.base)
def test_remove(self):
self.base.remove(2)
self.lazy.remove(2)
self.assertEqual(self.lazy, self.base)
def test_clear(self):
self.lazy.clear()
self.assertEqual(self.lazy, set())
if __name__ == '__main__':
warnings.simplefilter("error") # Warnings should be fatal in tests.
unittest.main()

@ -0,0 +1,870 @@
# -*- coding: ascii -*-
import doctest
import sys
import os
import os.path
import unittest
try:
import cPickle as pickle
except ImportError:
import pickle
from datetime import (
datetime,
timedelta
)
import warnings
if __name__ == '__main__':
# Only munge path if invoked as a script. Testrunners should have setup
# the paths already
sys.path.insert(0, os.path.abspath(os.path.join(os.pardir, os.pardir)))
import pytz # noqa
from pytz import reference # noqa
from pytz.tzfile import _byte_string # noqa
from pytz.tzinfo import DstTzInfo, StaticTzInfo # noqa
# I test for expected version to ensure the correct version of pytz is
# actually being tested.
EXPECTED_VERSION = '2021.1'
EXPECTED_OLSON_VERSION = '2021a'
fmt = '%Y-%m-%d %H:%M:%S %Z%z'
NOTIME = timedelta(0)
# GMT is a tzinfo.StaticTzInfo--the class we primarily want to test--while
# UTC is reference implementation. They both have the same timezone meaning.
UTC = pytz.timezone('UTC')
GMT = pytz.timezone('GMT')
assert isinstance(GMT, StaticTzInfo), 'GMT is no longer a StaticTzInfo'
def prettydt(dt):
"""datetime as a string using a known format.
We don't use strftime as it doesn't handle years earlier than 1900
per http://bugs.python.org/issue1777412
"""
if dt.utcoffset() >= timedelta(0):
offset = '+%s' % (dt.utcoffset(),)
else:
offset = '-%s' % (-1 * dt.utcoffset(),)
return '%04d-%02d-%02d %02d:%02d:%02d %s %s' % (
dt.year, dt.month, dt.day,
dt.hour, dt.minute, dt.second,
dt.tzname(), offset)
if sys.version_info[0] > 2:
# Python 3.x doesn't have unicode(), making writing code
# for Python 2.3 and Python 3.x a pain.
unicode = str
class BasicTest(unittest.TestCase):
def testVersion(self):
# Ensuring the correct version of pytz has been loaded
self.assertEqual(
EXPECTED_VERSION, pytz.__version__,
'Incorrect pytz version loaded. Import path is stuffed '
'or this test needs updating. (Wanted %s, got %s)'
% (EXPECTED_VERSION, pytz.__version__)
)
self.assertEqual(
EXPECTED_OLSON_VERSION, pytz.OLSON_VERSION,
'Incorrect pytz version loaded. Import path is stuffed '
'or this test needs updating. (Wanted %s, got %s)'
% (EXPECTED_OLSON_VERSION, pytz.OLSON_VERSION)
)
def testGMT(self):
now = datetime.now(tz=GMT)
self.assertTrue(now.utcoffset() == NOTIME)
self.assertTrue(now.dst() == NOTIME)
self.assertTrue(now.timetuple() == now.utctimetuple())
self.assertTrue(now == now.replace(tzinfo=UTC))
def testReferenceUTC(self):
now = datetime.now(tz=UTC)
self.assertTrue(now.utcoffset() == NOTIME)
self.assertTrue(now.dst() == NOTIME)
self.assertTrue(now.timetuple() == now.utctimetuple())
def testUnknownOffsets(self):
# This tzinfo behavior is required to make
# datetime.time.{utcoffset, dst, tzname} work as documented.
dst_tz = pytz.timezone('US/Eastern')
# This information is not known when we don't have a date,
# so return None per API.
self.assertTrue(dst_tz.utcoffset(None) is None)
self.assertTrue(dst_tz.dst(None) is None)
# We don't know the abbreviation, but this is still a valid
# tzname per the Python documentation.
self.assertEqual(dst_tz.tzname(None), 'US/Eastern')
def clearCache(self):
pytz._tzinfo_cache.clear()
def testUnicodeTimezone(self):
# We need to ensure that cold lookups work for both Unicode
# and traditional strings, and that the desired singleton is
# returned.
self.clearCache()
eastern = pytz.timezone(unicode('US/Eastern'))
self.assertTrue(eastern is pytz.timezone('US/Eastern'))
self.clearCache()
eastern = pytz.timezone('US/Eastern')
self.assertTrue(eastern is pytz.timezone(unicode('US/Eastern')))
def testStaticTzInfo(self):
# Ensure that static timezones are correctly detected,
# per lp:1602807
static = pytz.timezone('Etc/GMT-4')
self.assertTrue(isinstance(static, StaticTzInfo))
class PicklingTest(unittest.TestCase):
def _roundtrip_tzinfo(self, tz):
p = pickle.dumps(tz)
unpickled_tz = pickle.loads(p)
self.assertTrue(tz is unpickled_tz, '%s did not roundtrip' % tz.zone)
def _roundtrip_datetime(self, dt):
# Ensure that the tzinfo attached to a datetime instance
# is identical to the one returned. This is important for
# DST timezones, as some state is stored in the tzinfo.
tz = dt.tzinfo
p = pickle.dumps(dt)
unpickled_dt = pickle.loads(p)
unpickled_tz = unpickled_dt.tzinfo
self.assertTrue(tz is unpickled_tz, '%s did not roundtrip' % tz.zone)
def testDst(self):
tz = pytz.timezone('Europe/Amsterdam')
dt = datetime(2004, 2, 1, 0, 0, 0)
for localized_tz in tz._tzinfos.values():
self._roundtrip_tzinfo(localized_tz)
self._roundtrip_datetime(dt.replace(tzinfo=localized_tz))
def testRoundtrip(self):
for zone in pytz.all_timezones:
tz = pytz.timezone(zone)
self._roundtrip_tzinfo(tz)
def testDatabaseFixes(self):
# Hack the pickle to make it refer to a timezone abbreviation
# that does not match anything. The unpickler should be able
# to repair this case
tz = pytz.timezone('Australia/Melbourne')
p = pickle.dumps(tz)
tzname = tz._tzname
hacked_p = p.replace(
_byte_string(tzname),
_byte_string('?' * len(tzname))
)
self.assertNotEqual(p, hacked_p)
unpickled_tz = pickle.loads(hacked_p)
self.assertTrue(tz is unpickled_tz)
# Simulate a database correction. In this case, the incorrect
# data will continue to be used.
p = pickle.dumps(tz)
new_utcoffset = tz._utcoffset.seconds + 42
# Python 3 introduced a new pickle protocol where numbers are stored in
# hexadecimal representation. Here we extract the pickle
# representation of the number for the current Python version.
#
# Test protocol 3 on Python 3 and protocol 0 on Python 2.
if sys.version_info >= (3,):
protocol = 3
else:
protocol = 0
old_pickle_pattern = pickle.dumps(tz._utcoffset.seconds, protocol)[3:-1]
new_pickle_pattern = pickle.dumps(new_utcoffset, protocol)[3:-1]
hacked_p = p.replace(old_pickle_pattern, new_pickle_pattern)
self.assertNotEqual(p, hacked_p)
unpickled_tz = pickle.loads(hacked_p)
self.assertEqual(unpickled_tz._utcoffset.seconds, new_utcoffset)
self.assertTrue(tz is not unpickled_tz)
def testOldPickles(self):
# Ensure that applications serializing pytz instances as pickles
# have no troubles upgrading to a new pytz release. These pickles
# where created with pytz2006j
east1 = pickle.loads(
_byte_string(
"cpytz\n_p\np1\n(S'US/Eastern'\np2\nI-18000\n"
"I0\nS'EST'\np3\ntRp4\n."
)
)
east2 = pytz.timezone('US/Eastern').localize(
datetime(2006, 1, 1)).tzinfo
self.assertTrue(east1 is east2)
# Confirm changes in name munging between 2006j and 2007c cause
# no problems.
pap1 = pickle.loads(_byte_string(
"cpytz\n_p\np1\n(S'America/Port_minus_au_minus_Prince'"
"\np2\nI-17340\nI0\nS'PPMT'\np3\ntRp4\n."))
pap2 = pytz.timezone('America/Port-au-Prince').localize(
datetime(1910, 1, 1)).tzinfo
self.assertTrue(pap1 is pap2)
gmt1 = pickle.loads(_byte_string(
"cpytz\n_p\np1\n(S'Etc/GMT_plus_10'\np2\ntRp3\n."))
gmt2 = pytz.timezone('Etc/GMT+10')
self.assertTrue(gmt1 is gmt2)
class USEasternDSTStartTestCase(unittest.TestCase):
tzinfo = pytz.timezone('US/Eastern')
# 24 hours before DST changeover
transition_time = datetime(2002, 4, 7, 7, 0, 0, tzinfo=UTC)
# Increase for 'flexible' DST transitions due to 1 minute granularity
# of Python's datetime library
instant = timedelta(seconds=1)
# before transition
before = {
'tzname': 'EST',
'utcoffset': timedelta(hours=-5),
'dst': timedelta(hours=0),
}
# after transition
after = {
'tzname': 'EDT',
'utcoffset': timedelta(hours=-4),
'dst': timedelta(hours=1),
}
def _test_tzname(self, utc_dt, wanted):
tzname = wanted['tzname']
dt = utc_dt.astimezone(self.tzinfo)
self.assertEqual(
dt.tzname(), tzname,
'Expected %s as tzname for %s. Got %s' % (
tzname, str(utc_dt), dt.tzname()
)
)
def _test_utcoffset(self, utc_dt, wanted):
utcoffset = wanted['utcoffset']
dt = utc_dt.astimezone(self.tzinfo)
self.assertEqual(
dt.utcoffset(), wanted['utcoffset'],
'Expected %s as utcoffset for %s. Got %s' % (
utcoffset, utc_dt, dt.utcoffset()
)
)
def _test_dst(self, utc_dt, wanted):
dst = wanted['dst']
dt = utc_dt.astimezone(self.tzinfo)
self.assertEqual(
dt.dst(), dst,
'Expected %s as dst for %s. Got %s' % (dst, utc_dt, dt.dst())
)
def test_arithmetic(self):
utc_dt = self.transition_time
for days in range(-420, 720, 20):
delta = timedelta(days=days)
# Make sure we can get back where we started
dt = utc_dt.astimezone(self.tzinfo)
dt2 = dt + delta
dt2 = dt2 - delta
self.assertEqual(dt, dt2)
# Make sure arithmetic crossing DST boundaries ends
# up in the correct timezone after normalization
utc_plus_delta = (utc_dt + delta).astimezone(self.tzinfo)
local_plus_delta = self.tzinfo.normalize(dt + delta)
self.assertEqual(
prettydt(utc_plus_delta), prettydt(local_plus_delta),
'Incorrect result for delta==%d days. Wanted %r. Got %r' % (
days, prettydt(utc_plus_delta), prettydt(local_plus_delta),
)
)
def _test_all(self, utc_dt, wanted):
self._test_utcoffset(utc_dt, wanted)
self._test_tzname(utc_dt, wanted)
self._test_dst(utc_dt, wanted)
def testDayBefore(self):
self._test_all(
self.transition_time - timedelta(days=1), self.before
)
def testTwoHoursBefore(self):
self._test_all(
self.transition_time - timedelta(hours=2), self.before
)
def testHourBefore(self):
self._test_all(
self.transition_time - timedelta(hours=1), self.before
)
def testInstantBefore(self):
self._test_all(
self.transition_time - self.instant, self.before
)
def testTransition(self):
self._test_all(
self.transition_time, self.after
)
def testInstantAfter(self):
self._test_all(
self.transition_time + self.instant, self.after
)
def testHourAfter(self):
self._test_all(
self.transition_time + timedelta(hours=1), self.after
)
def testTwoHoursAfter(self):
self._test_all(
self.transition_time + timedelta(hours=1), self.after
)
def testDayAfter(self):
self._test_all(
self.transition_time + timedelta(days=1), self.after
)
class USEasternDSTEndTestCase(USEasternDSTStartTestCase):
tzinfo = pytz.timezone('US/Eastern')
transition_time = datetime(2002, 10, 27, 6, 0, 0, tzinfo=UTC)
before = {
'tzname': 'EDT',
'utcoffset': timedelta(hours=-4),
'dst': timedelta(hours=1),
}
after = {
'tzname': 'EST',
'utcoffset': timedelta(hours=-5),
'dst': timedelta(hours=0),
}
class USEasternEPTStartTestCase(USEasternDSTStartTestCase):
transition_time = datetime(1945, 8, 14, 23, 0, 0, tzinfo=UTC)
before = {
'tzname': 'EWT',
'utcoffset': timedelta(hours=-4),
'dst': timedelta(hours=1),
}
after = {
'tzname': 'EPT',
'utcoffset': timedelta(hours=-4),
'dst': timedelta(hours=1),
}
class USEasternEPTEndTestCase(USEasternDSTStartTestCase):
transition_time = datetime(1945, 9, 30, 6, 0, 0, tzinfo=UTC)
before = {
'tzname': 'EPT',
'utcoffset': timedelta(hours=-4),
'dst': timedelta(hours=1),
}
after = {
'tzname': 'EST',
'utcoffset': timedelta(hours=-5),
'dst': timedelta(hours=0),
}
class WarsawWMTEndTestCase(USEasternDSTStartTestCase):
# In 1915, Warsaw changed from Warsaw to Central European time.
# This involved the clocks being set backwards, causing a end-of-DST
# like situation without DST being involved.
tzinfo = pytz.timezone('Europe/Warsaw')
transition_time = datetime(1915, 8, 4, 22, 36, 0, tzinfo=UTC)
before = {
'tzname': 'WMT',
'utcoffset': timedelta(hours=1, minutes=24),
'dst': timedelta(0),
}
after = {
'tzname': 'CET',
'utcoffset': timedelta(hours=1),
'dst': timedelta(0),
}
class VilniusWMTEndTestCase(USEasternDSTStartTestCase):
# At the end of 1916, Vilnius changed timezones putting its clock
# forward by 11 minutes 35 seconds. Neither timezone was in DST mode.
tzinfo = pytz.timezone('Europe/Vilnius')
instant = timedelta(seconds=31)
transition_time = datetime(1916, 12, 31, 22, 36, 00, tzinfo=UTC)
before = {
'tzname': 'WMT',
'utcoffset': timedelta(hours=1, minutes=24),
'dst': timedelta(0),
}
after = {
'tzname': 'KMT',
'utcoffset': timedelta(hours=1, minutes=36), # Really 1:35:36
'dst': timedelta(0),
}
class VilniusCESTStartTestCase(USEasternDSTStartTestCase):
# In 1941, Vilnius changed from MSG to CEST, switching to summer
# time while simultaneously reducing its UTC offset by two hours,
# causing the clocks to go backwards for this summer time
# switchover.
tzinfo = pytz.timezone('Europe/Vilnius')
transition_time = datetime(1941, 6, 23, 21, 00, 00, tzinfo=UTC)
before = {
'tzname': 'MSK',
'utcoffset': timedelta(hours=3),
'dst': timedelta(0),
}
after = {
'tzname': 'CEST',
'utcoffset': timedelta(hours=2),
'dst': timedelta(hours=1),
}
class LondonHistoryStartTestCase(USEasternDSTStartTestCase):
# The first known timezone transition in London was in 1847 when
# clocks where synchronized to GMT. However, we currently only
# understand v1 format tzfile(5) files which does handle years
# this far in the past, so our earliest known transition is in
# 1916.
tzinfo = pytz.timezone('Europe/London')
# transition_time = datetime(1847, 12, 1, 1, 15, 00, tzinfo=UTC)
# before = {
# 'tzname': 'LMT',
# 'utcoffset': timedelta(minutes=-75),
# 'dst': timedelta(0),
# }
# after = {
# 'tzname': 'GMT',
# 'utcoffset': timedelta(0),
# 'dst': timedelta(0),
# }
transition_time = datetime(1916, 5, 21, 2, 00, 00, tzinfo=UTC)
before = {
'tzname': 'GMT',
'utcoffset': timedelta(0),
'dst': timedelta(0),
}
after = {
'tzname': 'BST',
'utcoffset': timedelta(hours=1),
'dst': timedelta(hours=1),
}
class LondonHistoryEndTestCase(USEasternDSTStartTestCase):
# Timezone switchovers are projected into the future, even
# though no official statements exist or could be believed even
# if they did exist. We currently only check the last known
# transition in 2037, as we are still using v1 format tzfile(5)
# files.
tzinfo = pytz.timezone('Europe/London')
# transition_time = datetime(2499, 10, 25, 1, 0, 0, tzinfo=UTC)
transition_time = datetime(2037, 10, 25, 1, 0, 0, tzinfo=UTC)
before = {
'tzname': 'BST',
'utcoffset': timedelta(hours=1),
'dst': timedelta(hours=1),
}
after = {
'tzname': 'GMT',
'utcoffset': timedelta(0),
'dst': timedelta(0),
}
class NoumeaHistoryStartTestCase(USEasternDSTStartTestCase):
# Noumea adopted a whole hour offset in 1912. Previously
# it was 11 hours, 5 minutes and 48 seconds off UTC. However,
# due to limitations of the Python datetime library, we need
# to round that to 11 hours 6 minutes.
tzinfo = pytz.timezone('Pacific/Noumea')
transition_time = datetime(1912, 1, 12, 12, 54, 12, tzinfo=UTC)
before = {
'tzname': 'LMT',
'utcoffset': timedelta(hours=11, minutes=6),
'dst': timedelta(0),
}
after = {
'tzname': '+11', # pre-2017a, NCT
'utcoffset': timedelta(hours=11),
'dst': timedelta(0),
}
class NoumeaDSTEndTestCase(USEasternDSTStartTestCase):
# Noumea dropped DST in 1997.
tzinfo = pytz.timezone('Pacific/Noumea')
transition_time = datetime(1997, 3, 1, 15, 00, 00, tzinfo=UTC)
before = {
'tzname': '+12', # pre-2017a, NCST
'utcoffset': timedelta(hours=12),
'dst': timedelta(hours=1),
}
after = {
'tzname': '+11', # pre-2017a, NCT
'utcoffset': timedelta(hours=11),
'dst': timedelta(0),
}
class NoumeaNoMoreDSTTestCase(NoumeaDSTEndTestCase):
# Noumea dropped DST in 1997. Here we test that it stops occuring.
transition_time = (
NoumeaDSTEndTestCase.transition_time + timedelta(days=365 * 10))
before = NoumeaDSTEndTestCase.after
after = NoumeaDSTEndTestCase.after
class TahitiTestCase(USEasternDSTStartTestCase):
# Tahiti has had a single transition in its history.
tzinfo = pytz.timezone('Pacific/Tahiti')
transition_time = datetime(1912, 10, 1, 9, 58, 16, tzinfo=UTC)
before = {
'tzname': 'LMT',
'utcoffset': timedelta(hours=-9, minutes=-58),
'dst': timedelta(0),
}
after = {
'tzname': '-10', # pre-2017a, TAHT
'utcoffset': timedelta(hours=-10),
'dst': timedelta(0),
}
class SamoaInternationalDateLineChange(USEasternDSTStartTestCase):
# At the end of 2011, Samoa will switch from being east of the
# international dateline to the west. There will be no Dec 30th
# 2011 and it will switch from UTC-10 to UTC+14.
tzinfo = pytz.timezone('Pacific/Apia')
transition_time = datetime(2011, 12, 30, 10, 0, 0, tzinfo=UTC)
before = {
'tzname': '-10', # pre-2017a, SDT
'utcoffset': timedelta(hours=-10),
'dst': timedelta(hours=1),
}
after = {
'tzname': '+14', # pre-2017a, WSDT
'utcoffset': timedelta(hours=14),
'dst': timedelta(hours=1),
}
class ReferenceUSEasternDSTStartTestCase(USEasternDSTStartTestCase):
tzinfo = reference.Eastern
def test_arithmetic(self):
# Reference implementation cannot handle this
pass
class ReferenceUSEasternDSTEndTestCase(USEasternDSTEndTestCase):
tzinfo = reference.Eastern
def testHourBefore(self):
# Python's datetime library has a bug, where the hour before
# a daylight saving transition is one hour out. For example,
# at the end of US/Eastern daylight saving time, 01:00 EST
# occurs twice (once at 05:00 UTC and once at 06:00 UTC),
# whereas the first should actually be 01:00 EDT.
# Note that this bug is by design - by accepting this ambiguity
# for one hour one hour per year, an is_dst flag on datetime.time
# became unnecessary.
self._test_all(self.transition_time - timedelta(hours=1), self.after)
def testInstantBefore(self):
self._test_all(self.transition_time - timedelta(seconds=1), self.after)
def test_arithmetic(self):
# Reference implementation cannot handle this
pass
class LocalTestCase(unittest.TestCase):
def testLocalize(self):
loc_tz = pytz.timezone('Europe/Amsterdam')
loc_time = loc_tz.localize(datetime(1930, 5, 10, 0, 0, 0))
# Actually +00:19:32, but Python datetime rounds this
self.assertEqual(loc_time.strftime('%Z%z'), 'AMT+0020')
loc_time = loc_tz.localize(datetime(1930, 5, 20, 0, 0, 0))
# Actually +00:19:32, but Python datetime rounds this
self.assertEqual(loc_time.strftime('%Z%z'), 'NST+0120')
loc_time = loc_tz.localize(datetime(1940, 5, 10, 0, 0, 0))
# pre-2017a, abbreviation was NCT
self.assertEqual(loc_time.strftime('%Z%z'), '+0020+0020')
loc_time = loc_tz.localize(datetime(1940, 5, 20, 0, 0, 0))
self.assertEqual(loc_time.strftime('%Z%z'), 'CEST+0200')
loc_time = loc_tz.localize(datetime(2004, 2, 1, 0, 0, 0))
self.assertEqual(loc_time.strftime('%Z%z'), 'CET+0100')
loc_time = loc_tz.localize(datetime(2004, 4, 1, 0, 0, 0))
self.assertEqual(loc_time.strftime('%Z%z'), 'CEST+0200')
loc_time = loc_tz.localize(datetime(1943, 3, 29, 1, 59, 59))
self.assertEqual(loc_time.strftime('%Z%z'), 'CET+0100')
# Switch to US
loc_tz = pytz.timezone('US/Eastern')
# End of DST ambiguity check
loc_time = loc_tz.localize(datetime(1918, 10, 27, 1, 59, 59), is_dst=1)
self.assertEqual(loc_time.strftime('%Z%z'), 'EDT-0400')
loc_time = loc_tz.localize(datetime(1918, 10, 27, 1, 59, 59), is_dst=0)
self.assertEqual(loc_time.strftime('%Z%z'), 'EST-0500')
self.assertRaises(
pytz.AmbiguousTimeError,
loc_tz.localize, datetime(1918, 10, 27, 1, 59, 59), is_dst=None
)
# Start of DST non-existent times
loc_time = loc_tz.localize(datetime(1918, 3, 31, 2, 0, 0), is_dst=0)
self.assertEqual(loc_time.strftime('%Z%z'), 'EST-0500')
loc_time = loc_tz.localize(datetime(1918, 3, 31, 2, 0, 0), is_dst=1)
self.assertEqual(loc_time.strftime('%Z%z'), 'EDT-0400')
self.assertRaises(
pytz.NonExistentTimeError,
loc_tz.localize, datetime(1918, 3, 31, 2, 0, 0), is_dst=None
)
# Weird changes - war time and peace time both is_dst==True
loc_time = loc_tz.localize(datetime(1942, 2, 9, 3, 0, 0))
self.assertEqual(loc_time.strftime('%Z%z'), 'EWT-0400')
loc_time = loc_tz.localize(datetime(1945, 8, 14, 19, 0, 0))
self.assertEqual(loc_time.strftime('%Z%z'), 'EPT-0400')
loc_time = loc_tz.localize(datetime(1945, 9, 30, 1, 0, 0), is_dst=1)
self.assertEqual(loc_time.strftime('%Z%z'), 'EPT-0400')
loc_time = loc_tz.localize(datetime(1945, 9, 30, 1, 0, 0), is_dst=0)
self.assertEqual(loc_time.strftime('%Z%z'), 'EST-0500')
# Weird changes - ambiguous time (end-of-DST like) but is_dst==False
for zonename, ambiguous_naive, expected in [
('Europe/Warsaw', datetime(1915, 8, 4, 23, 59, 59),
['1915-08-04 23:59:59 WMT+0124',
'1915-08-04 23:59:59 CET+0100']),
('Europe/Moscow', datetime(2014, 10, 26, 1, 30),
['2014-10-26 01:30:00 MSK+0400',
'2014-10-26 01:30:00 MSK+0300'])]:
loc_tz = pytz.timezone(zonename)
self.assertRaises(
pytz.AmbiguousTimeError,
loc_tz.localize, ambiguous_naive, is_dst=None
)
# Also test non-boolean is_dst in the weird case
for dst in [True, timedelta(1), False, timedelta(0)]:
loc_time = loc_tz.localize(ambiguous_naive, is_dst=dst)
self.assertEqual(loc_time.strftime(fmt), expected[not dst])
def testNormalize(self):
tz = pytz.timezone('US/Eastern')
dt = datetime(2004, 4, 4, 7, 0, 0, tzinfo=UTC).astimezone(tz)
dt2 = dt - timedelta(minutes=10)
self.assertEqual(
dt2.strftime('%Y-%m-%d %H:%M:%S %Z%z'),
'2004-04-04 02:50:00 EDT-0400'
)
dt2 = tz.normalize(dt2)
self.assertEqual(
dt2.strftime('%Y-%m-%d %H:%M:%S %Z%z'),
'2004-04-04 01:50:00 EST-0500'
)
def testPartialMinuteOffsets(self):
# utcoffset in Amsterdam was not a whole minute until 1937
# However, we fudge this by rounding them, as the Python
# datetime library
tz = pytz.timezone('Europe/Amsterdam')
utc_dt = datetime(1914, 1, 1, 13, 40, 28, tzinfo=UTC) # correct
utc_dt = utc_dt.replace(second=0) # But we need to fudge it
loc_dt = utc_dt.astimezone(tz)
self.assertEqual(
loc_dt.strftime('%Y-%m-%d %H:%M:%S %Z%z'),
'1914-01-01 14:00:00 AMT+0020'
)
# And get back...
utc_dt = loc_dt.astimezone(UTC)
self.assertEqual(
utc_dt.strftime('%Y-%m-%d %H:%M:%S %Z%z'),
'1914-01-01 13:40:00 UTC+0000'
)
def no_testCreateLocaltime(self):
# It would be nice if this worked, but it doesn't.
tz = pytz.timezone('Europe/Amsterdam')
dt = datetime(2004, 10, 31, 2, 0, 0, tzinfo=tz)
self.assertEqual(
dt.strftime(fmt),
'2004-10-31 02:00:00 CET+0100'
)
class CommonTimezonesTestCase(unittest.TestCase):
def test_bratislava(self):
# Bratislava is the default timezone for Slovakia, but our
# heuristics where not adding it to common_timezones. Ideally,
# common_timezones should be populated from zone.tab at runtime,
# but I'm hesitant to pay the startup cost as loading the list
# on demand whilst remaining backwards compatible seems
# difficult.
self.assertTrue('Europe/Bratislava' in pytz.common_timezones)
self.assertTrue('Europe/Bratislava' in pytz.common_timezones_set)
def test_us_eastern(self):
self.assertTrue('US/Eastern' in pytz.common_timezones)
self.assertTrue('US/Eastern' in pytz.common_timezones_set)
def test_belfast(self):
# Belfast uses London time.
self.assertTrue('Europe/Belfast' in pytz.all_timezones_set)
self.assertFalse('Europe/Belfast' in pytz.common_timezones)
self.assertFalse('Europe/Belfast' in pytz.common_timezones_set)
class ZoneCaseInsensitivityTestCase(unittest.TestCase):
def test_lower_case_timezone_constructor_arg(self):
for tz in pytz.all_timezones_set:
from_lower = pytz.timezone(tz.lower())
from_passed = pytz.timezone(tz)
self.assertEqual(from_lower,
from_passed,
"arg '%s' and arg '%s' produce different "
"timezone objects" % (
from_lower, from_passed))
class BaseTzInfoTestCase:
'''Ensure UTC, StaticTzInfo and DstTzInfo work consistently.
These tests are run for each type of tzinfo.
'''
tz = None # override
tz_class = None # override
def test_expectedclass(self):
self.assertTrue(isinstance(self.tz, self.tz_class))
def test_fromutc(self):
# naive datetime.
dt1 = datetime(2011, 10, 31)
# localized datetime, same timezone.
dt2 = self.tz.localize(dt1)
# Both should give the same results. Note that the standard
# Python tzinfo.fromutc() only supports the second.
for dt in [dt1, dt2]:
loc_dt = self.tz.fromutc(dt)
loc_dt2 = pytz.utc.localize(dt1).astimezone(self.tz)
self.assertEqual(loc_dt, loc_dt2)
# localized datetime, different timezone.
new_tz = pytz.timezone('Europe/Paris')
self.assertTrue(self.tz is not new_tz)
dt3 = new_tz.localize(dt1)
self.assertRaises(ValueError, self.tz.fromutc, dt3)
def test_normalize(self):
other_tz = pytz.timezone('Europe/Paris')
self.assertTrue(self.tz is not other_tz)
dt = datetime(2012, 3, 26, 12, 0)
other_dt = other_tz.localize(dt)
local_dt = self.tz.normalize(other_dt)
self.assertTrue(local_dt.tzinfo is not other_dt.tzinfo)
self.assertNotEqual(
local_dt.replace(tzinfo=None), other_dt.replace(tzinfo=None))
def test_astimezone(self):
other_tz = pytz.timezone('Europe/Paris')
self.assertTrue(self.tz is not other_tz)
dt = datetime(2012, 3, 26, 12, 0)
other_dt = other_tz.localize(dt)
local_dt = other_dt.astimezone(self.tz)
self.assertTrue(local_dt.tzinfo is not other_dt.tzinfo)
self.assertNotEqual(
local_dt.replace(tzinfo=None), other_dt.replace(tzinfo=None))
class OptimizedUTCTestCase(unittest.TestCase, BaseTzInfoTestCase):
tz = pytz.utc
tz_class = tz.__class__
class LegacyUTCTestCase(unittest.TestCase, BaseTzInfoTestCase):
# Deprecated timezone, but useful for comparison tests.
tz = pytz.timezone('Etc/UTC')
tz_class = StaticTzInfo
class StaticTzInfoTestCase(unittest.TestCase, BaseTzInfoTestCase):
tz = pytz.timezone('GMT')
tz_class = StaticTzInfo
class DstTzInfoTestCase(unittest.TestCase, BaseTzInfoTestCase):
tz = pytz.timezone('Australia/Melbourne')
tz_class = DstTzInfo
def test_suite():
suite = unittest.TestSuite()
suite.addTest(doctest.DocTestSuite('pytz'))
suite.addTest(doctest.DocTestSuite('pytz.tzinfo'))
suite.addTest(doctest.DocTestSuite('pytz.exceptions'))
import test_tzinfo
suite.addTest(unittest.defaultTestLoader.loadTestsFromModule(test_tzinfo))
return suite
if __name__ == '__main__':
warnings.simplefilter("error") # Warnings should be fatal in tests.
unittest.main(defaultTest='test_suite')

@ -1,4 +1,3 @@
#!/usr/bin/env python
'''
$Id: tzfile.py,v 1.8 2004/06/03 00:15:24 zenzen Exp $
'''

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -6,6 +6,10 @@
# NIST format leap-seconds.list file, which can be copied from
# <ftp://ftp.nist.gov/pub/time/leap-seconds.list>
# or <ftp://ftp.boulder.nist.gov/pub/time/leap-seconds.list>.
# The NIST file is used instead of its IERS upstream counterpart
# <https://hpiers.obspm.fr/iers/bul/bulc/ntp/leap-seconds.list>
# because under US law the NIST file is public domain
# whereas the IERS file's copyright and license status is unclear.
# For more about leap-seconds.list, please see
# The NTP Timescale and Leap Seconds
# <https://www.eecis.udel.edu/~mills/leap.html>.
@ -64,9 +68,15 @@ Leap 2012 Jun 30 23:59:60 + S
Leap 2015 Jun 30 23:59:60 + S
Leap 2016 Dec 31 23:59:60 + S
# UTC timestamp when this leap second list expires.
# Any additional leap seconds will come after this.
# This Expires line is commented out for now,
# so that pre-2020a zic implementations do not reject this file.
#Expires 2021 Dec 28 00:00:00
# POSIX timestamps for the data in this file:
#updated 1467936000 (2016-07-08 00:00:00 UTC)
#expires 1593302400 (2020-06-28 00:00:00 UTC)
#expires 1640649600 (2021-12-28 00:00:00 UTC)
# Updated through IERS Bulletin C58
# File expires on: 28 June 2020
# Updated through IERS Bulletin C61
# File expires on: 28 December 2021

Binary file not shown.

@ -1,4 +1,4 @@
# version unknown
# version unknown-dirty
# 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 -
@ -22,7 +22,7 @@ R d 1978 o - Mar 24 1 1 S
R d 1978 o - S 22 3 0 -
R d 1980 o - Ap 25 0 1 S
R d 1980 o - O 31 2 0 -
Z Africa/Algiers 0:12:12 - LMT 1891 Mar 15 0:1
Z Africa/Algiers 0:12:12 - LMT 1891 Mar 16
0:9:21 - PMT 1911 Mar 11
0 d WE%sT 1940 F 25 2
1 d CE%sT 1946 O 7
@ -86,17 +86,24 @@ R K 2014 o - Jul 31 24 1 S
R K 2014 o - S lastTh 24 0 -
Z Africa/Cairo 2:5:9 - LMT 1900 O
2 K EE%sT
R GH 1920 1942 - S 1 0 0:20 -
R GH 1920 1942 - D 31 0 0 -
Z Africa/Accra -0:0:52 - LMT 1918
0 GH GMT/+0020
R GH 1919 o - N 24 0 0:20 +0020
R GH 1920 1942 - Ja 1 2 0 GMT
R GH 1920 1939 - S 1 2 0:20 +0020
R GH 1940 1941 - May 1 2 0:20 +0020
R GH 1950 1955 - S 1 2 0:30 +0030
R GH 1951 1956 - Ja 1 2 0 GMT
Z Africa/Accra -0:0:52 - LMT 1915 N 2
0 GH %s 1942 F 8
0:30 - +0030 1946 Ja 6
0 GH %s
Z Africa/Bissau -1:2:20 - LMT 1912 Ja 1 1u
-1 - -01 1975
0 - GMT
Z Africa/Nairobi 2:27:16 - LMT 1928 Jul
3 - EAT 1930
2:30 - +0230 1940
2:45 - +0245 1960
Z Africa/Nairobi 2:27:16 - LMT 1908 May
2:30 - +0230 1928 Jun 30 24
3 - EAT 1930 Ja 4 24
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
@ -187,13 +194,13 @@ R M 2018 o - Jun 17 2 1 -
R M 2019 o - May 5 3 -1 -
R M 2019 o - Jun 9 2 0 -
R M 2020 o - Ap 19 3 -1 -
R M 2020 o - May 24 2 0 -
R M 2020 o - May 31 2 0 -
R M 2021 o - Ap 11 3 -1 -
R M 2021 o - May 16 2 0 -
R M 2022 o - Mar 27 3 -1 -
R M 2022 o - May 8 2 0 -
R M 2023 o - Mar 19 3 -1 -
R M 2023 o - Ap 23 2 0 -
R M 2023 o - Ap 30 2 0 -
R M 2024 o - Mar 10 3 -1 -
R M 2024 o - Ap 14 2 0 -
R M 2025 o - F 23 3 -1 -
@ -203,13 +210,13 @@ R M 2026 o - Mar 22 2 0 -
R M 2027 o - F 7 3 -1 -
R M 2027 o - Mar 14 2 0 -
R M 2028 o - Ja 23 3 -1 -
R M 2028 o - F 27 2 0 -
R M 2028 o - Mar 5 2 0 -
R M 2029 o - Ja 14 3 -1 -
R M 2029 o - F 18 2 0 -
R M 2029 o - D 30 3 -1 -
R M 2030 o - F 10 2 0 -
R M 2030 o - D 22 3 -1 -
R M 2031 o - Ja 26 2 0 -
R M 2031 o - F 2 2 0 -
R M 2031 o - D 14 3 -1 -
R M 2032 o - Ja 18 2 0 -
R M 2032 o - N 28 3 -1 -
@ -219,13 +226,13 @@ R M 2033 o - D 25 2 0 -
R M 2034 o - N 5 3 -1 -
R M 2034 o - D 17 2 0 -
R M 2035 o - O 28 3 -1 -
R M 2035 o - D 2 2 0 -
R M 2035 o - D 9 2 0 -
R M 2036 o - O 19 3 -1 -
R M 2036 o - N 23 2 0 -
R M 2037 o - O 4 3 -1 -
R M 2037 o - N 15 2 0 -
R M 2038 o - S 26 3 -1 -
R M 2038 o - O 31 2 0 -
R M 2038 o - N 7 2 0 -
R M 2039 o - S 18 3 -1 -
R M 2039 o - O 23 2 0 -
R M 2040 o - S 2 3 -1 -
@ -235,13 +242,13 @@ R M 2041 o - S 29 2 0 -
R M 2042 o - Au 10 3 -1 -
R M 2042 o - S 21 2 0 -
R M 2043 o - Au 2 3 -1 -
R M 2043 o - S 6 2 0 -
R M 2043 o - S 13 2 0 -
R M 2044 o - Jul 24 3 -1 -
R M 2044 o - Au 28 2 0 -
R M 2045 o - Jul 9 3 -1 -
R M 2045 o - Au 20 2 0 -
R M 2046 o - Jul 1 3 -1 -
R M 2046 o - Au 5 2 0 -
R M 2046 o - Au 12 2 0 -
R M 2047 o - Jun 23 3 -1 -
R M 2047 o - Jul 28 2 0 -
R M 2048 o - Jun 7 3 -1 -
@ -251,13 +258,13 @@ R M 2049 o - Jul 4 2 0 -
R M 2050 o - May 15 3 -1 -
R M 2050 o - Jun 26 2 0 -
R M 2051 o - May 7 3 -1 -
R M 2051 o - Jun 11 2 0 -
R M 2051 o - Jun 18 2 0 -
R M 2052 o - Ap 28 3 -1 -
R M 2052 o - Jun 2 2 0 -
R M 2053 o - Ap 13 3 -1 -
R M 2053 o - May 25 2 0 -
R M 2054 o - Ap 5 3 -1 -
R M 2054 o - May 10 2 0 -
R M 2054 o - May 17 2 0 -
R M 2055 o - Mar 28 3 -1 -
R M 2055 o - May 2 2 0 -
R M 2056 o - Mar 12 3 -1 -
@ -267,65 +274,65 @@ R M 2057 o - Ap 8 2 0 -
R M 2058 o - F 17 3 -1 -
R M 2058 o - Mar 31 2 0 -
R M 2059 o - F 9 3 -1 -
R M 2059 o - Mar 16 2 0 -
R M 2059 o - Mar 23 2 0 -
R M 2060 o - F 1 3 -1 -
R M 2060 o - Mar 7 2 0 -
R M 2061 o - Ja 16 3 -1 -
R M 2061 o - F 27 2 0 -
R M 2062 o - Ja 8 3 -1 -
R M 2062 o - F 12 2 0 -
R M 2062 o - F 19 2 0 -
R M 2062 o - D 31 3 -1 -
R M 2063 o - F 4 2 0 -
R M 2063 o - D 16 3 -1 -
R M 2064 o - Ja 20 2 0 -
R M 2064 o - Ja 27 2 0 -
R M 2064 o - D 7 3 -1 -
R M 2065 o - Ja 11 2 0 -
R M 2065 o - N 22 3 -1 -
R M 2066 o - Ja 3 2 0 -
R M 2066 o - N 14 3 -1 -
R M 2066 o - D 19 2 0 -
R M 2066 o - D 26 2 0 -
R M 2067 o - N 6 3 -1 -
R M 2067 o - D 11 2 0 -
R M 2068 o - O 21 3 -1 -
R M 2068 o - D 2 2 0 -
R M 2069 o - O 13 3 -1 -
R M 2069 o - N 17 2 0 -
R M 2069 o - N 24 2 0 -
R M 2070 o - O 5 3 -1 -
R M 2070 o - N 9 2 0 -
R M 2071 o - S 20 3 -1 -
R M 2071 o - O 25 2 0 -
R M 2071 o - N 1 2 0 -
R M 2072 o - S 11 3 -1 -
R M 2072 o - O 16 2 0 -
R M 2073 o - Au 27 3 -1 -
R M 2073 o - O 8 2 0 -
R M 2074 o - Au 19 3 -1 -
R M 2074 o - S 23 2 0 -
R M 2074 o - S 30 2 0 -
R M 2075 o - Au 11 3 -1 -
R M 2075 o - S 15 2 0 -
R M 2076 o - Jul 26 3 -1 -
R M 2076 o - S 6 2 0 -
R M 2077 o - Jul 18 3 -1 -
R M 2077 o - Au 22 2 0 -
R M 2077 o - Au 29 2 0 -
R M 2078 o - Jul 10 3 -1 -
R M 2078 o - Au 14 2 0 -
R M 2079 o - Jun 25 3 -1 -
R M 2079 o - Jul 30 2 0 -
R M 2079 o - Au 6 2 0 -
R M 2080 o - Jun 16 3 -1 -
R M 2080 o - Jul 21 2 0 -
R M 2081 o - Jun 1 3 -1 -
R M 2081 o - Jul 13 2 0 -
R M 2082 o - May 24 3 -1 -
R M 2082 o - Jun 28 2 0 -
R M 2082 o - Jul 5 2 0 -
R M 2083 o - May 16 3 -1 -
R M 2083 o - Jun 20 2 0 -
R M 2084 o - Ap 30 3 -1 -
R M 2084 o - Jun 11 2 0 -
R M 2085 o - Ap 22 3 -1 -
R M 2085 o - May 27 2 0 -
R M 2085 o - Jun 3 2 0 -
R M 2086 o - Ap 14 3 -1 -
R M 2086 o - May 19 2 0 -
R M 2087 o - Mar 30 3 -1 -
R M 2087 o - May 4 2 0 -
R M 2087 o - May 11 2 0 -
Z Africa/Casablanca -0:30:20 - LMT 1913 O 26
0 M +00/+01 1984 Mar 16
1 - +01 1986
@ -353,7 +360,10 @@ Z Africa/Windhoek 1:8:24 - LMT 1892 F 8
2 1 SAST 1943 Mar 21 2
2 - SAST 1990 Mar 21
2 NA %s
Z Africa/Lagos 0:13:36 - LMT 1919 S
Z Africa/Lagos 0:13:35 - LMT 1905 Jul
0 - GMT 1908 Jul
0:13:35 - LMT 1914
0:30 - +0030 1919 S
1 - WAT
L Africa/Lagos Africa/Bangui
L Africa/Lagos Africa/Brazzaville
@ -371,7 +381,7 @@ Z Africa/Sao_Tome 0:26:56 - LMT 1884
0 - GMT 2018 Ja 1 1
1 - WAT 2019 Ja 1 2
0 - GMT
Z Indian/Mahe 3:41:48 - LMT 1906 Jun
Z Indian/Mahe 3:41:48 - LMT 1907
4 - +04
R SA 1942 1943 - S Su>=15 2 1 -
R SA 1943 1944 - Mar Su>=15 2 0 -
@ -390,7 +400,8 @@ Z Africa/Khartoum 2:10:8 - LMT 1931
2 - CAT
Z Africa/Juba 2:6:28 - LMT 1931
2 SD CA%sT 2000 Ja 15 12
3 - EAT
3 - EAT 2021 F
2 - CAT
R n 1939 o - Ap 15 23s 1 S
R n 1939 o - N 18 23s 0 -
R n 1940 o - F 25 23s 1 S
@ -426,7 +437,12 @@ Z Antarctica/Casey 0 - -00 1969
11 - +11 2012 F 21 17u
8 - +08 2016 O 22
11 - +11 2018 Mar 11 4
8 - +08
8 - +08 2018 O 7 4
11 - +11 2019 Mar 17 3
8 - +08 2019 O 4 3
11 - +11 2020 Mar 8 3
8 - +08 2020 O 4 0:1
11 - +11
Z Antarctica/Davis 0 - -00 1957 Ja 13
7 - +07 1964 N
0 - -00 1969 F
@ -498,6 +514,8 @@ Z Asia/Yangon 6:24:47 - LMT 1880
6:30 - +0630 1942 May
9 - +09 1945 May 3
6:30 - +0630
R Sh 1919 o - Ap 12 24 1 D
R Sh 1919 o - S 30 24 0 S
R Sh 1940 o - Jun 1 0 1 D
R Sh 1940 o - O 12 24 0 S
R Sh 1941 o - Mar 15 0 1 D
@ -775,68 +793,66 @@ Z Asia/Baghdad 2:57:40 - LMT 1890
2:57:36 - BMT 1918
3 - +03 1982 May
3 IQ +03/+04
R Z 1940 o - Jun 1 0 1 D
R Z 1942 1944 - N 1 0 0 S
R Z 1943 o - Ap 1 2 1 D
R Z 1944 o - Ap 1 0 1 D
R Z 1945 o - Ap 16 0 1 D
R Z 1945 o - N 1 2 0 S
R Z 1946 o - Ap 16 2 1 D
R Z 1946 o - N 1 0 0 S
R Z 1948 o - May 23 0 2 DD
R Z 1948 o - S 1 0 1 D
R Z 1948 1949 - N 1 2 0 S
R Z 1949 o - May 1 0 1 D
R Z 1950 o - Ap 16 0 1 D
R Z 1950 o - S 15 3 0 S
R Z 1951 o - Ap 1 0 1 D
R Z 1951 o - N 11 3 0 S
R Z 1952 o - Ap 20 2 1 D
R Z 1952 o - O 19 3 0 S
R Z 1953 o - Ap 12 2 1 D
R Z 1953 o - S 13 3 0 S
R Z 1954 o - Jun 13 0 1 D
R Z 1954 o - S 12 0 0 S
R Z 1955 o - Jun 11 2 1 D
R Z 1955 o - S 11 0 0 S
R Z 1956 o - Jun 3 0 1 D
R Z 1956 o - S 30 3 0 S
R Z 1957 o - Ap 29 2 1 D
R Z 1957 o - S 22 0 0 S
R Z 1974 o - Jul 7 0 1 D
R Z 1974 o - O 13 0 0 S
R Z 1975 o - Ap 20 0 1 D
R Z 1975 o - Au 31 0 0 S
R Z 1980 o - Au 2 0 1 D
R Z 1980 o - S 13 1 0 S
R Z 1984 o - May 5 0 1 D
R Z 1984 o - Au 25 1 0 S
R Z 1985 o - Ap 14 0 1 D
R Z 1985 o - S 15 0 0 S
R Z 1986 o - May 18 0 1 D
R Z 1986 o - S 7 0 0 S
R Z 1987 o - Ap 15 0 1 D
R Z 1987 o - S 13 0 0 S
R Z 1988 o - Ap 10 0 1 D
R Z 1988 o - S 4 0 0 S
R Z 1989 o - Ap 30 0 1 D
R Z 1989 o - S 3 0 0 S
R Z 1990 o - Mar 25 0 1 D
R Z 1990 o - Au 26 0 0 S
R Z 1991 o - Mar 24 0 1 D
R Z 1991 o - S 1 0 0 S
R Z 1992 o - Mar 29 0 1 D
R Z 1992 o - S 6 0 0 S
R Z 1940 o - May 31 24u 1 D
R Z 1940 o - S 30 24u 0 S
R Z 1940 o - N 16 24u 1 D
R Z 1942 1946 - O 31 24u 0 S
R Z 1943 1944 - Mar 31 24u 1 D
R Z 1945 1946 - Ap 15 24u 1 D
R Z 1948 o - May 22 24u 2 DD
R Z 1948 o - Au 31 24u 1 D
R Z 1948 1949 - O 31 24u 0 S
R Z 1949 o - Ap 30 24u 1 D
R Z 1950 o - Ap 15 24u 1 D
R Z 1950 o - S 14 24u 0 S
R Z 1951 o - Mar 31 24u 1 D
R Z 1951 o - N 10 24u 0 S
R Z 1952 o - Ap 19 24u 1 D
R Z 1952 o - O 18 24u 0 S
R Z 1953 o - Ap 11 24u 1 D
R Z 1953 o - S 12 24u 0 S
R Z 1954 o - Jun 12 24u 1 D
R Z 1954 o - S 11 24u 0 S
R Z 1955 o - Jun 11 24u 1 D
R Z 1955 o - S 10 24u 0 S
R Z 1956 o - Jun 2 24u 1 D
R Z 1956 o - S 29 24u 0 S
R Z 1957 o - Ap 27 24u 1 D
R Z 1957 o - S 21 24u 0 S
R Z 1974 o - Jul 6 24 1 D
R Z 1974 o - O 12 24 0 S
R Z 1975 o - Ap 19 24 1 D
R Z 1975 o - Au 30 24 0 S
R Z 1980 o - Au 2 24s 1 D
R Z 1980 o - S 13 24s 0 S
R Z 1984 o - May 5 24s 1 D
R Z 1984 o - Au 25 24s 0 S
R Z 1985 o - Ap 13 24 1 D
R Z 1985 o - Au 31 24 0 S
R Z 1986 o - May 17 24 1 D
R Z 1986 o - S 6 24 0 S
R Z 1987 o - Ap 14 24 1 D
R Z 1987 o - S 12 24 0 S
R Z 1988 o - Ap 9 24 1 D
R Z 1988 o - S 3 24 0 S
R Z 1989 o - Ap 29 24 1 D
R Z 1989 o - S 2 24 0 S
R Z 1990 o - Mar 24 24 1 D
R Z 1990 o - Au 25 24 0 S
R Z 1991 o - Mar 23 24 1 D
R Z 1991 o - Au 31 24 0 S
R Z 1992 o - Mar 28 24 1 D
R Z 1992 o - S 5 24 0 S
R Z 1993 o - Ap 2 0 1 D
R Z 1993 o - S 5 0 0 S
R Z 1994 o - Ap 1 0 1 D
R Z 1994 o - Au 28 0 0 S
R Z 1995 o - Mar 31 0 1 D
R Z 1995 o - S 3 0 0 S
R Z 1996 o - Mar 15 0 1 D
R Z 1996 o - S 16 0 0 S
R Z 1997 o - Mar 21 0 1 D
R Z 1997 o - S 14 0 0 S
R Z 1996 o - Mar 14 24 1 D
R Z 1996 o - S 15 24 0 S
R Z 1997 o - Mar 20 24 1 D
R Z 1997 o - S 13 24 0 S
R Z 1998 o - Mar 20 0 1 D
R Z 1998 o - S 6 0 0 S
R Z 1999 o - Ap 2 2 1 D
@ -1089,10 +1105,10 @@ R P 2004 o - O 1 1 0 -
R P 2005 o - O 4 2 0 -
R P 2006 2007 - Ap 1 0 1 S
R P 2006 o - S 22 0 0 -
R P 2007 o - S Th>=8 2 0 -
R P 2007 o - S 13 2 0 -
R P 2008 2009 - Mar lastF 0 1 S
R P 2008 o - S 1 0 0 -
R P 2009 o - S F>=1 1 0 -
R P 2009 o - S 4 1 0 -
R P 2010 o - Mar 26 0 1 S
R P 2010 o - Au 11 0 0 -
R P 2011 o - Ap 1 0:1 1 S
@ -1101,12 +1117,16 @@ R P 2011 o - Au 30 0 1 S
R P 2011 o - S 30 0 0 -
R P 2012 2014 - Mar lastTh 24 1 S
R P 2012 o - S 21 1 0 -
R P 2013 o - S F>=21 0 0 -
R P 2014 2015 - O F>=21 0 0 -
R P 2015 o - Mar lastF 24 1 S
R P 2013 o - S 27 0 0 -
R P 2014 o - O 24 0 0 -
R P 2015 o - Mar 28 0 1 S
R P 2015 o - O 23 1 0 -
R P 2016 2018 - Mar Sa>=24 1 1 S
R P 2016 ma - O lastSa 1 0 -
R P 2019 ma - Mar lastF 0 1 S
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 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
@ -1245,13 +1265,13 @@ Z Asia/Ho_Chi_Minh 7:6:40 - LMT 1906 Jul
7 - +07 1959 D 31 23
8 - +08 1975 Jun 13
7 - +07
R AU 1917 o - Ja 1 0:1 1 D
R AU 1917 o - Mar 25 2 0 S
R AU 1942 o - Ja 1 2 1 D
R AU 1942 o - Mar 29 2 0 S
R AU 1942 o - S 27 2 1 D
R AU 1943 1944 - Mar lastSu 2 0 S
R AU 1943 o - O 3 2 1 D
R AU 1917 o - Ja 1 2s 1 D
R AU 1917 o - Mar lastSu 2s 0 S
R AU 1942 o - Ja 1 2s 1 D
R AU 1942 o - Mar lastSu 2s 0 S
R AU 1942 o - S 27 2s 1 D
R AU 1943 1944 - Mar lastSu 2s 0 S
R AU 1943 o - O 3 2s 1 D
Z Australia/Darwin 8:43:20 - LMT 1895 F
9 - ACST 1899 May
9:30 AU AC%sT
@ -1302,8 +1322,12 @@ Z Australia/Adelaide 9:14:20 - LMT 1895 F
9 - ACST 1899 May
9:30 AU AC%sT 1971
9:30 AS AC%sT
R AT 1916 o - O Su>=1 2s 1 D
R AT 1917 o - Mar lastSu 2s 0 S
R AT 1917 1918 - O Su>=22 2s 1 D
R AT 1918 1919 - Mar Su>=1 2s 0 S
R AT 1967 o - O Su>=1 2s 1 D
R AT 1968 o - Mar lastSu 2s 0 S
R AT 1968 o - Mar Su>=29 2s 0 S
R AT 1968 1985 - O lastSu 2s 1 D
R AT 1969 1971 - Mar Su>=8 2s 0 S
R AT 1972 o - F lastSu 2s 0 S
@ -1322,15 +1346,9 @@ R AT 2006 o - Ap Su>=1 2s 0 S
R AT 2007 o - Mar lastSu 2s 0 S
R AT 2008 ma - Ap Su>=1 2s 0 S
Z Australia/Hobart 9:49:16 - LMT 1895 S
10 - AEST 1916 O 1 2
10 1 AEDT 1917 F
10 AT AE%sT 1919 O 24
10 AU AE%sT 1967
10 AT AE%sT
Z Australia/Currie 9:35:28 - LMT 1895 S
10 - AEST 1916 O 1 2
10 1 AEDT 1917 F
10 AU AE%sT 1971 Jul
10 AT AE%sT
R AV 1971 1985 - O lastSu 2s 1 D
R AV 1972 o - F lastSu 2s 0 S
R AV 1973 1985 - Mar Su>=1 2s 0 S
@ -1397,8 +1415,9 @@ Z Antarctica/Macquarie 0 - -00 1899 N
10 AU AE%sT 1919 Ap 1 0s
0 - -00 1948 Mar 25
10 AU AE%sT 1967
10 AT AE%sT 2010 Ap 4 3
11 - +11
10 AT AE%sT 2010
10 1 AEDT 2011
10 AT AE%sT
Z Indian/Christmas 7:2:52 - LMT 1895 F
7 - +07
Z Indian/Cocos 6:27:40 - LMT 1900
@ -1413,7 +1432,9 @@ 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 ma - Ja Su>=12 3 0 -
R FJ 2019 ma - N Su>=8 2 1 -
R FJ 2019 o - N Su>=8 2 1 -
R FJ 2020 o - D 20 2 1 -
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
@ -1601,12 +1622,12 @@ Z Pacific/Funafuti 11:56:52 - LMT 1901
12 - +12
Z Pacific/Wake 11:6:28 - LMT 1901
12 - +12
R VU 1983 o - S 25 0 1 -
R VU 1984 1991 - Mar Su>=23 0 0 -
R VU 1984 o - O 23 0 1 -
R VU 1985 1991 - S Su>=23 0 1 -
R VU 1992 1993 - Ja Su>=23 0 0 -
R VU 1992 o - O Su>=23 0 1 -
R VU 1973 o - D 22 12u 1 -
R VU 1974 o - Mar 30 12u 0 -
R VU 1983 1991 - S Sa>=22 24 1 -
R VU 1984 1991 - Mar Sa>=22 24 0 -
R VU 1992 1993 - Ja Sa>=22 24 0 -
R VU 1992 o - O Sa>=22 24 1 -
Z Pacific/Efate 11:13:16 - LMT 1912 Ja 13
11 VU +11/+12
Z Pacific/Wallis 12:15:20 - LMT 1901
@ -1921,7 +1942,7 @@ Z America/Scoresbysund -1:27:52 - LMT 1916 Jul 28
-2 - -02 1980 Ap 6 2
-2 c -02/-01 1981 Mar 29
-1 E -01/+00
Z America/Godthab -3:26:56 - LMT 1916 Jul 28
Z America/Nuuk -3:26:56 - LMT 1916 Jul 28
-3 - -03 1980 Ap 6 2
-3 E -03/-02
Z America/Thule -4:35:8 - LMT 1916 Jul 28
@ -1990,8 +2011,8 @@ R F 1945 o - Ap 2 2 2 M
R F 1945 o - S 16 3 0 -
R F 1976 o - Mar 28 1 1 S
R F 1976 o - S 26 1 0 -
Z Europe/Paris 0:9:21 - LMT 1891 Mar 15 0:1
0:9:21 - PMT 1911 Mar 11 0:1
Z Europe/Paris 0:9:21 - LMT 1891 Mar 16
0:9:21 - PMT 1911 Mar 11
0 F WE%sT 1940 Jun 14 23
1 c CE%sT 1944 Au 25
0 F WE%sT 1945 S 16 3
@ -2043,29 +2064,30 @@ Z Europe/Athens 1:34:52 - LMT 1895 S 14
1 g CE%sT 1944 Ap 4
2 g EE%sT 1981
2 E EE%sT
R h 1918 o - Ap 1 3 1 S
R h 1918 o - S 16 3 0 -
R h 1919 o - Ap 15 3 1 S
R h 1919 o - N 24 3 0 -
R h 1918 1919 - Ap 15 2 1 S
R h 1918 1920 - S M>=15 3 0 -
R h 1920 o - Ap 5 2 1 S
R h 1945 o - May 1 23 1 S
R h 1945 o - N 1 0 0 -
R h 1945 o - N 1 1 0 -
R h 1946 o - Mar 31 2s 1 S
R h 1946 1949 - O Su>=1 2s 0 -
R h 1946 o - O 7 2 0 -
R h 1947 1949 - Ap Su>=4 2s 1 S
R h 1950 o - Ap 17 2s 1 S
R h 1950 o - O 23 2s 0 -
R h 1954 1955 - May 23 0 1 S
R h 1954 1955 - O 3 0 0 -
R h 1956 o - Jun Su>=1 0 1 S
R h 1956 o - S lastSu 0 0 -
R h 1957 o - Jun Su>=1 1 1 S
R h 1957 o - S lastSu 3 0 -
R h 1980 o - Ap 6 1 1 S
Z Europe/Budapest 1:16:20 - LMT 1890 O
R h 1947 1949 - O Su>=1 2s 0 -
R h 1954 o - May 23 0 1 S
R h 1954 o - O 3 0 0 -
R h 1955 o - May 22 2 1 S
R h 1955 o - O 2 3 0 -
R h 1956 1957 - Jun Su>=1 2 1 S
R h 1956 1957 - S lastSu 3 0 -
R h 1980 o - Ap 6 0 1 S
R h 1980 o - S 28 1 0 -
R h 1981 1983 - Mar lastSu 0 1 S
R h 1981 1983 - S lastSu 1 0 -
Z Europe/Budapest 1:16:20 - LMT 1890 N
1 c CE%sT 1918
1 h CE%sT 1941 Ap 8
1 h CE%sT 1941 Ap 7 23
1 c CE%sT 1945
1 h CE%sT 1980 S 28 2s
1 h CE%sT 1984
1 E CE%sT
R w 1917 1919 - F 19 23 1 -
R w 1917 o - O 21 1 0 -
@ -2221,8 +2243,8 @@ Z Europe/Chisinau 1:55:20 - LMT 1880
2 R EE%sT 1992
2 e EE%sT 1997
2 MD EE%sT
Z Europe/Monaco 0:29:32 - LMT 1891 Mar 15
0:9:21 - PMT 1911 Mar 11
Z Europe/Monaco 0:29:32 - LMT 1892 Jun
0:9:21 - PMT 1911 Mar 29
0 F WE%sT 1945 S 16 3
1 F CE%sT 1977
1 E CE%sT
@ -2448,7 +2470,8 @@ Z Europe/Volgograd 2:57:40 - LMT 1920 Ja 3
3 R +03/+04 2011 Mar 27 2s
4 - +04 2014 O 26 2s
3 - +03 2018 O 28 2s
4 - +04
4 - +04 2020 D 27 2s
3 - +03
Z Europe/Saratov 3:4:18 - LMT 1919 Jul 1 0u
3 - +03 1930 Jun 21
4 R +04/+05 1988 Mar 27 2s
@ -3411,11 +3434,13 @@ Z America/Inuvik 0 - -00 1953
Z America/Whitehorse -9:0:12 - LMT 1900 Au 20
-9 Y Y%sT 1967 May 28
-8 Y P%sT 1980
-8 C P%sT
-8 C P%sT 2020 N
-7 - MST
Z America/Dawson -9:17:40 - LMT 1900 Au 20
-9 Y Y%sT 1973 O 28
-8 Y P%sT 1980
-8 C P%sT
-8 C P%sT 2020 N
-7 - MST
R m 1939 o - F 5 0 1 D
R m 1939 o - Jun 25 0 0 S
R m 1940 o - D 9 0 1 D
@ -3529,6 +3554,11 @@ Z America/Tijuana -7:48:4 - LMT 1922 Ja 1 0:11:56
-8 u P%sT 2002 F 20
-8 m P%sT 2010
-8 u P%sT
R BS 1942 o - May 1 24 1 W
R BS 1944 o - D 31 24 0 S
R BS 1945 o - F 1 0 1 W
R BS 1945 o - Au 14 23u 1 P
R BS 1945 o - O 17 24 0 S
R BS 1964 1975 - O lastSu 2 0 S
R BS 1964 1975 - Ap lastSu 2 1 D
Z America/Nassau -5:9:30 - LMT 1912 Mar 2
@ -3542,16 +3572,38 @@ R BB 1980 o - S 25 2 0 S
Z America/Barbados -3:58:29 - LMT 1924
-3:58:29 - BMT 1932
-4 BB A%sT
R BZ 1918 1942 - O Su>=2 0 0:30 -0530
R BZ 1919 1943 - F Su>=9 0 0 CST
R BZ 1918 1941 - O Sa>=1 24 0:30 -0530
R BZ 1919 1942 - F Sa>=8 24 0 CST
R BZ 1942 o - Jun 27 24 1 CWT
R BZ 1945 o - Au 14 23u 1 CPT
R BZ 1945 o - D 15 24 0 CST
R BZ 1947 1967 - O Sa>=1 24 0:30 -0530
R BZ 1948 1968 - F Sa>=8 24 0 CST
R BZ 1973 o - D 5 0 1 CDT
R BZ 1974 o - F 9 0 0 CST
R BZ 1982 o - D 18 0 1 CDT
R BZ 1983 o - F 12 0 0 CST
Z America/Belize -5:52:48 - LMT 1912 Ap
-6 BZ %s
Z Atlantic/Bermuda -4:19:18 - LMT 1930 Ja 1 2
-4 - AST 1974 Ap 28 2
R Be 1917 o - Ap 5 24 1 -
R Be 1917 o - S 30 24 0 -
R Be 1918 o - Ap 13 24 1 -
R Be 1918 o - S 15 24 0 S
R Be 1942 o - Ja 11 2 1 D
R Be 1942 o - O 18 2 0 S
R Be 1943 o - Mar 21 2 1 D
R Be 1943 o - O 31 2 0 S
R Be 1944 1945 - Mar Su>=8 2 1 D
R Be 1944 1945 - N Su>=1 2 0 S
R Be 1947 o - May Su>=15 2 1 D
R Be 1947 o - S Su>=8 2 0 S
R Be 1948 1952 - May Su>=22 2 1 D
R Be 1948 1952 - S Su>=1 2 0 S
R Be 1956 o - May Su>=22 2 1 D
R Be 1956 o - O lastSu 2 0 S
Z Atlantic/Bermuda -4:19:18 - LMT 1890
-4:19:18 Be BMT/BST 1930 Ja 1 2
-4 Be A%sT 1974 Ap 28 2
-4 C A%sT 1976
-4 u A%sT
R CR 1979 1980 - F lastSu 0 1 D
@ -3690,7 +3742,7 @@ Z America/Miquelon -3:44:40 - LMT 1911 May 15
Z America/Grand_Turk -4:44:32 - LMT 1890
-5:7:10 - KMT 1912 F
-5 - EST 1979
-5 u E%sT 2015 N Su>=1 2
-5 u E%sT 2015 Mar 8 2
-4 - AST 2018 Mar 11 3
-5 u E%sT
R A 1930 o - D 1 0 1 -
@ -4294,6 +4346,7 @@ L America/Atikokan America/Coral_Harbour
L America/Argentina/Cordoba America/Cordoba
L America/Tijuana America/Ensenada
L America/Indiana/Indianapolis America/Fort_Wayne
L America/Nuuk America/Godthab
L America/Indiana/Indianapolis America/Indianapolis
L America/Argentina/Jujuy America/Jujuy
L America/Indiana/Knox America/Knox_IN
@ -4325,6 +4378,7 @@ L Atlantic/Faroe Atlantic/Faeroe
L Europe/Oslo Atlantic/Jan_Mayen
L Australia/Sydney Australia/ACT
L Australia/Sydney Australia/Canberra
L Australia/Hobart Australia/Currie
L Australia/Lord_Howe Australia/LHI
L Australia/Sydney Australia/NSW
L Australia/Darwin Australia/North

@ -56,8 +56,7 @@ AS -1416-17042 Pacific/Pago_Pago
AT +4813+01620 Europe/Vienna
AU -3133+15905 Australia/Lord_Howe Lord Howe Island
AU -5430+15857 Antarctica/Macquarie Macquarie Island
AU -4253+14719 Australia/Hobart Tasmania (most areas)
AU -3956+14352 Australia/Currie Tasmania (King Island)
AU -4253+14719 Australia/Hobart Tasmania
AU -3749+14458 Australia/Melbourne Victoria
AU -3352+15113 Australia/Sydney New South Wales (most areas)
AU -3157+14127 Australia/Broken_Hill New South Wales (Yancowinna)
@ -130,9 +129,9 @@ CA +682059-1334300 America/Inuvik Mountain - NT (west)
CA +4906-11631 America/Creston MST - BC (Creston)
CA +5946-12014 America/Dawson_Creek MST - BC (Dawson Cr, Ft St John)
CA +5848-12242 America/Fort_Nelson MST - BC (Ft Nelson)
CA +6043-13503 America/Whitehorse MST - Yukon (east)
CA +6404-13925 America/Dawson MST - Yukon (west)
CA +4916-12307 America/Vancouver Pacific - BC (most areas)
CA +6043-13503 America/Whitehorse Pacific - Yukon (south)
CA +6404-13925 America/Dawson Pacific - Yukon (north)
CC -1210+09655 Indian/Cocos
CD -0418+01518 Africa/Kinshasa Dem. Rep. of Congo (west)
CD -1140+02728 Africa/Lubumbashi Dem. Rep. of Congo (east)
@ -189,7 +188,7 @@ GF +0456-05220 America/Cayenne
GG +492717-0023210 Europe/Guernsey
GH +0533-00013 Africa/Accra
GI +3608-00521 Europe/Gibraltar
GL +6411-05144 America/Godthab Greenland (most areas)
GL +6411-05144 America/Nuuk Greenland (most areas)
GL +7646-01840 America/Danmarkshavn National Park (east coast)
GL +7029-02158 America/Scoresbysund Scoresbysund/Ittoqqortoormiit
GL +7634-06847 America/Thule Thule/Pituffik
@ -335,10 +334,10 @@ RU +554521+0373704 Europe/Moscow MSK+00 - Moscow area
# The obsolescent zone.tab format cannot represent Europe/Simferopol well.
# Put it in RU section and list as UA. See "territorial claims" above.
# Programs should use zone1970.tab instead; see above.
UA +4457+03406 Europe/Simferopol MSK+00 - Crimea
UA +4457+03406 Europe/Simferopol Crimea
RU +5836+04939 Europe/Kirov MSK+00 - Kirov
RU +4844+04425 Europe/Volgograd MSK+00 - Volgograd
RU +4621+04803 Europe/Astrakhan MSK+01 - Astrakhan
RU +4844+04425 Europe/Volgograd MSK+01 - Volgograd
RU +5134+04602 Europe/Saratov MSK+01 - Saratov
RU +5420+04824 Europe/Ulyanovsk MSK+01 - Ulyanovsk
RU +5312+05009 Europe/Samara MSK+01 - Samara, Udmurtia
@ -399,8 +398,8 @@ TV -0831+17913 Pacific/Funafuti
TW +2503+12130 Asia/Taipei
TZ -0648+03917 Africa/Dar_es_Salaam
UA +5026+03031 Europe/Kiev Ukraine (most areas)
UA +4837+02218 Europe/Uzhgorod Ruthenia
UA +4750+03510 Europe/Zaporozhye Zaporozh'ye/Zaporizhia; Lugansk/Luhansk (east)
UA +4837+02218 Europe/Uzhgorod Transcarpathia
UA +4750+03510 Europe/Zaporozhye Zaporozhye and east Lugansk
UG +0019+03225 Africa/Kampala
UM +2813-17722 Pacific/Midway Midway Islands
UM +1917+16637 Pacific/Wake Wake Island

@ -63,8 +63,7 @@ AS,UM -1416-17042 Pacific/Pago_Pago Samoa, Midway
AT +4813+01620 Europe/Vienna
AU -3133+15905 Australia/Lord_Howe Lord Howe Island
AU -5430+15857 Antarctica/Macquarie Macquarie Island
AU -4253+14719 Australia/Hobart Tasmania (most areas)
AU -3956+14352 Australia/Currie Tasmania (King Island)
AU -4253+14719 Australia/Hobart Tasmania
AU -3749+14458 Australia/Melbourne Victoria
AU -3352+15113 Australia/Sydney New South Wales (most areas)
AU -3157+14127 Australia/Broken_Hill New South Wales (Yancowinna)
@ -127,9 +126,9 @@ CA +682059-1334300 America/Inuvik Mountain - NT (west)
CA +4906-11631 America/Creston MST - BC (Creston)
CA +5946-12014 America/Dawson_Creek MST - BC (Dawson Cr, Ft St John)
CA +5848-12242 America/Fort_Nelson MST - BC (Ft Nelson)
CA +6043-13503 America/Whitehorse MST - Yukon (east)
CA +6404-13925 America/Dawson MST - Yukon (west)
CA +4916-12307 America/Vancouver Pacific - BC (most areas)
CA +6043-13503 America/Whitehorse Pacific - Yukon (south)
CA +6404-13925 America/Dawson Pacific - Yukon (north)
CC -1210+09655 Indian/Cocos
CH,DE,LI +4723+00832 Europe/Zurich Swiss time
CI,BF,GM,GN,ML,MR,SH,SL,SN,TG +0519-00402 Africa/Abidjan
@ -173,7 +172,7 @@ GE +4143+04449 Asia/Tbilisi
GF +0456-05220 America/Cayenne
GH +0533-00013 Africa/Accra
GI +3608-00521 Europe/Gibraltar
GL +6411-05144 America/Godthab Greenland (most areas)
GL +6411-05144 America/Nuuk Greenland (most areas)
GL +7646-01840 America/Danmarkshavn National Park (east coast)
GL +7029-02158 America/Scoresbysund Scoresbysund/Ittoqqortoormiit
GL +7634-06847 America/Thule Thule/Pituffik
@ -290,10 +289,10 @@ RS,BA,HR,ME,MK,SI +4450+02030 Europe/Belgrade
RU +5443+02030 Europe/Kaliningrad MSK-01 - Kaliningrad
RU +554521+0373704 Europe/Moscow MSK+00 - Moscow area
# Mention RU and UA alphabetically. See "territorial claims" above.
RU,UA +4457+03406 Europe/Simferopol MSK+00 - Crimea
RU,UA +4457+03406 Europe/Simferopol Crimea
RU +5836+04939 Europe/Kirov MSK+00 - Kirov
RU +4844+04425 Europe/Volgograd MSK+00 - Volgograd
RU +4621+04803 Europe/Astrakhan MSK+01 - Astrakhan
RU +4844+04425 Europe/Volgograd MSK+01 - Volgograd
RU +5134+04602 Europe/Saratov MSK+01 - Saratov
RU +5420+04824 Europe/Ulyanovsk MSK+01 - Ulyanovsk
RU +5312+05009 Europe/Samara MSK+01 - Samara, Udmurtia
@ -341,8 +340,8 @@ TT,AG,AI,BL,DM,GD,GP,KN,LC,MF,MS,VC,VG,VI +1039-06131 America/Port_of_Spain
TV -0831+17913 Pacific/Funafuti
TW +2503+12130 Asia/Taipei
UA +5026+03031 Europe/Kiev Ukraine (most areas)
UA +4837+02218 Europe/Uzhgorod Ruthenia
UA +4750+03510 Europe/Zaporozhye Zaporozh'ye/Zaporizhia; Lugansk/Luhansk (east)
UA +4837+02218 Europe/Uzhgorod Transcarpathia
UA +4750+03510 Europe/Zaporozhye Zaporozhye and east Lugansk
UM +1917+16637 Pacific/Wake Wake Island
US +404251-0740023 America/New_York Eastern (most areas)
US +421953-0830245 America/Detroit Eastern - MI (most areas)

@ -20,7 +20,7 @@ py-pretty=1
pycountry=18.2.23
pyga=2.6.1
pysrt=1.1.1
pytz=2018.4
pytz=2021.1
rarfile=3.0
rebulk=3.0.1
requests=2.18.4

Loading…
Cancel
Save