summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAymeric Augustin <aymeric.augustin@m4x.org>2015-11-07 16:12:13 +0100
committerAymeric Augustin <aymeric.augustin@m4x.org>2015-11-07 23:18:59 +0100
commit94d13415d81f24743045bcaa43027c737e2bcf5f (patch)
tree1cb2570b61e236c604a2787a3d4b32ba78d82b7c
parent78a28cca200e6e03432bab9bf73856b8f778c6f0 (diff)
[1.8.x] Fixed debug view crash during autumn DST change.
This only happens if USE_TZ = False and pytz is installed (perhaps not the most logical combination, but who am I to jugde?) Refs #23714 which essentially fixed the same problem when USE_TZ = True. Thanks Florian and Carl for insisting until I wrote a complete patch. Backport of 1014ba026e from master
-rw-r--r--django/utils/dateformat.py34
-rw-r--r--docs/releases/1.8.7.txt3
-rw-r--r--tests/utils_tests/test_dateformat.py17
3 files changed, 48 insertions, 6 deletions
diff --git a/django/utils/dateformat.py b/django/utils/dateformat.py
index f4de4e7f7c..ea55eaaf9d 100644
--- a/django/utils/dateformat.py
+++ b/django/utils/dateformat.py
@@ -136,6 +136,8 @@ class TimeFormat(Formatter):
return ""
seconds = self.Z()
+ if seconds == "":
+ return ""
sign = '-' if seconds < 0 else '+'
seconds = abs(seconds)
return "%s%02d%02d" % (sign, seconds // 3600, (seconds // 60) % 60)
@@ -167,7 +169,14 @@ class TimeFormat(Formatter):
if not self.timezone:
return ""
- name = self.timezone.tzname(self.data) if self.timezone else None
+ name = None
+ try:
+ name = self.timezone.tzname(self.data)
+ except Exception:
+ # pytz raises AmbiguousTimeError during the autumn DST change.
+ # This happens mainly when __init__ receives a naive datetime
+ # and sets self.timezone = get_default_timezone().
+ pass
if name is None:
name = self.format('O')
return six.text_type(name)
@@ -188,7 +197,14 @@ class TimeFormat(Formatter):
if not self.timezone:
return ""
- offset = self.timezone.utcoffset(self.data)
+ try:
+ offset = self.timezone.utcoffset(self.data)
+ except Exception:
+ # pytz raises AmbiguousTimeError during the autumn DST change.
+ # This happens mainly when __init__ receives a naive datetime
+ # and sets self.timezone = get_default_timezone().
+ return ""
+
# `offset` is a datetime.timedelta. For negative values (to the west of
# UTC) only days can be negative (days=-1) and seconds are always
# positive. e.g. UTC-1 -> timedelta(days=-1, seconds=82800, microseconds=0)
@@ -228,10 +244,16 @@ class DateFormat(TimeFormat):
def I(self):
"'1' if Daylight Savings Time, '0' otherwise."
- if self.timezone and self.timezone.dst(self.data):
- return '1'
- else:
- return '0'
+ try:
+ if self.timezone and self.timezone.dst(self.data):
+ return '1'
+ else:
+ return '0'
+ except Exception:
+ # pytz raises AmbiguousTimeError during the autumn DST change.
+ # This happens mainly when __init__ receives a naive datetime
+ # and sets self.timezone = get_default_timezone().
+ return ''
def j(self):
"Day of the month without leading zeros; i.e. '1' to '31'"
diff --git a/docs/releases/1.8.7.txt b/docs/releases/1.8.7.txt
index 6db055b5fc..9aed739c01 100644
--- a/docs/releases/1.8.7.txt
+++ b/docs/releases/1.8.7.txt
@@ -9,4 +9,7 @@ Django 1.8.7 fixes several bugs in 1.8.6.
Bugfixes
========
+* Fixed a crash of the debug view during the autumn DST change when
+ :setting:`USE_TZ` is ``False`` and ``pytz`` is installed.
+
* ...
diff --git a/tests/utils_tests/test_dateformat.py b/tests/utils_tests/test_dateformat.py
index 1edf01422d..61859fbaec 100644
--- a/tests/utils_tests/test_dateformat.py
+++ b/tests/utils_tests/test_dateformat.py
@@ -10,6 +10,11 @@ from django.utils.timezone import (
get_default_timezone, get_fixed_timezone, make_aware, utc,
)
+try:
+ import pytz
+except ImportError:
+ pytz = None
+
@override_settings(TIME_ZONE='Europe/Copenhagen')
class DateFormatTests(TestCase):
@@ -29,6 +34,18 @@ class DateFormatTests(TestCase):
dt = datetime(2009, 5, 16, 5, 30, 30)
self.assertEqual(datetime.fromtimestamp(int(format(dt, 'U'))), dt)
+ def test_naive_ambiguous_datetime(self):
+ # dt is ambiguous in Europe/Copenhagen. LocalTimezone guesses the
+ # offset (and gets it wrong 50% of the time) while pytz refuses the
+ # temptation to guess. In any case, this shouldn't crash.
+ dt = datetime(2015, 10, 25, 2, 30, 0)
+
+ # Try all formatters that involve self.timezone.
+ self.assertEqual(format(dt, 'I'), '0' if pytz is None else '')
+ self.assertEqual(format(dt, 'O'), '+0100' if pytz is None else '')
+ self.assertEqual(format(dt, 'T'), 'CET' if pytz is None else '')
+ self.assertEqual(format(dt, 'Z'), '3600' if pytz is None else '')
+
@requires_tz_support
def test_datetime_with_local_tzinfo(self):
ltz = get_default_timezone()