summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorniemeyer <>2008-02-28 04:52:22 +0000
committerniemeyer <>2008-02-28 04:52:22 +0000
commit05c217d3ae21303cc4d5ccff241854caf44af317 (patch)
tree0f12c89c92709c8a7046986f195e36396ab03adc
parentf296b1a67f3b6a58b81221da98c3cebc177ea31e (diff)
downloaddateutil-05c217d3ae21303cc4d5ccff241854caf44af317.tar.gz
- Fixed case where tzrange.utcoffset and tzrange.dst() might fail due
to a date being used where a datetime was expected (reported and fixed by Lennart Regebro). - Prevent tzstr from introducing daylight timings in strings that didn't specify them (reported by Lennart Regebro). - Calls like gettz("GMT+3") and gettz("UTC-2") will now return the expected values, instead of the TZ variable behavior.
-rw-r--r--NEWS16
-rw-r--r--dateutil/parser.py4
-rw-r--r--dateutil/tz.py23
-rw-r--r--test.py25
4 files changed, 56 insertions, 12 deletions
diff --git a/NEWS b/NEWS
index 6a80ca4..27fd1cc 100644
--- a/NEWS
+++ b/NEWS
@@ -1,10 +1,20 @@
Version 1.4
-----------
-- Fixed another precision problem on conversion of decimal seconds to
- microseconds, as reported by Erik Brown. Now they're gone for real,
- since it's not using floating point arithmetic anymore.
+- Fixed another parser precision problem on conversion of decimal seconds
+ to microseconds, as reported by Erik Brown. Now these issues are gone
+ for real since it's not using floating point arithmetic anymore.
+- Fixed case where tzrange.utcoffset and tzrange.dst() might fail due
+ to a date being used where a datetime was expected (reported and fixed
+ by Lennart Regebro).
+
+- Prevent tzstr from introducing daylight timings in strings that didn't
+ specify them (reported by Lennart Regebro).
+
+- Calls like gettz("GMT+3") and gettz("UTC-2") will now return the
+ expected values, instead of the TZ variable behavior.
+
Version 1.3
diff --git a/dateutil/parser.py b/dateutil/parser.py
index b1b7cc2..5d824e4 100644
--- a/dateutil/parser.py
+++ b/dateutil/parser.py
@@ -741,6 +741,8 @@ class _tzparser(object):
if (i < len_l and
(l[i] in ('+', '-') or l[i][0] in "0123456789")):
if l[i] in ('+', '-'):
+ # Yes, that's right. See the TZ variable
+ # documentation.
signal = (1,-1)[l[i] == '+']
i += 1
else:
@@ -863,7 +865,7 @@ class _tzparser(object):
except (IndexError, ValueError, AssertionError):
return None
-
+
return res
diff --git a/dateutil/tz.py b/dateutil/tz.py
index 61fe2c1..0e28d6b 100644
--- a/dateutil/tz.py
+++ b/dateutil/tz.py
@@ -438,7 +438,7 @@ class tzfile(datetime.tzinfo):
# The documentation says that utcoffset()-dst() must
# be constant for every dt.
- return self._find_ttinfo(dt, laststd=1).delta-tti.delta
+ return tti.delta-self._find_ttinfo(dt, laststd=1).delta
# An alternative for that would be:
#
@@ -492,12 +492,12 @@ class tzrange(datetime.tzinfo):
self._dst_offset = self._std_offset+datetime.timedelta(hours=+1)
else:
self._dst_offset = ZERO
- if start is None:
+ if dstabbr and start is None:
self._start_delta = relativedelta.relativedelta(
hours=+2, month=4, day=1, weekday=relativedelta.SU(+1))
else:
self._start_delta = start
- if end is None:
+ if dstabbr and end is None:
self._end_delta = relativedelta.relativedelta(
hours=+1, month=10, day=31, weekday=relativedelta.SU(-1))
else:
@@ -524,7 +524,7 @@ class tzrange(datetime.tzinfo):
def _isdst(self, dt):
if not self._start_delta:
return False
- year = datetime.date(dt.year,1,1)
+ year = datetime.datetime(dt.year,1,1)
start = year+self._start_delta
end = year+self._end_delta
dt = dt.replace(tzinfo=None)
@@ -563,6 +563,11 @@ class tzstr(tzrange):
if res is None:
raise ValueError, "unknown string format"
+ # Here we break the compatibility with the TZ variable handling.
+ # GMT-3 actually *means* the timezone -3.
+ if res.stdabbr in ("GMT", "UTC"):
+ res.stdoffset *= -1
+
# We must initialize it first, since _delta() needs
# _std_offset and _dst_offset set. Use False in start/end
# to avoid building it two times.
@@ -570,9 +575,13 @@ class tzstr(tzrange):
res.dstabbr, res.dstoffset,
start=False, end=False)
- self._start_delta = self._delta(res.start)
- if self._start_delta:
- self._end_delta = self._delta(res.end, isend=1)
+ if not res.dstabbr:
+ self._start_delta = None
+ self._end_delta = None
+ else:
+ self._start_delta = self._delta(res.start)
+ if self._start_delta:
+ self._end_delta = self._delta(res.end, isend=1)
def _delta(self, x, isend=0):
kwargs = {}
diff --git a/test.py b/test.py
index c99efff..b7ad75e 100644
--- a/test.py
+++ b/test.py
@@ -3871,7 +3871,7 @@ END:VTIMEZONE
tz = zoneinfo.gettz("EST5EDT")
self.assertEqual(datetime(2003,4,6,1,59,tzinfo=tz).tzname(), "EST")
self.assertEqual(datetime(2003,4,6,2,00,tzinfo=tz).tzname(), "EDT")
-
+
def testZoneInfoFileEnd1(self):
tz = zoneinfo.gettz("EST5EDT")
self.assertEqual(datetime(2003,10,26,0,59,tzinfo=tz).tzname(), "EDT")
@@ -3899,6 +3899,29 @@ END:VTIMEZONE
tz = tzfile(StringIO(base64.decodestring(self.NEW_YORK)))
self.assertEquals(datetime(2007,3,31,20,12).tzname(), None)
+ def testBrokenIsDstHandling(self):
+ # tzrange._isdst() was using a date() rather than a datetime().
+ # Issue reported by Lennart Regebro.
+ dt = datetime(2007,8,6,4,10, tzinfo=tzutc())
+ self.assertEquals(dt.astimezone(tz=gettz("GMT+2")),
+ datetime(2007,8,6,6,10, tzinfo=tzstr("GMT+2")))
+
+ def testGMTHasNoDaylight(self):
+ # tzstr("GMT+2") improperly considered daylight saving time.
+ # Issue reported by Lennart Regebro.
+ dt = datetime(2007,8,6,4,10)
+ self.assertEquals(gettz("GMT+2").dst(dt), timedelta(0))
+
+ def testGMTOffset(self):
+ # GMT and UTC offsets have inverted signal when compared to the
+ # usual TZ variable handling.
+ dt = datetime(2007,8,6,4,10, tzinfo=tzutc())
+ self.assertEquals(dt.astimezone(tz=tzstr("GMT+2")),
+ datetime(2007,8,6,6,10, tzinfo=tzstr("GMT+2")))
+ self.assertEquals(dt.astimezone(tz=gettz("UTC-2")),
+ datetime(2007,8,6,2,10, tzinfo=tzstr("UTC-2")))
+
+
if __name__ == "__main__":
unittest.main()