Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Fixed #17262 -- Refactored tzinfo implementations.

This commit deprecates django.utils.tzinfo in favor of the more recent
django.utils.timezone which was introduced when Django gained support
for time zones.
  • Loading branch information...
commit ec2778b445546f624d3b3a1f2118e751b10bb2e7 1 parent 9d70032
@aaugustin aaugustin authored
View
60 django/utils/timezone.py
@@ -18,7 +18,8 @@
from django.utils import six
__all__ = [
- 'utc', 'get_default_timezone', 'get_current_timezone',
+ 'utc', 'get_fixed_timezone',
+ 'get_default_timezone', 'get_current_timezone',
'activate', 'deactivate', 'override',
'is_naive', 'is_aware', 'make_aware', 'make_naive',
]
@@ -47,19 +48,45 @@ def tzname(self, dt):
def dst(self, dt):
return ZERO
+class FixedOffset(tzinfo):
+ """
+ Fixed offset in minutes east from UTC. Taken from Python's docs.
+
+ Kept as close as possible to the reference version. __init__ was changed
+ to make its arguments optional, according to Python's requirement that
+ tzinfo subclasses can be instantiated without arguments.
+ """
+
+ def __init__(self, offset=None, name=None):
+ if offset is not None:
+ self.__offset = timedelta(minutes=offset)
+ if name is not None:
+ self.__name = name
+
+ def utcoffset(self, dt):
+ return self.__offset
+
+ def tzname(self, dt):
+ return self.__name
+
+ def dst(self, dt):
+ return ZERO
+
class ReferenceLocalTimezone(tzinfo):
"""
- Local time implementation taken from Python's docs.
+ Local time. Taken from Python's docs.
Used only when pytz isn't available, and most likely inaccurate. If you're
having trouble with this class, don't waste your time, just install pytz.
- Kept identical to the reference version. Subclasses contain improvements.
+ Kept as close as possible to the reference version. __init__ was added to
+ delay the computation of STDOFFSET, DSTOFFSET and DSTDIFF which is
+ performed at import time in the example.
+
+ Subclasses contain further improvements.
"""
def __init__(self):
- # This code is moved in __init__ to execute it as late as possible
- # See get_default_timezone().
self.STDOFFSET = timedelta(seconds=-_time.timezone)
if _time.daylight:
self.DSTOFFSET = timedelta(seconds=-_time.altzone)
@@ -68,9 +95,6 @@ def __init__(self):
self.DSTDIFF = self.DSTOFFSET - self.STDOFFSET
tzinfo.__init__(self)
- def __repr__(self):
- return "<LocalTimezone>"
-
def utcoffset(self, dt):
if self._isdst(dt):
return self.DSTOFFSET
@@ -84,8 +108,7 @@ def dst(self, dt):
return ZERO
def tzname(self, dt):
- is_dst = False if dt is None else self._isdst(dt)
- return _time.tzname[is_dst]
+ return _time.tzname[self._isdst(dt)]
def _isdst(self, dt):
tt = (dt.year, dt.month, dt.day,
@@ -103,6 +126,10 @@ class LocalTimezone(ReferenceLocalTimezone):
error message is helpful.
"""
+ def tzname(self, dt):
+ is_dst = False if dt is None else self._isdst(dt)
+ return _time.tzname[is_dst]
+
def _isdst(self, dt):
try:
return super(LocalTimezone, self)._isdst(dt)
@@ -116,6 +143,17 @@ def _isdst(self, dt):
utc = pytz.utc if pytz else UTC()
"""UTC time zone as a tzinfo instance."""
+def get_fixed_timezone(offset):
+ """
+ Returns a tzinfo instance with a fixed offset from UTC.
+ """
+ if isinstance(offset, timedelta):
+ offset = offset.seconds // 60
+ sign = '-' if offset < 0 else '+'
+ hhmm = '%02d%02d' % divmod(abs(offset), 60)
+ name = sign + hhmm
+ return FixedOffset(offset, name)
+
# In order to avoid accessing the settings at compile time,
# wrap the expression in a function and cache the result.
_localtime = None
@@ -125,8 +163,6 @@ def get_default_timezone():
Returns the default time zone as a tzinfo instance.
This is the time zone defined by settings.TIME_ZONE.
-
- See also :func:`get_current_timezone`.
"""
global _localtime
if _localtime is None:
View
17 django/utils/tzinfo.py
@@ -2,11 +2,18 @@
from __future__ import unicode_literals
-import time
from datetime import timedelta, tzinfo
+import time
+import warnings
from django.utils.encoding import force_str, force_text, DEFAULT_LOCALE_ENCODING
+warnings.warn(
+ "django.utils.tzinfo will be removed in Django 1.9. "
+ "Use django.utils.timezone instead.",
+ PendingDeprecationWarning)
+
+
# Python's doc say: "A tzinfo subclass must have an __init__() method that can
# be called with no arguments". FixedOffset and LocalTimezone don't honor this
# requirement. Defining __getinitargs__ is sufficient to fix copy/deepcopy as
@@ -15,6 +22,10 @@
class FixedOffset(tzinfo):
"Fixed offset in minutes east from UTC."
def __init__(self, offset):
+ warnings.warn(
+ "django.utils.tzinfo.FixedOffset will be removed in Django 1.9. "
+ "Use django.utils.timezone.get_fixed_timezone instead.",
+ PendingDeprecationWarning)
if isinstance(offset, timedelta):
self.__offset = offset
offset = self.__offset.seconds // 60
@@ -48,6 +59,10 @@ def dst(self, dt):
class LocalTimezone(tzinfo):
"Proxy timezone information from time module."
def __init__(self, dt):
+ warnings.warn(
+ "django.utils.tzinfo.LocalTimezone will be removed in Django 1.9. "
+ "Use django.utils.timezone.get_default_timezone instead.",
+ PendingDeprecationWarning)
tzinfo.__init__(self)
self.__dt = dt
self._tzname = self.tzname(dt)
View
2  docs/internals/deprecation.txt
@@ -417,6 +417,8 @@ these changes.
* ``django.utils.importlib`` will be removed.
+* ``django.utils.tzinfo`` will be removed.
+
* ``django.utils.unittest`` will be removed.
* The ``syncdb`` command will be removed.
View
20 docs/ref/utils.txt
@@ -927,6 +927,17 @@ For a complete discussion on the usage of the following see the
:class:`~datetime.tzinfo` instance that represents UTC.
+.. function:: get_fixed_timezone(offset)
+
+ .. versionadded:: 1.7
+
+ Returns a :class:`~datetime.tzinfo` instance that represents a time zone
+ with a fixed offset from UTC.
+
+ ``offset`` is a :class:`datetime.timedelta` or an integer number of
+ minutes. Use positive values for time zones east of UTC and negative
+ values for west of UTC.
+
.. function:: get_default_timezone()
Returns a :class:`~datetime.tzinfo` instance that represents the
@@ -1021,6 +1032,9 @@ For a complete discussion on the usage of the following see the
``django.utils.tzinfo``
=======================
+.. deprecated:: 1.7
+ Use :mod:`~django.utils.timezone` instead.
+
.. module:: django.utils.tzinfo
:synopsis: Implementation of ``tzinfo`` classes for use with ``datetime.datetime``.
@@ -1028,6 +1042,12 @@ For a complete discussion on the usage of the following see the
Fixed offset in minutes east from UTC.
+ .. deprecated:: 1.7
+ Use :func:`~django.utils.timezone.get_fixed_timezone` instead.
+
.. class:: LocalTimezone
Proxy timezone information from time module.
+
+ .. deprecated:: 1.7
+ Use :func:`~django.utils.timezone.get_default_timezone` instead.
View
19 docs/releases/1.7.txt
@@ -308,6 +308,16 @@ For apps with migrations, ``allow_migrate`` will now get passed
without custom attributes, methods or managers. Make sure your ``allow_migrate``
methods are only referring to fields or other items in ``model._meta``.
+pytz may be required
+~~~~~~~~~~~~~~~~~~~~
+
+If your project handles datetimes before 1970 or after 2037 and Django raises
+a :exc:`~exceptions.ValueError` when encountering them, you will have to
+install pytz_. You may be affected by this problem if you use Django's time
+zone-related date formats or :mod:`django.contrib.syndication`.
+
+.. _pytz: https://pypi.python.org/pypi/pytz/
+
Miscellaneous
~~~~~~~~~~~~~
@@ -389,6 +399,15 @@ Features deprecated in 1.7
respectively :mod:`logging.config` and :mod:`importlib` provided for Python
versions prior to 2.7. They have been deprecated.
+``django.utils.tzinfo``
+~~~~~~~~~~~~~~~~~~~~~~~
+
+``django.utils.tzinfo`` provided two :class:`~datetime.tzinfo` subclasses,
+``LocalTimezone`` and ``FixedOffset``. They've been deprecated in favor of
+more correct alternatives provided by :mod:`django.utils.timezone`,
+:func:`django.utils.timezone.get_default_timezone` and
+:func:`django.utils.timezone.get_fixed_timezone`.
+
``django.utils.unittest``
~~~~~~~~~~~~~~~~~~~~~~~~~
View
5 tests/timezones/tests.py
@@ -25,7 +25,6 @@
from django.test.utils import override_settings
from django.utils import six
from django.utils import timezone
-from django.utils.tzinfo import FixedOffset
from .forms import EventForm, EventSplitForm, EventModelForm
from .models import Event, MaybeEvent, Session, SessionEvent, Timestamp, AllDayEvent
@@ -40,8 +39,8 @@
# 10:20:30 in UTC and 17:20:30 in ICT.
UTC = timezone.utc
-EAT = FixedOffset(180) # Africa/Nairobi
-ICT = FixedOffset(420) # Asia/Bangkok
+EAT = timezone.get_fixed_timezone(180) # Africa/Nairobi
+ICT = timezone.get_fixed_timezone(420) # Asia/Bangkok
TZ_SUPPORT = hasattr(time, 'tzset')
View
5 tests/utils_tests/test_timezone.py
@@ -6,11 +6,10 @@
from django.test.utils import override_settings
from django.utils import six
from django.utils import timezone
-from django.utils.tzinfo import FixedOffset
-EAT = FixedOffset(180) # Africa/Nairobi
-ICT = FixedOffset(420) # Asia/Bangkok
+EAT = timezone.get_fixed_timezone(180) # Africa/Nairobi
+ICT = timezone.get_fixed_timezone(420) # Asia/Bangkok
class TimezoneTests(unittest.TestCase):
View
10 tests/utils_tests/test_tzinfo.py
@@ -4,10 +4,16 @@
import pickle
import time
import unittest
+import warnings
-from django.utils.tzinfo import FixedOffset, LocalTimezone
+from django.test.utils import IgnorePendingDeprecationWarningsMixin
-class TzinfoTests(unittest.TestCase):
+# Swallow the import-time warning to test the deprecated implementation.
+with warnings.catch_warnings():
+ warnings.filterwarnings("ignore", category=PendingDeprecationWarning)
+ from django.utils.tzinfo import FixedOffset, LocalTimezone
+
+class TzinfoTests(IgnorePendingDeprecationWarningsMixin, unittest.TestCase):
@classmethod
def setUpClass(cls):
Please sign in to comment.
Something went wrong with that request. Please try again.