Commit 1e74b61d authored by Brett Cannon's avatar Brett Cannon

Fix handling of bad locale setup where time.tzname[0] == time.tzname[1] and

time.daylight is true.  Add an explicit test for this situation.

Fixed some wording in docstrings.
parent a13906a4
...@@ -64,6 +64,10 @@ class LocaleTime(object): ...@@ -64,6 +64,10 @@ class LocaleTime(object):
locks to prevent changing the locale while locale-dependent code is locks to prevent changing the locale while locale-dependent code is
running. The check here is done in case someone does not think about running. The check here is done in case someone does not think about
doing this. doing this.
Only other possible issue is if someone changed the timezone and did
not call tz.tzset . That is an issue for the programmer, though,
since changing the timezone is worthless without that call.
""" """
self.lang = _getlang() self.lang = _getlang()
...@@ -155,6 +159,8 @@ class LocaleTime(object): ...@@ -155,6 +159,8 @@ class LocaleTime(object):
def __calc_timezone(self): def __calc_timezone(self):
# Set self.timezone by using time.tzname. # Set self.timezone by using time.tzname.
# Do not worry about possibility of time.tzname[0] == timetzname[1]
# and time.daylight; handle that in strptime .
try: try:
time.tzset() time.tzset()
except AttributeError: except AttributeError:
...@@ -237,7 +243,7 @@ class TimeRE(dict): ...@@ -237,7 +243,7 @@ class TimeRE(dict):
"""Return regex pattern for the format string. """Return regex pattern for the format string.
Need to make sure that any characters that might be interpreted as Need to make sure that any characters that might be interpreted as
regex syntax is escaped. regex syntax are escaped.
""" """
processed_format = '' processed_format = ''
...@@ -263,11 +269,11 @@ _cache_lock = _thread_allocate_lock() ...@@ -263,11 +269,11 @@ _cache_lock = _thread_allocate_lock()
# DO NOT modify _TimeRE_cache or _regex_cache without acquiring the cache lock # DO NOT modify _TimeRE_cache or _regex_cache without acquiring the cache lock
# first! # first!
_TimeRE_cache = TimeRE() _TimeRE_cache = TimeRE()
_CACHE_MAX_SIZE = 5 _CACHE_MAX_SIZE = 5 # Max number of regexes stored in _regex_cache
_regex_cache = {} _regex_cache = {}
def strptime(data_string, format="%a %b %d %H:%M:%S %Y"): def strptime(data_string, format="%a %b %d %H:%M:%S %Y"):
"""Return a time struct based on the input data and the format string.""" """Return a time struct based on the input string and the format string."""
global _TimeRE_cache global _TimeRE_cache
_cache_lock.acquire() _cache_lock.acquire()
try: try:
...@@ -355,14 +361,17 @@ def strptime(data_string, format="%a %b %d %H:%M:%S %Y"): ...@@ -355,14 +361,17 @@ def strptime(data_string, format="%a %b %d %H:%M:%S %Y"):
# Since -1 is default value only need to worry about setting tz if # Since -1 is default value only need to worry about setting tz if
# it can be something other than -1. # it can be something other than -1.
found_zone = found_dict['Z'].lower() found_zone = found_dict['Z'].lower()
if locale_time.timezone[0] == locale_time.timezone[1] and \ for value, tz_values in enumerate(locale_time.timezone):
time.daylight: if found_zone in tz_values:
pass #Deals with bad locale setup where timezone info is # Deal with bad locale setup where timezone names are the
# the same; first found on FreeBSD 4.4. # same and yet time.daylight is true; too ambiguous to
else: # be able to tell what timezone has daylight savings
for value, tz_values in enumerate(locale_time.timezone): if time.tzname[0] == time.tzname[1] and \
if found_zone in tz_values: time.daylight:
break
else:
tz = value tz = value
break
# Cannot pre-calculate datetime_date() since can change in Julian # Cannot pre-calculate datetime_date() since can change in Julian
#calculation and thus could have different value for the day of the week #calculation and thus could have different value for the day of the week
#calculation #calculation
......
...@@ -5,6 +5,7 @@ import time ...@@ -5,6 +5,7 @@ import time
import locale import locale
import re import re
import sets import sets
import sys
from test import test_support from test import test_support
import _strptime import _strptime
...@@ -258,6 +259,9 @@ class StrptimeTests(unittest.TestCase): ...@@ -258,6 +259,9 @@ class StrptimeTests(unittest.TestCase):
self.failUnlessEqual(strp_output.tm_isdst, 0) self.failUnlessEqual(strp_output.tm_isdst, 0)
strp_output = _strptime.strptime("GMT", "%Z") strp_output = _strptime.strptime("GMT", "%Z")
self.failUnlessEqual(strp_output.tm_isdst, 0) self.failUnlessEqual(strp_output.tm_isdst, 0)
if sys.platform == "mac":
# Timezones don't really work on MacOS9
return
time_tuple = time.localtime() time_tuple = time.localtime()
strf_output = time.strftime("%Z") #UTC does not have a timezone strf_output = time.strftime("%Z") #UTC does not have a timezone
strp_output = _strptime.strptime(strf_output, "%Z") strp_output = _strptime.strptime(strf_output, "%Z")
...@@ -271,6 +275,22 @@ class StrptimeTests(unittest.TestCase): ...@@ -271,6 +275,22 @@ class StrptimeTests(unittest.TestCase):
"LocaleTime().timezone has duplicate values and " "LocaleTime().timezone has duplicate values and "
"time.daylight but timezone value not set to -1") "time.daylight but timezone value not set to -1")
def test_bad_timezone(self):
# Explicitly test possibility of bad timezone;
# when time.tzname[0] == time.tzname[1] and time.daylight
if sys.platform == "mac":
return #MacOS9 has severely broken timezone support.
try:
original_tzname = time.tzname
original_daylight = time.daylight
time.tzname = ("PDT", "PDT")
time.daylight = 1
tz_value = _strptime.strptime("PDT", "%Z")[8]
self.failUnlessEqual(tz_value, -1)
finally:
time.tzname = original_tzname
time.daylight = original_daylight
def test_date_time(self): def test_date_time(self):
# Test %c directive # Test %c directive
for position in range(6): for position in range(6):
......
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