Commit 622aa860 authored by Laurence Rowe's avatar Laurence Rowe

* Move all timezone usage to use pytz

* Add support to timezone aware datetime conversion
* Correct capitalization of Brazil/DeNoronha

All previous timezone names are tested against the new pytz based timezones.
This test shows that the following zones changed when pytz support was added
(i.e. not in this commit):

t1 = time.mktime(datetime(2002, 1, 1).timetuple())
t2 = time.mktime(datetime(2002, 7, 1).timetuple())
expected_failures = [ # zone.info(t1)     newzone.info(t1)     zone.info(t2)     newzone.info(t2)
    'Jamaica',        # (-18000, 0, 'EST') (-18000, 0, 'EST') (-14400, 1, 'EDT') (-18000, 0, 'EST')
    'Turkey',         # (10800, 0, 'EET') (7200, 0, 'EET') (14400, 1, 'EET DST') (10800, 1, 'EEST')
    'Mexico/BajaSur', # (-25200, 0, 'MST') (-25200, 0, 'MST') (-25200, 0, 'MST') (-21600, 1, 'MDT')
    'Mexico/General', # (-21600, 0, 'CST') (-21600, 0, 'CST') (-21600, 0, 'CST') (-18000, 1, 'CDT')
    'Canada/Yukon',   # (-32400, 0, 'YST') (-28800, 0, 'PST') (-28800, 1, 'YDT') (-25200, 1, 'PDT')
    'Brazil/West',    # (-10800, 1, 'WDT') (-14400, 0, 'AMT') (-14400, 0, 'WST') (-14400, 0, 'AMT')
    'Brazil/Acre',    # (-14400, 1, 'ADT') (-18000, 0, 'ACT') (-18000, 0, 'AST') (-18000, 0, 'ACT')
    ]

The most likely explanation for this is that the old database was out of date.
parent cb8db59c
......@@ -23,6 +23,7 @@ from interfaces import IDateTime
from interfaces import DateTimeError, SyntaxError, DateError, TimeError
from zope.interface import implements
from pytz_support import PytzCache
_cache = PytzCache
default_datefmt = None
......@@ -108,206 +109,6 @@ iso8601Match = re.compile(r'''
''', re.VERBOSE).match
class _timezone:
def __init__(self,data):
self.name,self.timect,self.typect, \
self.ttrans,self.tindex,self.tinfo,self.az=data
def default_index(self):
if self.timect == 0: return 0
for i in range(self.typect):
if self.tinfo[i][1] == 0: return i
return 0
def index(self,t=None):
t=t or time()
if self.timect==0: idx=(0, 0, 0)
elif t < self.ttrans[0]:
i=self.default_index()
idx=(i, ord(self.tindex[0]),i)
elif t >= self.ttrans[-1]:
if self.timect > 1:
idx=(ord(self.tindex[-1]),ord(self.tindex[-1]),
ord(self.tindex[-2]))
else:
idx=(ord(self.tindex[-1]),ord(self.tindex[-1]),
self.default_index())
else:
for i in range(self.timect-1):
if t < self.ttrans[i+1]:
if i==0: idx=(ord(self.tindex[0]),ord(self.tindex[1]),
self.default_index())
else: idx=(ord(self.tindex[i]),ord(self.tindex[i+1]),
ord(self.tindex[i-1]))
break
return idx
def info(self,t=None):
idx=self.index(t)[0]
zs =self.az[self.tinfo[idx][2]:]
return self.tinfo[idx][0],self.tinfo[idx][1],zs[:zs.find('\000')]
class _cache:
_zlst=['Brazil/Acre','Brazil/East', #'Brazil/DeNoronha',
'Brazil/West','Canada/Atlantic','Canada/Central',
'Canada/Eastern','Canada/East-Saskatchewan',
'Canada/Mountain','Canada/Newfoundland',
'Canada/Pacific','Canada/Yukon',
'Chile/Continental','Chile/EasterIsland','CST','Cuba',
'Egypt','EST','GB-Eire','Greenwich','Hongkong','Iceland',
'Iran','Israel','Jamaica','Japan','Mexico/BajaNorte',
'Mexico/BajaSur','Mexico/General','MST','Poland','PST',
'Singapore','Turkey','Universal','US/Alaska','US/Aleutian',
'US/Arizona','US/Central','US/Eastern','US/East-Indiana',
'US/Hawaii','US/Indiana-Starke','US/Michigan',
'US/Mountain','US/Pacific','US/Samoa','UTC','UCT','GMT',
'GMT+0100','GMT+0200','GMT+0300','GMT+0400','GMT+0500',
'GMT+0600','GMT+0700','GMT+0800','GMT+0900','GMT+1000',
'GMT+1100','GMT+1200','GMT+1300','GMT-0100','GMT-0200',
'GMT-0300','GMT-0400','GMT-0500','GMT-0600','GMT-0700',
'GMT-0800','GMT-0900','GMT-1000','GMT-1100','GMT-1200',
'GMT+1',
'GMT+0130', 'GMT+0230', 'GMT+0330', 'GMT+0430', 'GMT+0530',
'GMT+0630', 'GMT+0730', 'GMT+0830', 'GMT+0930', 'GMT+1030',
'GMT+1130', 'GMT+1230',
'GMT-0130', 'GMT-0230', 'GMT-0330', 'GMT-0430', 'GMT-0530',
'GMT-0630', 'GMT-0730', 'GMT-0830', 'GMT-0930', 'GMT-1030',
'GMT-1130', 'GMT-1230',
'UT','BST','MEST','SST','FST','WADT','EADT','NZDT',
'WET','WAT','AT','AST','NT','IDLW','CET','MET',
'MEWT','SWT','FWT','EET','EEST','BT','ZP4','ZP5','ZP6',
'WAST','CCT','JST','EAST','GST','NZT','NZST','IDLE']
_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',
'brazil/acre':'Brazil/Acre',
#'brazil/denoronha':'Brazil/Denoronha',
'brazil/east':'Brazil/East','brazil/west':'Brazil/West',
'canada/atlantic':'Canada/Atlantic',
'canada/central':'Canada/Central',
'canada/eastern':'Canada/Eastern',
'canada/east-saskatchewan':'Canada/East-Saskatchewan',
'canada/mountain':'Canada/Mountain',
'canada/newfoundland':'Canada/Newfoundland',
'canada/pacific':'Canada/Pacific','canada/yukon':'Canada/Yukon',
'central europe standard time':'GMT+1',
'chile/continental':'Chile/Continental',
'chile/easterisland':'Chile/EasterIsland',
'cst':'US/Central','cuba':'Cuba','est':'US/Eastern','egypt':'Egypt',
'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',
'gb-eire':'GB-Eire','gmt':'GMT',
'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',
'greenwich':'Greenwich','hongkong':'Hongkong',
'iceland':'Iceland','iran':'Iran','israel':'Israel',
'jamaica':'Jamaica','japan':'Japan',
'mexico/bajanorte':'Mexico/BajaNorte',
'mexico/bajasur':'Mexico/BajaSur','mexico/general':'Mexico/General',
'mst':'US/Mountain','pst':'US/Pacific','poland':'Poland',
'singapore':'Singapore','turkey':'Turkey','universal':'Universal',
'utc':'Universal','uct':'Universal','us/alaska':'US/Alaska',
'us/aleutian':'US/Aleutian','us/arizona':'US/Arizona',
'us/central':'US/Central','us/eastern':'US/Eastern',
'us/east-indiana':'US/East-Indiana','us/hawaii':'US/Hawaii',
'us/indiana-starke':'US/Indiana-Starke','us/michigan':'US/Michigan',
'us/mountain':'US/Mountain','us/pacific':'US/Pacific',
'us/samoa':'US/Samoa',
'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'
}
def __init__(self):
self._db=DateTimeZone._data
self._d,self._zidx={},self._zmap.keys()
def __getitem__(self,k):
try:
n=self._zmap[k.lower()]
except KeyError:
if numericTimeZoneMatch(k) == None:
raise DateTimeError,'Unrecognized timezone: %s' % k
return k
try: return self._d[n]
except KeyError:
z=self._d[n]=_timezone(self._db[n])
return z
def _findLocalTimeZoneName(isDST):
if not daylight:
# Daylight savings does not occur in this time zone.
......@@ -665,10 +466,10 @@ class DateTime:
- New in 2.11:
The DateTime function may now be invoked with a single argument
that is a datetime.datetime instance. Timezone naive DateTimes may
be converted back to timezone naive datetime.datetime objects with
asdatetime(). All DateTime instances may be converted to a timezone
naive datetime.datetime in UTC with utcdatetime().
that is a datetime.datetime instance. DateTimes may be converted
back to datetime.datetime objects with asdatetime().
DateTime instances may be converted to a timezone naive
datetime.datetime in UTC with utcdatetime().
- If the function is invoked with two numeric arguments, then
the first is taken to be an integer year and the second
......@@ -734,7 +535,7 @@ class DateTime:
will raise a DateError, while invalid time or timezone components
will raise a DateTimeError.
The module function Timezones() will return a list of the
The module function Timezones() will return a list of the (common)
timezones recognized by the DateTime module. Recognition of
timezone names is case-insensitive.
"""
......@@ -790,17 +591,26 @@ class DateTime:
sc=sc+ms
elif isinstance(arg, datetime):
yr,mo,dy,hr,mn,sc,tz,tznaive=self._parse_iso8601_preserving_tznaive(arg.isoformat())
self._timezone_naive = tznaive
yr,mo,dy,hr,mn,sc,numerictz,tznaive=self._parse_iso8601_preserving_tznaive(arg.isoformat())
if arg.tzinfo is None:
self._timezone_naive = True
tz = None
else:
self._timezone_naive = False
tz = arg.tzinfo.zone
ms = sc - math.floor(sc)
x = _calcDependentSecond2(yr,mo,dy,hr,mn,sc)
if tz:
try: tz=self._tzinfo._zmap[tz.lower()]
except KeyError:
if numericTimeZoneMatch(tz) is None:
try:
zone = self._tzinfo[tz]
except DateTimeError:
try:
zone = self._tzinfo[numerictz]
except DateTimeError:
raise DateTimeError, \
'Unknown time zone in date: %s' % arg
tz = zone.tzinfo.zone
else:
tz = self._calcTimezoneName(x, ms)
s,d,t,microsecs = _calcIndependentSecondEtc(tz, x, ms)
......@@ -988,7 +798,7 @@ class DateTime:
# For backward compatibility only:
_isDST = localtime(time())[8]
_localzone = _isDST and _localzone1 or _localzone0
_tzinfo = PytzCache(_cache())
_tzinfo = PytzCache()
def localZone(self, ltm=None):
'''Returns the time zone on the given date. The time zone
......@@ -1799,16 +1609,15 @@ class DateTime:
"""Return a standard libary datetime.datetime
"""
tznaive = self.timezoneNaive()
if tznaive is True:
# we were either converted from an ISO8601 timezone naive string or
# a timezone naive datetime
if tznaive:
tzinfo = None
else:
tzinfo = self._tzinfo[self._tz].tzinfo
second = int(self._second)
microsec = self.micros() % 1000000
dt = datetime(self._year, self._month, self._day, self._hour,
self._minute, second, microsec)
self._minute, second, microsec, tzinfo)
return dt
else:
raise NotImplementedError('conversion of datetime aware DateTime to datetime unsupported')
def utcdatetime(self):
"""Convert the time to UTC then return a timezone naive datetime object"""
......@@ -2041,5 +1850,5 @@ class strftimeFormatter:
# Module methods
def Timezones():
"""Return the list of recognized timezone names"""
return list(PytzCache(_cache())._zlst)
return PytzCache._zlst
......@@ -12,7 +12,7 @@ Returns the list of recognized timezone names:
>>> from DateTime import Timezones
>>> Timezones() # doctest: +ELLIPSIS
[...'Brazil/Acre', 'Brazil/DeNoronha', ..., 'NZST', 'IDLE']
[...'Brazil/Acre'... 'Brazil/DeNoronha'... 'IDLE'... 'NZST'...]
Class DateTime
......
......@@ -10,6 +10,9 @@
# FOR A PARTICULAR PURPOSE
#
##############################################################################
# This data is used only for testing legacy compatibility with pytz
_data={
......
......@@ -126,13 +126,13 @@ class.
The _zlst attribute is a list of supported time zone names.
>>> cache._zlst #doctest: +ELLIPSIS
['Africa/Abidjan', 'Africa/Accra', ... 'NZT', 'NZST', 'IDLE']
['Africa/Abidjan'... 'Africa/Accra'... 'IDLE'... 'NZST'... 'NZT'...]
The _zidx attribute is a list of lower-case and possibly abbreviated
time zone names that can be mapped to offical zone names.
>>> cache._zidx #doctest: +ELLIPSIS
['australia/yancowinna', 'gmt+0500', ... 'europe/isle_of_man']
['australia/yancowinna'... 'gmt+0500'... 'europe/isle_of_man'...]
Note that there are more items in _zidx than in _zlst since there are
multiple names for some time zones.
......
......@@ -16,8 +16,191 @@ Pytz timezone support.
import pytz
import pytz.reference
from pytz.tzinfo import StaticTzInfo, memorized_timedelta
from datetime import datetime, timedelta
import re
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'
}
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:
"""
......@@ -31,7 +214,7 @@ class Timezone:
if t is None:
dt = datetime.utcnow().replace(tzinfo=pytz.utc)
else:
dt = datetime.utcfromtimestamp(t).replace(tzinfo=pytz.utc)
dt = EPOCH + timedelta(0, t) # can't use utcfromtimestamp past 2038
# need to normalize tzinfo for the datetime to deal with
# daylight savings time.
......@@ -50,24 +233,20 @@ class Timezone:
class PytzCache:
"""
Wrapper for the DateTime._cache class that uses pytz for
timezone information where possible.
Reimplementation of the DateTime._cache class that uses for timezone info
"""
def __init__(self, cache):
self.cache = cache
self._zlst = list(pytz.common_timezones)
for name in cache._zlst:
if name not in self._zlst:
self._zlst.append(name)
self._zmap = dict(cache._zmap)
self._zmap.update(dict([(name.lower(), name)
for name in pytz.common_timezones]))
self._zidx = self._zmap.keys()
_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:
name = self._zmap[key.lower()]
return Timezone(pytz.timezone(name))
except (KeyError, pytz.UnknownTimeZoneError):
return self.cache[key]
except pytz.UnknownTimeZoneError:
try:
return Timezone(_numeric_timezones[name])
except KeyError:
raise DateTimeError,'Unrecognized timezone: %s' % key
\ No newline at end of file
##############################################################################
#
# Copyright (c) 2002 Zope Corporation and Contributors. All Rights Reserved.
#
# 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.DateTimeZone import _data
from time import time
class _timezone:
def __init__(self,data):
self.name,self.timect,self.typect, \
self.ttrans,self.tindex,self.tinfo,self.az=data
def default_index(self):
if self.timect == 0: return 0
for i in range(self.typect):
if self.tinfo[i][1] == 0: return i
return 0
def index(self,t=None):
t=t or time()
if self.timect==0: idx=(0, 0, 0)
elif t < self.ttrans[0]:
i=self.default_index()
idx=(i, ord(self.tindex[0]),i)
elif t >= self.ttrans[-1]:
if self.timect > 1:
idx=(ord(self.tindex[-1]),ord(self.tindex[-1]),
ord(self.tindex[-2]))
else:
idx=(ord(self.tindex[-1]),ord(self.tindex[-1]),
self.default_index())
else:
for i in range(self.timect-1):
if t < self.ttrans[i+1]:
if i==0: idx=(ord(self.tindex[0]),ord(self.tindex[1]),
self.default_index())
else: idx=(ord(self.tindex[i]),ord(self.tindex[i+1]),
ord(self.tindex[i-1]))
break
return idx
def info(self,t=None):
idx=self.index(t)[0]
zs =self.az[self.tinfo[idx][2]:]
return self.tinfo[idx][0],self.tinfo[idx][1],zs[:zs.find('\000')]
_zlst = ['Brazil/Acre','Brazil/DeNoronha','Brazil/East',
'Brazil/West','Canada/Atlantic','Canada/Central',
'Canada/Eastern','Canada/East-Saskatchewan',
'Canada/Mountain','Canada/Newfoundland',
'Canada/Pacific','Canada/Yukon',
'Chile/Continental','Chile/EasterIsland','CST','Cuba',
'Egypt','EST','GB-Eire','Greenwich','Hongkong','Iceland',
'Iran','Israel','Jamaica','Japan','Mexico/BajaNorte',
'Mexico/BajaSur','Mexico/General','MST','Poland','PST',
'Singapore','Turkey','Universal','US/Alaska','US/Aleutian',
'US/Arizona','US/Central','US/Eastern','US/East-Indiana',
'US/Hawaii','US/Indiana-Starke','US/Michigan',
'US/Mountain','US/Pacific','US/Samoa','UTC','UCT','GMT',
'GMT+0100','GMT+0200','GMT+0300','GMT+0400','GMT+0500',
'GMT+0600','GMT+0700','GMT+0800','GMT+0900','GMT+1000',
'GMT+1100','GMT+1200','GMT+1300','GMT-0100','GMT-0200',
'GMT-0300','GMT-0400','GMT-0500','GMT-0600','GMT-0700',
'GMT-0800','GMT-0900','GMT-1000','GMT-1100','GMT-1200',
'GMT+1',
'GMT+0130', 'GMT+0230', 'GMT+0330', 'GMT+0430', 'GMT+0530',
'GMT+0630', 'GMT+0730', 'GMT+0830', 'GMT+0930', 'GMT+1030',
'GMT+1130', 'GMT+1230',
'GMT-0130', 'GMT-0230', 'GMT-0330', 'GMT-0430', 'GMT-0530',
'GMT-0630', 'GMT-0730', 'GMT-0830', 'GMT-0930', 'GMT-1030',
'GMT-1130', 'GMT-1230',
'UT','BST','MEST','SST','FST','WADT','EADT','NZDT',
'WET','WAT','AT','AST','NT','IDLW','CET','MET',
'MEWT','SWT','FWT','EET','EEST','BT','ZP4','ZP5','ZP6',
'WAST','CCT','JST','EAST','GST','NZT','NZST','IDLE']
_zmap = {'aest':'GMT+1000', 'aedt':'GMT+1100',
'aus eastern standard time':'GMT+1000',
'sydney standard time':'GMT+1000',
'tasmania standard time':'GMT+1000',
'e. australia standard time':'GMT+1000',
'aus central standard time':'GMT+0930',
'cen. australia standard time':'GMT+0930',
'w. australia standard time':'GMT+0800',
'brazil/acre':'Brazil/Acre',
'brazil/denoronha':'Brazil/DeNoronha',
'brazil/east':'Brazil/East','brazil/west':'Brazil/West',
'canada/atlantic':'Canada/Atlantic',
'canada/central':'Canada/Central',
'canada/eastern':'Canada/Eastern',
'canada/east-saskatchewan':'Canada/East-Saskatchewan',
'canada/mountain':'Canada/Mountain',
'canada/newfoundland':'Canada/Newfoundland',
'canada/pacific':'Canada/Pacific','canada/yukon':'Canada/Yukon',
'central europe standard time':'GMT+0100',
'chile/continental':'Chile/Continental',
'chile/easterisland':'Chile/EasterIsland',
'cst':'US/Central','cuba':'Cuba','est':'US/Eastern','egypt':'Egypt',
'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',
'gb-eire':'GB-Eire','gmt':'GMT',
'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',
'greenwich':'Greenwich','hongkong':'Hongkong',
'iceland':'Iceland','iran':'Iran','israel':'Israel',
'jamaica':'Jamaica','japan':'Japan',
'mexico/bajanorte':'Mexico/BajaNorte',
'mexico/bajasur':'Mexico/BajaSur','mexico/general':'Mexico/General',
'mst':'US/Mountain','pst':'US/Pacific','poland':'Poland',
'singapore':'Singapore','turkey':'Turkey','universal':'Universal',
'utc':'Universal','uct':'Universal','us/alaska':'US/Alaska',
'us/aleutian':'US/Aleutian','us/arizona':'US/Arizona',
'us/central':'US/Central','us/eastern':'US/Eastern',
'us/east-indiana':'US/East-Indiana','us/hawaii':'US/Hawaii',
'us/indiana-starke':'US/Indiana-Starke','us/michigan':'US/Michigan',
'us/mountain':'US/Mountain','us/pacific':'US/Pacific',
'us/samoa':'US/Samoa',
'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'
}
timezones = dict((name, _timezone(data)) for name, data in _data.iteritems())
\ No newline at end of file
......@@ -21,6 +21,7 @@ from DateTime.DateTime import _findLocalTimeZoneName, _cache
from DateTime import DateTime
from datetime import datetime
import pytz
import legacy
try:
__file__
......@@ -505,14 +506,49 @@ class DateTimeTests(unittest.TestCase):
dt4 = DateTime('2007-10-04T10:00:00+05:00')
sdt4 = datetime(2007, 10, 4, 5, 0)
self.assertEqual(dt4.utcdatetime(), sdt4)
self.assertEqual(dt4.asdatetime(), sdt4.replace(tzinfo=pytz.utc))
dt5 = DateTime('2007-10-23 10:00:00 US/Eastern')
tz = pytz.timezone('US/Eastern')
sdt5 = datetime(2007, 10, 23, 10, 0, tzinfo=tz)
dt6 = DateTime(sdt5)
self.assertEqual(dt5.asdatetime(), sdt5)
self.assertEqual(dt6.asdatetime(), sdt5)
self.assertEqual(dt5, dt6)
self.assertEqual(dt5.asdatetime().tzinfo, tz)
self.assertEqual(dt6.asdatetime().tzinfo, tz)
def testLegacyTimezones(self):
# check that all the legacy timezone names can actually be looked up
cache = _cache()
for key in cache._zmap.keys():
tz = cache[key]
for key in cache._zlst:
tz = cache[key]
# The year is important here as timezones change over time
t1 = time.mktime(datetime(2002, 1, 1).timetuple())
t2 = time.mktime(datetime(2002, 7, 1).timetuple())
for name in legacy._zlst + legacy._zmap.keys() + legacy._data.keys():
self.failUnless(name.lower() in cache._zidx, 'legacy timezone %s cannot be looked up' % name)
failures = []
for name, zone in legacy.timezones.iteritems():
newzone = cache[name]
# The name of the new zone might change (eg GMT+6 rather than GMT+0600)
if zone.info(t1)[:2] != newzone.info(t1)[:2] or zone.info(t2)[:2] != newzone.info(t2)[:2]:
failures.append(name)
expected_failures = [ # zone.info(t1) newzone.info(t1) zone.info(t2) newzone.info(t2)
'Jamaica', # (-18000, 0, 'EST') (-18000, 0, 'EST') (-14400, 1, 'EDT') (-18000, 0, 'EST')
'Turkey', # (10800, 0, 'EET') (7200, 0, 'EET') (14400, 1, 'EET DST') (10800, 1, 'EEST')
'Mexico/BajaSur', # (-25200, 0, 'MST') (-25200, 0, 'MST') (-25200, 0, 'MST') (-21600, 1, 'MDT')
'Mexico/General', # (-21600, 0, 'CST') (-21600, 0, 'CST') (-21600, 0, 'CST') (-18000, 1, 'CDT')
'Canada/Yukon', # (-32400, 0, 'YST') (-28800, 0, 'PST') (-28800, 1, 'YDT') (-25200, 1, 'PDT')
'Brazil/West', # (-10800, 1, 'WDT') (-14400, 0, 'AMT') (-14400, 0, 'WST') (-14400, 0, 'AMT')
'Brazil/Acre', # (-14400, 1, 'ADT') (-18000, 0, 'ACT') (-18000, 0, 'AST') (-18000, 0, 'ACT')
]
real_failures = list(set(failures).difference(set(expected_failures)))
self.failIf(real_failures, '\n'.join(real_failures))
def test_suite():
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment