summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStuart Bishop <stuart@stuartbishop.net>2009-09-29 02:49:44 +0700
committerStuart Bishop <stuart@stuartbishop.net>2009-09-29 02:49:44 +0700
commit112de0583c188e16b82e935ab8802615b3f05e08 (patch)
tree4d69f87288ea7cb9889028fe9462ba71e5d86c08
parent6b8aa43f84b50c1cfb72e47d5ca857fd9df340ff (diff)
downloadpytz-112de0583c188e16b82e935ab8802615b3f05e08.tar.gz
Fix skip_local in zdump, handle dst transition with no actual wallclock time change
-rw-r--r--gen_tzinfo.py4
-rw-r--r--src/pytz/tzfile.py3
-rw-r--r--src/pytz/tzinfo.py12
-rw-r--r--test_zdump.py75
4 files changed, 59 insertions, 35 deletions
diff --git a/gen_tzinfo.py b/gen_tzinfo.py
index ddeb7e5..5db2792 100644
--- a/gen_tzinfo.py
+++ b/gen_tzinfo.py
@@ -27,7 +27,7 @@ def allzones():
])
stripnum = len(os.path.commonprefix(zones))
zones = [z[stripnum:] for z in zones]
-
+
if target:
wanted = target + ['US/Eastern', 'UTC']
zones = [z for z in zones if z in wanted]
@@ -128,7 +128,7 @@ def add_allzones(filename):
def main(destdir):
_destdir = os.path.join(os.path.abspath(destdir), 'dist')
-
+
dupe_src(_destdir)
add_allzones(os.path.join(_destdir, 'pytz', '__init__.py'))
diff --git a/src/pytz/tzfile.py b/src/pytz/tzfile.py
index ea8032a..88f4320 100644
--- a/src/pytz/tzfile.py
+++ b/src/pytz/tzfile.py
@@ -91,6 +91,9 @@ def build_tzinfo(zone, fp):
break # Found std time.
dst = inf[0] - stdinf[0]
+ if dst == 0: # Can't calculate the dst offset, so use 1hr.
+ dst = 3600
+
tzname = inf[2]
# Round utcoffset and dst to the nearest minute or the
diff --git a/src/pytz/tzinfo.py b/src/pytz/tzinfo.py
index ed035a3..f31dc90 100644
--- a/src/pytz/tzinfo.py
+++ b/src/pytz/tzinfo.py
@@ -250,12 +250,14 @@ class DstTzInfo(BaseTzInfo):
if dt.tzinfo is not None:
raise ValueError, 'Not naive datetime (tzinfo is already set)'
- # Find the possibly correct timezones. We probably just have one,
- # but we might end up with two if we are in the end-of-DST
- # transition period. Or possibly more in some particularly confused
- # location...
+ # Find the two best possibilities.
possible_loc_dt = set()
- for tzinfo in self._tzinfos.values():
+ for delta in [timedelta(days=-1), timedelta(days=1)]:
+ loc_dt = dt + delta
+ idx = max(0, bisect_right(
+ self._utc_transition_times, loc_dt) - 1)
+ inf = self._transition_info[idx]
+ tzinfo = self._tzinfos[inf]
loc_dt = tzinfo.normalize(dt.replace(tzinfo=tzinfo))
if loc_dt.replace(tzinfo=None) == dt:
possible_loc_dt.add(loc_dt)
diff --git a/test_zdump.py b/test_zdump.py
index 9e5b440..c815a28 100644
--- a/test_zdump.py
+++ b/test_zdump.py
@@ -28,20 +28,17 @@ def test_suite():
testcases = []
raw_data = open(
os.path.join(os.path.dirname(__file__), 'zdump.out'), 'r').readlines()
- raw_data.reverse() # Keep tests running in alphabetical order
last_zone = None
test_class = None
- for line in raw_data:
- m = re.match(
- r'^([^\s]+) \s+ (.+) \s UTC \s+ = \s+ (.+) \s ([^\s]+) \s+ '
- r'isdst=(0|1)$',
- line, re.X
- )
- if m:
- zone, utc_string, loc_string, tzname, is_dst = m.groups()
- else:
+ zdump_line_re = re.compile(r'''(?x)
+ ^([^\s]+) \s+ (.+) \s UTC \s+ = \s+ (.+) \s ([^\s]+) \s+ isdst=(0|1)$
+ ''')
+ for i in range(0, len(raw_data)):
+ line = raw_data[i]
+ m = zdump_line_re.search(line)
+ if m is None:
raise RuntimeError, 'Dud line %r' % (line,)
-
+ zone, utc_string, loc_string, tzname, is_dst = m.groups()
is_dst = bool(int(is_dst))
if zone != last_zone:
@@ -50,31 +47,49 @@ def test_suite():
test_class = type(classname, (ZdumpTestCase,), {})
testcases.append(test_class)
last_zone = zone
- prev_loc_dt = None
- prev_is_dst = False
+ skip_next_local = False
utc_dt = datetime(
*strptime(utc_string, '%a %b %d %H:%M:%S %Y')[:6])
loc_dt = datetime(
*strptime(loc_string, '%a %b %d %H:%M:%S %Y')[:6])
- # Urgh - utcoffset() and dst() have to be rounded to the nearest
- # minute, so we need to break our tests to match this limitation
- real_offset = loc_dt - utc_dt
- secs = real_offset.seconds + real_offset.days*86400
- fake_offset = timedelta(seconds=int((secs+30)/60)*60)
- loc_dt = utc_dt + fake_offset
+ def round_dt(loc_dt, utc_dt):
+ # Urgh - utcoffset() and dst() have to be rounded to the nearest
+ # minute, so we need to break our tests to match this limitation
+ real_offset = loc_dt - utc_dt
+ secs = real_offset.seconds + real_offset.days*86400
+ fake_offset = timedelta(seconds=int((secs+30)/60)*60)
+ return utc_dt + fake_offset
+
+ loc_dt = round_dt(loc_dt, utc_dt)
- # If the naive time on the previous line is greater than on this
+ # If the naive time on the next line is less than on this
# line, and we arn't seeing an end-of-dst transition, then
- # we can't do our local->utc test since we are in an ambiguous
- # time period (ie. we have wound back the clock but don't have
- # differing is_dst flags to resolve the ambiguity)
- skip_local = (
- prev_loc_dt is not None and prev_loc_dt > loc_dt and
- bool(prev_is_dst) == bool(is_dst))
- prev_loc_dt = loc_dt
- prev_is_dst = is_dst
+ # we can't do our local->utc tests for either this nor the
+ # next line since we are in an ambiguous time period (ie.
+ # we have wound back the clock but don't have differing
+ # is_dst flags to resolve the ambiguity)
+ skip_local = skip_next_local
+ skip_next_local = False
+ try:
+ m = zdump_line_re.match(raw_data[i+1])
+ except IndexError:
+ m = None
+ if m is not None:
+ (next_zone, next_utc_string, next_loc_string,
+ next_tzname, next_is_dst) = m.groups()
+ next_is_dst = bool(int(next_is_dst))
+ if next_zone == zone and next_is_dst == is_dst:
+ next_utc_dt = datetime(
+ *strptime(next_utc_string, '%a %b %d %H:%M:%S %Y')[:6])
+ next_loc_dt = round_dt(
+ datetime(*strptime(
+ next_loc_string, '%a %b %d %H:%M:%S %Y')[:6]),
+ next_utc_dt)
+ if next_loc_dt <= loc_dt:
+ skip_local = True
+ skip_next_local = True
loc_tz = pytz.timezone(zone)
loc_dt = loc_tz.localize(loc_dt, is_dst)
@@ -106,6 +121,10 @@ def test_suite():
test_local_to_utc.__name__ = test_name
setattr(test_class, test_name, test_local_to_utc)
+ classname = zone.replace(
+ '+', '_plus_').replace('-', '_minus_').replace('/','_')
+ test_class = type(classname, (ZdumpTestCase,), {})
+ testcases.append(test_class)
suite = unittest.TestSuite()
while testcases: