Varken/lib/DateTime/pytz_support.py
2018-12-02 13:38:37 -06:00

259 lines
12 KiB
Python

##############################################################################
#
# Copyright (c) 2007 Zope Foundation and Contributors.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
from datetime import datetime, timedelta
import pytz
import pytz.reference
from pytz.tzinfo import StaticTzInfo, memorized_timedelta
from .interfaces import DateTimeError
EPOCH = datetime.utcfromtimestamp(0).replace(tzinfo=pytz.utc)
_numeric_timezone_data = {
'GMT': ('GMT', 0, 1, [], '', [(0, 0, 0)], 'GMT\000'),
'GMT+0': ('GMT+0', 0, 1, [], '', [(0, 0, 0)], 'GMT+0000\000'),
'GMT+1': ('GMT+1', 0, 1, [], '', [(3600, 0, 0)], 'GMT+0100\000'),
'GMT+2': ('GMT+2', 0, 1, [], '', [(7200, 0, 0)], 'GMT+0200\000'),
'GMT+3': ('GMT+3', 0, 1, [], '', [(10800, 0, 0)], 'GMT+0300\000'),
'GMT+4': ('GMT+4', 0, 1, [], '', [(14400, 0, 0)], 'GMT+0400\000'),
'GMT+5': ('GMT+5', 0, 1, [], '', [(18000, 0, 0)], 'GMT+0500\000'),
'GMT+6': ('GMT+6', 0, 1, [], '', [(21600, 0, 0)], 'GMT+0600\000'),
'GMT+7': ('GMT+7', 0, 1, [], '', [(25200, 0, 0)], 'GMT+0700\000'),
'GMT+8': ('GMT+8', 0, 1, [], '', [(28800, 0, 0)], 'GMT+0800\000'),
'GMT+9': ('GMT+9', 0, 1, [], '', [(32400, 0, 0)], 'GMT+0900\000'),
'GMT+10': ('GMT+10', 0, 1, [], '', [(36000, 0, 0)], 'GMT+1000\000'),
'GMT+11': ('GMT+11', 0, 1, [], '', [(39600, 0, 0)], 'GMT+1100\000'),
'GMT+12': ('GMT+12', 0, 1, [], '', [(43200, 0, 0)], 'GMT+1200\000'),
'GMT+13': ('GMT+13', 0, 1, [], '', [(46800, 0, 0)], 'GMT+1300\000'),
'GMT-1': ('GMT-1', 0, 1, [], '', [(-3600, 0, 0)], 'GMT-0100\000'),
'GMT-2': ('GMT-2', 0, 1, [], '', [(-7200, 0, 0)], 'GMT-0200\000'),
'GMT-3': ('GMT-3', 0, 1, [], '', [(-10800, 0, 0)], 'GMT-0300\000'),
'GMT-4': ('GMT-4', 0, 1, [], '', [(-14400, 0, 0)], 'GMT-0400\000'),
'GMT-5': ('GMT-5', 0, 1, [], '', [(-18000, 0, 0)], 'GMT-0500\000'),
'GMT-6': ('GMT-6', 0, 1, [], '', [(-21600, 0, 0)], 'GMT-0600\000'),
'GMT-7': ('GMT-7', 0, 1, [], '', [(-25200, 0, 0)], 'GMT-0700\000'),
'GMT-8': ('GMT-8', 0, 1, [], '', [(-28800, 0, 0)], 'GMT-0800\000'),
'GMT-9': ('GMT-9', 0, 1, [], '', [(-32400, 0, 0)], 'GMT-0900\000'),
'GMT-10': ('GMT-10', 0, 1, [], '', [(-36000, 0, 0)], 'GMT-1000\000'),
'GMT-11': ('GMT-11', 0, 1, [], '', [(-39600, 0, 0)], 'GMT-1100\000'),
'GMT-12': ('GMT-12', 0, 1, [], '', [(-43200, 0, 0)], 'GMT-1200\000'),
'GMT+0130': ('GMT+0130', 0, 1, [], '', [(5400, 0, 0)], 'GMT+0130\000'),
'GMT+0230': ('GMT+0230', 0, 1, [], '', [(9000, 0, 0)], 'GMT+0230\000'),
'GMT+0330': ('GMT+0330', 0, 1, [], '', [(12600, 0, 0)], 'GMT+0330\000'),
'GMT+0430': ('GMT+0430', 0, 1, [], '', [(16200, 0, 0)], 'GMT+0430\000'),
'GMT+0530': ('GMT+0530', 0, 1, [], '', [(19800, 0, 0)], 'GMT+0530\000'),
'GMT+0630': ('GMT+0630', 0, 1, [], '', [(23400, 0, 0)], 'GMT+0630\000'),
'GMT+0730': ('GMT+0730', 0, 1, [], '', [(27000, 0, 0)], 'GMT+0730\000'),
'GMT+0830': ('GMT+0830', 0, 1, [], '', [(30600, 0, 0)], 'GMT+0830\000'),
'GMT+0930': ('GMT+0930', 0, 1, [], '', [(34200, 0, 0)], 'GMT+0930\000'),
'GMT+1030': ('GMT+1030', 0, 1, [], '', [(37800, 0, 0)], 'GMT+1030\000'),
'GMT+1130': ('GMT+1130', 0, 1, [], '', [(41400, 0, 0)], 'GMT+1130\000'),
'GMT+1230': ('GMT+1230', 0, 1, [], '', [(45000, 0, 0)], 'GMT+1230\000'),
'GMT-0130': ('GMT-0130', 0, 1, [], '', [(-5400, 0, 0)], 'GMT-0130\000'),
'GMT-0230': ('GMT-0230', 0, 1, [], '', [(-9000, 0, 0)], 'GMT-0230\000'),
'GMT-0330': ('GMT-0330', 0, 1, [], '', [(-12600, 0, 0)], 'GMT-0330\000'),
'GMT-0430': ('GMT-0430', 0, 1, [], '', [(-16200, 0, 0)], 'GMT-0430\000'),
'GMT-0530': ('GMT-0530', 0, 1, [], '', [(-19800, 0, 0)], 'GMT-0530\000'),
'GMT-0630': ('GMT-0630', 0, 1, [], '', [(-23400, 0, 0)], 'GMT-0630\000'),
'GMT-0730': ('GMT-0730', 0, 1, [], '', [(-27000, 0, 0)], 'GMT-0730\000'),
'GMT-0830': ('GMT-0830', 0, 1, [], '', [(-30600, 0, 0)], 'GMT-0830\000'),
'GMT-0930': ('GMT-0930', 0, 1, [], '', [(-34200, 0, 0)], 'GMT-0930\000'),
'GMT-1030': ('GMT-1030', 0, 1, [], '', [(-37800, 0, 0)], 'GMT-1030\000'),
'GMT-1130': ('GMT-1130', 0, 1, [], '', [(-41400, 0, 0)], 'GMT-1130\000'),
'GMT-1230': ('GMT-1230', 0, 1, [], '', [(-45000, 0, 0)], 'GMT-1230\000'),
}
# These are the timezones not in pytz.common_timezones
_old_zlst = [
'AST', 'AT', 'BST', 'BT', 'CCT',
'CET', 'CST', 'Cuba', 'EADT', 'EAST',
'EEST', 'EET', 'EST', 'Egypt', 'FST',
'FWT', 'GB-Eire', 'GMT+0100', 'GMT+0130', 'GMT+0200',
'GMT+0230', 'GMT+0300', 'GMT+0330', 'GMT+0400', 'GMT+0430',
'GMT+0500', 'GMT+0530', 'GMT+0600', 'GMT+0630', 'GMT+0700',
'GMT+0730', 'GMT+0800', 'GMT+0830', 'GMT+0900', 'GMT+0930',
'GMT+1', 'GMT+1000', 'GMT+1030', 'GMT+1100', 'GMT+1130',
'GMT+1200', 'GMT+1230', 'GMT+1300', 'GMT-0100', 'GMT-0130',
'GMT-0200', 'GMT-0300', 'GMT-0400', 'GMT-0500', 'GMT-0600',
'GMT-0630', 'GMT-0700', 'GMT-0730', 'GMT-0800', 'GMT-0830',
'GMT-0900', 'GMT-0930', 'GMT-1000', 'GMT-1030', 'GMT-1100',
'GMT-1130', 'GMT-1200', 'GMT-1230', 'GST', 'Greenwich',
'Hongkong', 'IDLE', 'IDLW', 'Iceland', 'Iran',
'Israel', 'JST', 'Jamaica', 'Japan', 'MEST',
'MET', 'MEWT', 'MST', 'NT', 'NZDT',
'NZST', 'NZT', 'PST', 'Poland', 'SST',
'SWT', 'Singapore', 'Turkey', 'UCT', 'UT',
'Universal', 'WADT', 'WAST', 'WAT', 'WET',
'ZP4', 'ZP5', 'ZP6',
]
_old_zmap = {
'aest': 'GMT+10', 'aedt': 'GMT+11',
'aus eastern standard time': 'GMT+10',
'sydney standard time': 'GMT+10',
'tasmania standard time': 'GMT+10',
'e. australia standard time': 'GMT+10',
'aus central standard time': 'GMT+0930',
'cen. australia standard time': 'GMT+0930',
'w. australia standard time': 'GMT+8',
'central europe standard time': 'GMT+1',
'eastern standard time': 'US/Eastern',
'us eastern standard time': 'US/Eastern',
'central standard time': 'US/Central',
'mountain standard time': 'US/Mountain',
'pacific standard time': 'US/Pacific',
'mst': 'US/Mountain', 'pst': 'US/Pacific',
'cst': 'US/Central', 'est': 'US/Eastern',
'gmt+0000': 'GMT+0', 'gmt+0': 'GMT+0',
'gmt+0100': 'GMT+1', 'gmt+0200': 'GMT+2', 'gmt+0300': 'GMT+3',
'gmt+0400': 'GMT+4', 'gmt+0500': 'GMT+5', 'gmt+0600': 'GMT+6',
'gmt+0700': 'GMT+7', 'gmt+0800': 'GMT+8', 'gmt+0900': 'GMT+9',
'gmt+1000': 'GMT+10', 'gmt+1100': 'GMT+11', 'gmt+1200': 'GMT+12',
'gmt+1300': 'GMT+13',
'gmt-0100': 'GMT-1', 'gmt-0200': 'GMT-2', 'gmt-0300': 'GMT-3',
'gmt-0400': 'GMT-4', 'gmt-0500': 'GMT-5', 'gmt-0600': 'GMT-6',
'gmt-0700': 'GMT-7', 'gmt-0800': 'GMT-8', 'gmt-0900': 'GMT-9',
'gmt-1000': 'GMT-10', 'gmt-1100': 'GMT-11', 'gmt-1200': 'GMT-12',
'gmt+1': 'GMT+1', 'gmt+2': 'GMT+2', 'gmt+3': 'GMT+3',
'gmt+4': 'GMT+4', 'gmt+5': 'GMT+5', 'gmt+6': 'GMT+6',
'gmt+7': 'GMT+7', 'gmt+8': 'GMT+8', 'gmt+9': 'GMT+9',
'gmt+10': 'GMT+10', 'gmt+11': 'GMT+11', 'gmt+12': 'GMT+12',
'gmt+13': 'GMT+13',
'gmt-1': 'GMT-1', 'gmt-2': 'GMT-2', 'gmt-3': 'GMT-3',
'gmt-4': 'GMT-4', 'gmt-5': 'GMT-5', 'gmt-6': 'GMT-6',
'gmt-7': 'GMT-7', 'gmt-8': 'GMT-8', 'gmt-9': 'GMT-9',
'gmt-10': 'GMT-10', 'gmt-11': 'GMT-11', 'gmt-12': 'GMT-12',
'gmt+130': 'GMT+0130', 'gmt+0130': 'GMT+0130',
'gmt+230': 'GMT+0230', 'gmt+0230': 'GMT+0230',
'gmt+330': 'GMT+0330', 'gmt+0330': 'GMT+0330',
'gmt+430': 'GMT+0430', 'gmt+0430': 'GMT+0430',
'gmt+530': 'GMT+0530', 'gmt+0530': 'GMT+0530',
'gmt+630': 'GMT+0630', 'gmt+0630': 'GMT+0630',
'gmt+730': 'GMT+0730', 'gmt+0730': 'GMT+0730',
'gmt+830': 'GMT+0830', 'gmt+0830': 'GMT+0830',
'gmt+930': 'GMT+0930', 'gmt+0930': 'GMT+0930',
'gmt+1030': 'GMT+1030',
'gmt+1130': 'GMT+1130',
'gmt+1230': 'GMT+1230',
'gmt-130': 'GMT-0130', 'gmt-0130': 'GMT-0130',
'gmt-230': 'GMT-0230', 'gmt-0230': 'GMT-0230',
'gmt-330': 'GMT-0330', 'gmt-0330': 'GMT-0330',
'gmt-430': 'GMT-0430', 'gmt-0430': 'GMT-0430',
'gmt-530': 'GMT-0530', 'gmt-0530': 'GMT-0530',
'gmt-630': 'GMT-0630', 'gmt-0630': 'GMT-0630',
'gmt-730': 'GMT-0730', 'gmt-0730': 'GMT-0730',
'gmt-830': 'GMT-0830', 'gmt-0830': 'GMT-0830',
'gmt-930': 'GMT-0930', 'gmt-0930': 'GMT-0930',
'gmt-1030': 'GMT-1030',
'gmt-1130': 'GMT-1130',
'gmt-1230': 'GMT-1230',
'ut': 'Universal',
'bst': 'GMT+1', 'mest': 'GMT+2', 'sst': 'GMT+2',
'fst': 'GMT+2', 'wadt': 'GMT+8', 'eadt': 'GMT+11', 'nzdt': 'GMT+13',
'wet': 'GMT', 'wat': 'GMT-1', 'at': 'GMT-2', 'ast': 'GMT-4',
'nt': 'GMT-11', 'idlw': 'GMT-12', 'cet': 'GMT+1', 'cest': 'GMT+2',
'met': 'GMT+1',
'mewt': 'GMT+1', 'swt': 'GMT+1', 'fwt': 'GMT+1', 'eet': 'GMT+2',
'eest': 'GMT+3',
'bt': 'GMT+3', 'zp4': 'GMT+4', 'zp5': 'GMT+5', 'zp6': 'GMT+6',
'wast': 'GMT+7', 'cct': 'GMT+8', 'jst': 'GMT+9', 'east': 'GMT+10',
'gst': 'GMT+10', 'nzt': 'GMT+12', 'nzst': 'GMT+12', 'idle': 'GMT+12',
'ret': 'GMT+4', 'ist': 'GMT+0530', 'edt': 'GMT-4',
}
# some timezone definitions of the "-0400" are not working
# when upgrading
for hour in range(0, 13):
hour = hour
fhour = str(hour)
if len(fhour) == 1:
fhour = '0' + fhour
_old_zmap['-%s00' % fhour] = 'GMT-%i' % hour
_old_zmap['+%s00' % fhour] = 'GMT+%i' % hour
def _static_timezone_factory(data):
zone = data[0]
cls = type(zone, (StaticTzInfo,), dict(
zone=zone,
_utcoffset=memorized_timedelta(data[5][0][0]),
_tzname=data[6][:-1])) # strip the trailing null
return cls()
_numeric_timezones = dict((key, _static_timezone_factory(data))
for key, data in _numeric_timezone_data.items())
class Timezone:
"""
Timezone information returned by PytzCache.__getitem__
Adapts datetime.tzinfo object to DateTime._timezone interface
"""
def __init__(self, tzinfo):
self.tzinfo = tzinfo
def info(self, t=None):
if t is None:
dt = datetime.utcnow().replace(tzinfo=pytz.utc)
else:
# can't use utcfromtimestamp past 2038
dt = EPOCH + timedelta(0, t)
# need to normalize tzinfo for the datetime to deal with
# daylight savings time.
normalized_dt = self.tzinfo.normalize(dt.astimezone(self.tzinfo))
normalized_tzinfo = normalized_dt.tzinfo
offset = normalized_tzinfo.utcoffset(normalized_dt)
secs = offset.days * 24 * 60 * 60 + offset.seconds
dst = normalized_tzinfo.dst(normalized_dt)
if dst == timedelta(0):
is_dst = 0
else:
is_dst = 1
return secs, is_dst, normalized_tzinfo.tzname(normalized_dt)
class PytzCache:
"""
Reimplementation of the DateTime._cache class that uses for timezone info
"""
_zlst = pytz.common_timezones + _old_zlst # used by DateTime.TimeZones
_zmap = dict((name.lower(), name) for name in pytz.all_timezones)
_zmap.update(_old_zmap) # These must take priority
_zidx = _zmap.keys()
def __getitem__(self, key):
name = self._zmap.get(key.lower(), key) # fallback to key
try:
return Timezone(pytz.timezone(name))
except pytz.UnknownTimeZoneError:
try:
return Timezone(_numeric_timezones[name])
except KeyError:
raise DateTimeError('Unrecognized timezone: %s' % key)