diff --git a/django/contrib/admin/util.py b/django/contrib/admin/util.py index af8fad382e..551146472f 100644 --- a/django/contrib/admin/util.py +++ b/django/contrib/admin/util.py @@ -295,7 +295,7 @@ def display_for_field(value, field): elif value is None: return EMPTY_CHANGELIST_VALUE elif isinstance(field, models.DateTimeField): - return formats.localize(timezone.aslocaltime(value)) + return formats.localize(timezone.localtime(value)) elif isinstance(field, models.DateField) or isinstance(field, models.TimeField): return formats.localize(value) elif isinstance(field, models.DecimalField): diff --git a/django/template/base.py b/django/template/base.py index 572ec6138f..40a577dbd8 100644 --- a/django/template/base.py +++ b/django/template/base.py @@ -18,7 +18,7 @@ from django.utils.safestring import (SafeData, EscapeData, mark_safe, from django.utils.formats import localize from django.utils.html import escape from django.utils.module_loading import module_has_submodule -from django.utils.timezone import aslocaltime +from django.utils.timezone import localtime TOKEN_TEXT = 0 @@ -595,7 +595,7 @@ class FilterExpression(object): else: arg_vals.append(arg.resolve(context)) if getattr(func, 'expects_localtime', False): - obj = aslocaltime(obj, context.use_tz) + obj = localtime(obj, context.use_tz) if getattr(func, 'needs_autoescape', False): new_obj = func(obj, autoescape=context.autoescape, *arg_vals) else: @@ -856,7 +856,7 @@ def _render_value_in_context(value, context): means escaping, if required, and conversion to a unicode object. If value is a string, it is expected to have already been translated. """ - value = aslocaltime(value, use_tz=context.use_tz) + value = localtime(value, use_tz=context.use_tz) value = localize(value, use_l10n=context.use_l10n) value = force_unicode(value) if ((context.autoescape and not isinstance(value, SafeData)) or diff --git a/django/template/debug.py b/django/template/debug.py index d4b973b5e0..74aa82bcec 100644 --- a/django/template/debug.py +++ b/django/template/debug.py @@ -3,7 +3,7 @@ from django.utils.encoding import force_unicode from django.utils.html import escape from django.utils.safestring import SafeData, EscapeData from django.utils.formats import localize -from django.utils.timezone import aslocaltime +from django.utils.timezone import localtime class DebugLexer(Lexer): @@ -82,7 +82,7 @@ class DebugVariableNode(VariableNode): def render(self, context): try: output = self.filter_expression.resolve(context) - output = aslocaltime(output, use_tz=context.use_tz) + output = localtime(output, use_tz=context.use_tz) output = localize(output, use_l10n=context.use_l10n) output = force_unicode(output) except UnicodeDecodeError: diff --git a/django/templatetags/tz.py b/django/templatetags/tz.py index 14b613e24f..48c511f2e0 100644 --- a/django/templatetags/tz.py +++ b/django/templatetags/tz.py @@ -13,6 +13,7 @@ from django.utils import timezone register = Library() + # HACK: datetime is an old-style class, create a new-style equivalent # so we can define additional attributes. class datetimeobject(datetime, object): @@ -22,23 +23,25 @@ class datetimeobject(datetime, object): # Template filters @register.filter -def aslocaltime(value): +def localtime(value): """ Converts a datetime to local time in the active time zone. This only makes sense within a {% localtime off %} block. """ - return astimezone(value, timezone.get_current_timezone()) + return do_timezone(value, timezone.get_current_timezone()) + @register.filter -def asutc(value): +def utc(value): """ Converts a datetime to UTC. """ - return astimezone(value, timezone.utc) + return do_timezone(value, timezone.utc) -@register.filter -def astimezone(value, arg): + +@register.filter('timezone') +def do_timezone(value, arg): """ Converts a datetime to local time in a given time zone. @@ -103,6 +106,7 @@ class LocalTimeNode(Node): context.use_tz = old_setting return output + class TimezoneNode(Node): """ Template node class used by ``timezone_tag``. @@ -116,6 +120,7 @@ class TimezoneNode(Node): output = self.nodelist.render(context) return output + class GetCurrentTimezoneNode(Node): """ Template node class used by ``get_current_timezone_tag``. @@ -127,6 +132,7 @@ class GetCurrentTimezoneNode(Node): context[self.variable] = timezone.get_current_timezone_name() return '' + @register.tag('localtime') def localtime_tag(parser, token): """ @@ -142,13 +148,15 @@ def localtime_tag(parser, token): if len(bits) == 1: use_tz = True elif len(bits) > 2 or bits[1] not in ('on', 'off'): - raise TemplateSyntaxError("%r argument should be 'on' or 'off'" % bits[0]) + raise TemplateSyntaxError("%r argument should be 'on' or 'off'" % + bits[0]) else: use_tz = bits[1] == 'on' nodelist = parser.parse(('endlocaltime',)) parser.delete_first_token() return LocalTimeNode(nodelist, use_tz) + @register.tag('timezone') def timezone_tag(parser, token): """ @@ -167,12 +175,14 @@ def timezone_tag(parser, token): """ bits = token.split_contents() if len(bits) != 2: - raise TemplateSyntaxError("'%s' takes one argument (timezone)" % bits[0]) + raise TemplateSyntaxError("'%s' takes one argument (timezone)" % + bits[0]) tz = parser.compile_filter(bits[1]) nodelist = parser.parse(('endtimezone',)) parser.delete_first_token() return TimezoneNode(nodelist, tz) + @register.tag("get_current_timezone") def get_current_timezone_tag(parser, token): """ @@ -187,5 +197,6 @@ def get_current_timezone_tag(parser, token): """ args = token.contents.split() if len(args) != 3 or args[1] != 'as': - raise TemplateSyntaxError("'get_current_timezone' requires 'as variable' (got %r)" % args) + raise TemplateSyntaxError("'get_current_timezone' requires " + "'as variable' (got %r)" % args) return GetCurrentTimezoneNode(args[2]) diff --git a/django/utils/timezone.py b/django/utils/timezone.py index 22860eb8cc..9e78134d2a 100644 --- a/django/utils/timezone.py +++ b/django/utils/timezone.py @@ -17,7 +17,7 @@ from django.conf import settings __all__ = [ 'utc', 'get_default_timezone', 'get_current_timezone', 'activate', 'deactivate', 'override', - 'aslocaltime', 'isnaive', + 'localtime', 'isnaive', ] @@ -198,7 +198,7 @@ class override(object): # Utilities -def aslocaltime(value, use_tz=None): +def localtime(value, use_tz=None): """ Checks if value is a datetime and converts it to local time if necessary. diff --git a/docs/ref/settings.txt b/docs/ref/settings.txt index 0d91f16821..a35d99a535 100644 --- a/docs/ref/settings.txt +++ b/docs/ref/settings.txt @@ -2108,6 +2108,7 @@ Otherwise, Django will use naive datetimes in local time. See also :setting:`TIME_ZONE`, :setting:`USE_I18N` and :setting:`USE_L10N`. .. note:: + The default :file:`settings.py` file created by :djadmin:`django-admin.py startproject ` includes ``USE_TZ = True`` for convenience. diff --git a/docs/ref/utils.txt b/docs/ref/utils.txt index 9a9adba0d8..2c0110f94a 100644 --- a/docs/ref/utils.txt +++ b/docs/ref/utils.txt @@ -660,7 +660,7 @@ For a complete discussion on the usage of the following see the ``None``, the :ref:`current time zone ` is unset on entry with :func:`deactivate()` instead. -.. function:: aslocaltime(value, use_tz=None) +.. function:: localtime(value, use_tz=None) This function is used by the template engine to convert datetimes to local time where appropriate. diff --git a/docs/topics/i18n/timezones.txt b/docs/topics/i18n/timezones.txt index 41e8380acc..18d30b941a 100644 --- a/docs/topics/i18n/timezones.txt +++ b/docs/topics/i18n/timezones.txt @@ -330,10 +330,10 @@ These filters accept both aware and naive datetimes. For conversion purposes, they assume that naive datetimes are in the default time zone. They always return aware datetimes. -.. templatefilter:: aslocaltime +.. templatefilter:: localtime -aslocaltime -~~~~~~~~~~~ +localtime +~~~~~~~~~ Forces conversion of a single value to the current time zone. @@ -341,12 +341,12 @@ For example:: {% load tz %} - {{ value|aslocaltime }} + {{ value|localtime }} -.. templatefilter:: asutc +.. templatefilter:: utc -asutc -~~~~~ +utc +~~~ Forces conversion of a single value to UTC. @@ -354,10 +354,12 @@ For example:: {% load tz %} - {{ value|asutc }} + {{ value|utc }} -astimezone -~~~~~~~~~~ +.. templatefilter:: timezone + +timezone +~~~~~~~~ Forces conversion of a single value to an arbitrary timezone. @@ -368,7 +370,7 @@ For example:: {% load tz %} - {{ value|astimezone:"Europe/Paris" }} + {{ value|timezone:"Europe/Paris" }} .. _time-zones-migration-guide: diff --git a/tests/modeltests/timezones/tests.py b/tests/modeltests/timezones/tests.py index e33d4c61f8..547680c728 100644 --- a/tests/modeltests/timezones/tests.py +++ b/tests/modeltests/timezones/tests.py @@ -537,10 +537,10 @@ class TemplateTests(BaseDateTimeTests): 'naive': datetime.datetime(2011, 9, 1, 13, 20, 30), } templates = { - 'notag': Template("{% load tz %}{{ dt }}|{{ dt|aslocaltime }}|{{ dt|asutc }}|{{ dt|astimezone:ICT }}"), - 'noarg': Template("{% load tz %}{% localtime %}{{ dt }}|{{ dt|aslocaltime }}|{{ dt|asutc }}|{{ dt|astimezone:ICT }}{% endlocaltime %}"), - 'on': Template("{% load tz %}{% localtime on %}{{ dt }}|{{ dt|aslocaltime }}|{{ dt|asutc }}|{{ dt|astimezone:ICT }}{% endlocaltime %}"), - 'off': Template("{% load tz %}{% localtime off %}{{ dt }}|{{ dt|aslocaltime }}|{{ dt|asutc }}|{{ dt|astimezone:ICT }}{% endlocaltime %}"), + 'notag': Template("{% load tz %}{{ dt }}|{{ dt|localtime }}|{{ dt|utc }}|{{ dt|timezone:ICT }}"), + 'noarg': Template("{% load tz %}{% localtime %}{{ dt }}|{{ dt|localtime }}|{{ dt|utc }}|{{ dt|timezone:ICT }}{% endlocaltime %}"), + 'on': Template("{% load tz %}{% localtime on %}{{ dt }}|{{ dt|localtime }}|{{ dt|utc }}|{{ dt|timezone:ICT }}{% endlocaltime %}"), + 'off': Template("{% load tz %}{% localtime off %}{{ dt }}|{{ dt|localtime }}|{{ dt|utc }}|{{ dt|timezone:ICT }}{% endlocaltime %}"), } # Transform a list of keys in 'datetimes' to the expected template @@ -600,10 +600,10 @@ class TemplateTests(BaseDateTimeTests): @skipIf(pytz is None, "this test requires pytz") def test_localtime_filters_with_pytz(self): """ - Test the |aslocaltime, |asutc, and |astimezone filters with pytz. + Test the |localtime, |utc, and |timezone filters with pytz. """ # Use a pytz timezone as local time - tpl = Template("{% load tz %}{{ dt|aslocaltime }}|{{ dt|asutc }}") + tpl = Template("{% load tz %}{{ dt|localtime }}|{{ dt|utc }}") ctx = Context({'dt': datetime.datetime(2011, 9, 1, 12, 20, 30)}) timezone._localtime = None @@ -612,13 +612,13 @@ class TemplateTests(BaseDateTimeTests): timezone._localtime = None # Use a pytz timezone as argument - tpl = Template("{% load tz %}{{ dt|astimezone:tz }}") + tpl = Template("{% load tz %}{{ dt|timezone:tz }}") ctx = Context({'dt': datetime.datetime(2011, 9, 1, 13, 20, 30), 'tz': pytz.timezone('Europe/Paris')}) self.assertEqual(tpl.render(ctx), "2011-09-01T12:20:30+02:00") # Use a pytz timezone name as argument - tpl = Template("{% load tz %}{{ dt|astimezone:'Europe/Paris' }}") + tpl = Template("{% load tz %}{{ dt|timezone:'Europe/Paris' }}") ctx = Context({'dt': datetime.datetime(2011, 9, 1, 13, 20, 30), 'tz': pytz.timezone('Europe/Paris')}) self.assertEqual(tpl.render(ctx), "2011-09-01T12:20:30+02:00") @@ -629,9 +629,9 @@ class TemplateTests(BaseDateTimeTests): def test_localtime_filters_do_not_raise_exceptions(self): """ - Test the |aslocaltime, |asutc, and |astimezone filters on bad inputs. + Test the |localtime, |utc, and |timezone filters on bad inputs. """ - tpl = Template("{% load tz %}{{ dt }}|{{ dt|aslocaltime }}|{{ dt|asutc }}|{{ dt|astimezone:tz }}") + tpl = Template("{% load tz %}{{ dt }}|{{ dt|localtime }}|{{ dt|utc }}|{{ dt|timezone:tz }}") with self.settings(USE_TZ=True): # bad datetime value ctx = Context({'dt': None, 'tz': ICT}) @@ -639,7 +639,7 @@ class TemplateTests(BaseDateTimeTests): ctx = Context({'dt': 'not a date', 'tz': ICT}) self.assertEqual(tpl.render(ctx), "not a date|||") # bad timezone value - tpl = Template("{% load tz %}{{ dt|astimezone:tz }}") + tpl = Template("{% load tz %}{{ dt|timezone:tz }}") ctx = Context({'dt': datetime.datetime(2011, 9, 1, 13, 20, 30), 'tz': None}) self.assertEqual(tpl.render(ctx), "") ctx = Context({'dt': datetime.datetime(2011, 9, 1, 13, 20, 30), 'tz': 'not a tz'})