Skip to content
This repository was archived by the owner on Mar 30, 2021. It is now read-only.

Commit 9ce0782

Browse files
niemeyerpaxan
authored andcommitted
1 parent 83f4241 commit 9ce0782

File tree

9 files changed

+116
-16
lines changed

9 files changed

+116
-16
lines changed

NEWS

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
Version 1.2
2+
-----------
3+
4+
- Now tzfile will round timezones to full-minutes if necessary,
5+
since Python's datetime doesn't support sub-minute offsets.
6+
Thanks to Ilpo Nyyss�nen for reporting the issue.
7+
8+
- Removed bare string exceptions, as reported and fixed by
9+
Wilfredo S�nchez Vega.
10+
11+
- Fix bug in leap count parsing (reported and fixed by Eugene Oden).
12+
113

214
Version 1.1
315
-----------

PKG-INFO

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Metadata-Version: 1.0
22
Name: python-dateutil
3-
Version: 1.1
3+
Version: 1.2
44
Summary: Extensions to the standard python 2.3+ datetime module
55
Home-page: http://labix.org/python-dateutil
66
Author: Gustavo Niemeyer

dateutil/rrule.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,9 +257,16 @@ def __init__(self, freq, dtstart=None,
257257
if bysetpos is None:
258258
self._bysetpos = None
259259
elif type(bysetpos) is int:
260+
if bysetpos == 0 or not (-366 <= bysetpos <= 366):
261+
raise ValueError("bysetpos must be between 1 and 366, "
262+
"or between -366 and -1")
260263
self._bysetpos = (bysetpos,)
261264
else:
262265
self._bysetpos = tuple(bysetpos)
266+
for pos in self._bysetpos:
267+
if pos == 0 or not (-366 <= pos <= 366):
268+
raise ValueError("bysetpos must be between 1 and 366, "
269+
"or between -366 and -1")
263270
if not (byweekno or byyearday or bymonthday or
264271
byweekday is not None or byeaster is not None):
265272
if freq == YEARLY:
@@ -965,9 +972,9 @@ def _parse_rfc_rrule(self, line,
965972
ignoretz=ignoretz,
966973
tzinfos=tzinfos)
967974
except AttributeError:
968-
raise "unknown parameter '%s'" % name
975+
raise ValueError, "unknown parameter '%s'" % name
969976
except (KeyError, ValueError):
970-
raise "invalid '%s': %s" % (name, value)
977+
raise ValueError, "invalid '%s': %s" % (name, value)
971978
return rrule(dtstart=dtstart, cache=cache, **rrkwargs)
972979

973980
def _parse_rfc(self, s,

dateutil/tz.py

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ def __init__(self, fileobj):
297297

298298
# Not used, for now
299299
if leapcnt:
300-
leap = struct.unpack(">%dl" % leapcnt*2,
300+
leap = struct.unpack(">%dl" % (leapcnt*2),
301301
fileobj.read(leapcnt*8))
302302

303303
# Then there are tzh_ttisstdcnt standard/wall
@@ -329,11 +329,16 @@ def __init__(self, fileobj):
329329
# Build ttinfo list
330330
self._ttinfo_list = []
331331
for i in range(typecnt):
332+
gmtoff, isdst, abbrind = ttinfo[i]
333+
# Round to full-minutes if that's not the case. Python's
334+
# datetime doesn't accept sub-minute timezones. Check
335+
# http://python.org/sf/1447945 for some information.
336+
gmtoff = (gmtoff+30)//60*60
332337
tti = _ttinfo()
333-
tti.offset = ttinfo[i][0]
334-
tti.delta = datetime.timedelta(seconds=ttinfo[i][0])
335-
tti.isdst = ttinfo[i][1]
336-
tti.abbr = abbr[ttinfo[i][2]:abbr.find('\x00', ttinfo[i][2])]
338+
tti.offset = gmtoff
339+
tti.delta = datetime.timedelta(seconds=gmtoff)
340+
tti.isdst = isdst
341+
tti.abbr = abbr[abbrind:abbr.find('\x00', abbrind)]
337342
tti.isstd = (ttisstdcnt > i and isstd[i] != 0)
338343
tti.isgmt = (ttisgmtcnt > i and isgmt[i] != 0)
339344
self._ttinfo_list.append(tti)
@@ -709,9 +714,9 @@ def get(self, tzid=None):
709714
if tzid is None:
710715
keys = self._vtz.keys()
711716
if len(keys) == 0:
712-
raise "no timezones defined"
717+
raise ValueError, "no timezones defined"
713718
elif len(keys) > 1:
714-
raise "more than one timezone available"
719+
raise ValueError, "more than one timezone available"
715720
tzid = keys[0]
716721
return self._vtz.get(tzid)
717722

dateutil/zoneinfo/__init__.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,18 @@ class tzfile(tzfile):
2020
def __reduce__(self):
2121
return (gettz, (self._filename,))
2222

23-
ZONEINFOFILE = None
24-
for entry in os.listdir(os.path.dirname(__file__)):
25-
if entry.startswith("zoneinfo") and ".tar." in entry:
26-
ZONEINFOFILE = os.path.join(os.path.dirname(__file__), entry)
27-
break
23+
def getzoneinfofile():
24+
filenames = os.listdir(os.path.join(os.path.dirname(__file__)))
25+
filenames.sort()
26+
filenames.reverse()
27+
for entry in filenames:
28+
if entry.startswith("zoneinfo") and ".tar." in entry:
29+
return os.path.join(os.path.dirname(__file__), entry)
30+
return None
31+
32+
ZONEINFOFILE = getzoneinfofile()
33+
34+
del getzoneinfofile
2835

2936
def setcachesize(size):
3037
global CACHESIZE, CACHE
-71.8 KB
Binary file not shown.
75.1 KB
Binary file not shown.

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
ZONEINFO = join("dateutil", "zoneinfo")
1414

1515
setup(name="python-dateutil",
16-
version = "1.1",
16+
version = "1.2",
1717
description = "Extensions to the standard python 2.3+ datetime module",
1818
author = "Gustavo Niemeyer",
1919
author_email = "gustavo@niemeyer.net",

test.py

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2933,6 +2933,19 @@ def testStrNWeekDay(self):
29332933
datetime(1998, 1, 6, 9, 0),
29342934
datetime(1998, 12, 31, 9, 0)])
29352935

2936+
def testBadBySetPos(self):
2937+
self.assertRaises(ValueError,
2938+
rrule, MONTHLY,
2939+
count=1,
2940+
bysetpos=0,
2941+
dtstart=parse("19970902T090000"))
2942+
2943+
def testBadBySetPosMany(self):
2944+
self.assertRaises(ValueError,
2945+
rrule, MONTHLY,
2946+
count=1,
2947+
bysetpos=(-1,0,1),
2948+
dtstart=parse("19970902T090000"))
29362949

29372950

29382951
class ParserTest(unittest.TestCase):
@@ -3640,6 +3653,50 @@ class TZTest(unittest.TestCase):
36403653
AEVQVAAAAAABAAAAAQ==
36413654
"""
36423655

3656+
EUROPE_HELSINKI = """
3657+
VFppZgAAAAAAAAAAAAAAAAAAAAAAAAAFAAAABQAAAAAAAAB1AAAABQAAAA2kc28Yy85RYMy/hdAV
3658+
I+uQFhPckBcDzZAX876QGOOvkBnToJAaw5GQG7y9EBysrhAdnJ8QHoyQEB98gRAgbHIQIVxjECJM
3659+
VBAjPEUQJCw2ECUcJxAmDBgQJwVDkCf1NJAo5SWQKdUWkCrFB5ArtPiQLKTpkC2U2pAuhMuQL3S8
3660+
kDBkrZAxXdkQMnK0EDM9uxA0UpYQNR2dEDYyeBA2/X8QOBuUkDjdYRA5+3aQOr1DEDvbWJA8pl+Q
3661+
Pbs6kD6GQZA/mxyQQGYjkEGEORBCRgWQQ2QbEEQl55BFQ/0QRgXJkEcj3xBH7uYQSQPBEEnOyBBK
3662+
46MQS66qEEzMv5BNjowQTqyhkE9ubhBQjIOQUVeKkFJsZZBTN2yQVExHkFUXTpBWLCmQVvcwkFgV
3663+
RhBY1xKQWfUoEFq29JBb1QoQXKAREF207BBef/MQX5TOEGBf1RBhfeqQYj+3EGNdzJBkH5kQZT2u
3664+
kGYItZBnHZCQZ+iXkGj9cpBpyHmQat1UkGuoW5BsxnEQbYg9kG6mUxBvaB+QcIY1EHFRPBByZhcQ
3665+
czEeEHRF+RB1EQAQdi8VkHbw4hB4DveQeNDEEHnu2ZB6sKYQe867kHyZwpB9rp2QfnmkkH+Of5AC
3666+
AQIDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQD
3667+
BAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAMEAwQDBAME
3668+
AwQAABdoAAAAACowAQQAABwgAAkAACowAQQAABwgAAlITVQARUVTVABFRVQAAAAAAQEAAAABAQ==
3669+
"""
3670+
3671+
NEW_YORK = """
3672+
VFppZgAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAABcAAADrAAAABAAAABCeph5wn7rrYKCGAHCh
3673+
ms1gomXicKOD6eCkaq5wpTWnYKZTyvCnFYlgqDOs8Kj+peCqE47wqt6H4KvzcPCsvmngrdNS8K6e
3674+
S+CvszTwsH4t4LGcUXCyZ0pgs3wzcLRHLGC1XBVwticOYLc793C4BvBguRvZcLnm0mC7BPXwu8a0
3675+
YLzk1/C9r9DgvsS58L+PsuDApJvwwW+U4MKEffDDT3bgxGRf8MUvWODGTXxwxw864MgtXnDI+Fdg
3676+
yg1AcMrYOWDLiPBw0iP0cNJg++DTdeTw1EDd4NVVxvDWIL/g1zWo8NgAoeDZFYrw2eCD4Nr+p3Db
3677+
wGXg3N6JcN2pgmDevmtw34lkYOCeTXDhaUZg4n4vcONJKGDkXhFw5Vcu4OZHLfDnNxDg6CcP8OkW
3678+
8uDqBvHw6vbU4Ovm0/Ds1rbg7ca18O6/02Dvr9Jw8J+1YPGPtHDyf5dg82+WcPRfeWD1T3hw9j9b
3679+
YPcvWnD4KHfg+Q88cPoIWeD6+Fjw++g74PzYOvD9yB3g/rgc8P+n/+AAl/7wAYfh4AJ34PADcP5g
3680+
BGD9cAVQ4GEGQN9yBzDCYgeNGXMJEKRjCa2U9ArwhmQL4IV1DNmi5Q3AZ3YOuYTmD6mD9xCZZucR
3681+
iWX4EnlI6BNpR/kUWSrpFUkp+RY5DOoXKQv6GCIpaxkI7fsaAgtsGvIKfBvh7Wwc0ex8HcHPbR6x
3682+
zn0fobFtIHYA/SGBk20iVeL+I2qv7iQ1xP4lSpHuJhWm/ycqc+8n/sOAKQpV8CnepYAq6jfxK76H
3683+
gSzTVHItnmmCLrM2cy9+S4MwkxhzMWdoBDJy+nQzR0oENFLcdTUnLAU2Mr51NwcOBjgb2vY45vAG
3684+
Ofu89jrG0gY72572PK/uhj27gPY+j9CGP5ti9kBvsoZBhH92Qk+UhkNkYXZEL3aHRURDd0XzqQdH
3685+
LV/3R9OLB0kNQfdJs20HSu0j90uciYdM1kB3TXxrh062IndPXE2HUJYEd1E8L4dSdeZ3UxwRh1RV
3686+
yHdU+/OHVjWqd1blEAdYHsb3WMTyB1n+qPdapNQHW96K91yEtgddvmz3XmSYB1+eTvdgTbSHYYdr
3687+
d2ItlodjZ013ZA14h2VHL3dl7VqHZycRd2fNPIdpBvN3aa0eh2rm1XdrljsHbM/x9212HQdur9P3
3688+
b1X/B3CPtfdxNeEHcm+X93MVwwd0T3n3dP7fh3Y4lnd23sGHeBh4d3i+o4d5+Fp3ep6Fh3vYPHd8
3689+
fmeHfbged35eSYd/mAB3AAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQAB
3690+
AAEAAQABAgMBAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQAB
3691+
AAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEA
3692+
AQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQABAAEAAQAB
3693+
AAEAAQABAAEAAQABAAEAAQABAAEAAf//x8ABAP//ubAABP//x8ABCP//x8ABDEVEVABFU1QARVdU
3694+
AEVQVAAEslgAAAAAAQWk7AEAAAACB4YfggAAAAMJZ1MDAAAABAtIhoQAAAAFDSsLhQAAAAYPDD8G
3695+
AAAABxDtcocAAAAIEs6mCAAAAAkVn8qJAAAACheA/goAAAALGWIxiwAAAAwdJeoMAAAADSHa5Q0A
3696+
AAAOJZ6djgAAAA8nf9EPAAAAECpQ9ZAAAAARLDIpEQAAABIuE1ySAAAAEzDnJBMAAAAUM7hIlAAA
3697+
ABU2jBAVAAAAFkO3G5YAAAAXAAAAAQAAAAE=
3698+
"""
3699+
36433700
TZICAL_EST5EDT = """
36443701
BEGIN:VTIMEZONE
36453702
TZID:US-Eastern
@@ -3796,6 +3853,18 @@ def testICalEnd1(self):
37963853
self.assertEqual(datetime(2003,10,26,0,59,tzinfo=tz).tzname(), "EDT")
37973854
self.assertEqual(datetime(2003,10,26,1,00,tzinfo=tz).tzname(), "EST")
37983855

3856+
def testRoundNonFullMinutes(self):
3857+
# This timezone has an offset of 5992 seconds in 1900-01-01.
3858+
tz = tzfile(StringIO(base64.decodestring(self.EUROPE_HELSINKI)))
3859+
self.assertEquals(str(datetime(1900,1,1,0,0, tzinfo=tz)),
3860+
"1900-01-01 00:00:00+01:40")
3861+
3862+
def testLeapCountDecodesProperly(self):
3863+
# This timezone has leapcnt, and failed to decode until
3864+
# Eugene Oden notified about the issue.
3865+
tz = tzfile(StringIO(base64.decodestring(self.NEW_YORK)))
3866+
self.assertEquals(datetime(2007,3,31,20,12).tzname(), None)
3867+
37993868
if __name__ == "__main__":
38003869
unittest.main()
38013870

0 commit comments

Comments
 (0)