Skip to content

Commit

Permalink
Fixed #17255 -- Removed "as" prefix from new timezone template filter…
Browse files Browse the repository at this point in the history
… names for the sake of clarity. Cheers to Aymeric Augustin for bearing with me.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@17107 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information
jezdez committed Nov 18, 2011
1 parent 9b1cb75 commit 6f66b55
Show file tree
Hide file tree
Showing 9 changed files with 54 additions and 40 deletions.
2 changes: 1 addition & 1 deletion django/contrib/admin/util.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ def display_for_field(value, field):
elif value is None: elif value is None:
return EMPTY_CHANGELIST_VALUE return EMPTY_CHANGELIST_VALUE
elif isinstance(field, models.DateTimeField): 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): elif isinstance(field, models.DateField) or isinstance(field, models.TimeField):
return formats.localize(value) return formats.localize(value)
elif isinstance(field, models.DecimalField): elif isinstance(field, models.DecimalField):
Expand Down
6 changes: 3 additions & 3 deletions django/template/base.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from django.utils.formats import localize from django.utils.formats import localize
from django.utils.html import escape from django.utils.html import escape
from django.utils.module_loading import module_has_submodule from django.utils.module_loading import module_has_submodule
from django.utils.timezone import aslocaltime from django.utils.timezone import localtime




TOKEN_TEXT = 0 TOKEN_TEXT = 0
Expand Down Expand Up @@ -595,7 +595,7 @@ def resolve(self, context, ignore_failures=False):
else: else:
arg_vals.append(arg.resolve(context)) arg_vals.append(arg.resolve(context))
if getattr(func, 'expects_localtime', False): if getattr(func, 'expects_localtime', False):
obj = aslocaltime(obj, context.use_tz) obj = localtime(obj, context.use_tz)
if getattr(func, 'needs_autoescape', False): if getattr(func, 'needs_autoescape', False):
new_obj = func(obj, autoescape=context.autoescape, *arg_vals) new_obj = func(obj, autoescape=context.autoescape, *arg_vals)
else: else:
Expand Down Expand Up @@ -856,7 +856,7 @@ def _render_value_in_context(value, context):
means escaping, if required, and conversion to a unicode object. If value means escaping, if required, and conversion to a unicode object. If value
is a string, it is expected to have already been translated. 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 = localize(value, use_l10n=context.use_l10n)
value = force_unicode(value) value = force_unicode(value)
if ((context.autoescape and not isinstance(value, SafeData)) or if ((context.autoescape and not isinstance(value, SafeData)) or
Expand Down
4 changes: 2 additions & 2 deletions django/template/debug.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from django.utils.html import escape from django.utils.html import escape
from django.utils.safestring import SafeData, EscapeData from django.utils.safestring import SafeData, EscapeData
from django.utils.formats import localize from django.utils.formats import localize
from django.utils.timezone import aslocaltime from django.utils.timezone import localtime




class DebugLexer(Lexer): class DebugLexer(Lexer):
Expand Down Expand Up @@ -82,7 +82,7 @@ class DebugVariableNode(VariableNode):
def render(self, context): def render(self, context):
try: try:
output = self.filter_expression.resolve(context) 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 = localize(output, use_l10n=context.use_l10n)
output = force_unicode(output) output = force_unicode(output)
except UnicodeDecodeError: except UnicodeDecodeError:
Expand Down
29 changes: 20 additions & 9 deletions django/templatetags/tz.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@


register = Library() register = Library()



# HACK: datetime is an old-style class, create a new-style equivalent # HACK: datetime is an old-style class, create a new-style equivalent
# so we can define additional attributes. # so we can define additional attributes.
class datetimeobject(datetime, object): class datetimeobject(datetime, object):
Expand All @@ -22,23 +23,25 @@ class datetimeobject(datetime, object):
# Template filters # Template filters


@register.filter @register.filter
def aslocaltime(value): def localtime(value):
""" """
Converts a datetime to local time in the active time zone. Converts a datetime to local time in the active time zone.
This only makes sense within a {% localtime off %} block. 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 @register.filter
def asutc(value): def utc(value):
""" """
Converts a datetime to UTC. 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. Converts a datetime to local time in a given time zone.
Expand Down Expand Up @@ -103,6 +106,7 @@ def render(self, context):
context.use_tz = old_setting context.use_tz = old_setting
return output return output



class TimezoneNode(Node): class TimezoneNode(Node):
""" """
Template node class used by ``timezone_tag``. Template node class used by ``timezone_tag``.
Expand All @@ -116,6 +120,7 @@ def render(self, context):
output = self.nodelist.render(context) output = self.nodelist.render(context)
return output return output



class GetCurrentTimezoneNode(Node): class GetCurrentTimezoneNode(Node):
""" """
Template node class used by ``get_current_timezone_tag``. Template node class used by ``get_current_timezone_tag``.
Expand All @@ -127,6 +132,7 @@ def render(self, context):
context[self.variable] = timezone.get_current_timezone_name() context[self.variable] = timezone.get_current_timezone_name()
return '' return ''



@register.tag('localtime') @register.tag('localtime')
def localtime_tag(parser, token): def localtime_tag(parser, token):
""" """
Expand All @@ -142,13 +148,15 @@ def localtime_tag(parser, token):
if len(bits) == 1: if len(bits) == 1:
use_tz = True use_tz = True
elif len(bits) > 2 or bits[1] not in ('on', 'off'): 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: else:
use_tz = bits[1] == 'on' use_tz = bits[1] == 'on'
nodelist = parser.parse(('endlocaltime',)) nodelist = parser.parse(('endlocaltime',))
parser.delete_first_token() parser.delete_first_token()
return LocalTimeNode(nodelist, use_tz) return LocalTimeNode(nodelist, use_tz)



@register.tag('timezone') @register.tag('timezone')
def timezone_tag(parser, token): def timezone_tag(parser, token):
""" """
Expand All @@ -167,12 +175,14 @@ def timezone_tag(parser, token):
""" """
bits = token.split_contents() bits = token.split_contents()
if len(bits) != 2: 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]) tz = parser.compile_filter(bits[1])
nodelist = parser.parse(('endtimezone',)) nodelist = parser.parse(('endtimezone',))
parser.delete_first_token() parser.delete_first_token()
return TimezoneNode(nodelist, tz) return TimezoneNode(nodelist, tz)



@register.tag("get_current_timezone") @register.tag("get_current_timezone")
def get_current_timezone_tag(parser, token): def get_current_timezone_tag(parser, token):
""" """
Expand All @@ -187,5 +197,6 @@ def get_current_timezone_tag(parser, token):
""" """
args = token.contents.split() args = token.contents.split()
if len(args) != 3 or args[1] != 'as': 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]) return GetCurrentTimezoneNode(args[2])
4 changes: 2 additions & 2 deletions django/utils/timezone.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
__all__ = [ __all__ = [
'utc', 'get_default_timezone', 'get_current_timezone', 'utc', 'get_default_timezone', 'get_current_timezone',
'activate', 'deactivate', 'override', 'activate', 'deactivate', 'override',
'aslocaltime', 'isnaive', 'localtime', 'isnaive',
] ]




Expand Down Expand Up @@ -198,7 +198,7 @@ def __exit__(self, exc_type, exc_value, traceback):


# Utilities # 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. Checks if value is a datetime and converts it to local time if necessary.
Expand Down
1 change: 1 addition & 0 deletions docs/ref/settings.txt
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -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`. See also :setting:`TIME_ZONE`, :setting:`USE_I18N` and :setting:`USE_L10N`.


.. note:: .. note::

The default :file:`settings.py` file created by The default :file:`settings.py` file created by
:djadmin:`django-admin.py startproject <startproject>` includes :djadmin:`django-admin.py startproject <startproject>` includes
``USE_TZ = True`` for convenience. ``USE_TZ = True`` for convenience.
Expand Down
2 changes: 1 addition & 1 deletion docs/ref/utils.txt
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -660,7 +660,7 @@ For a complete discussion on the usage of the following see the
``None``, the :ref:`current time zone <default-current-time-zone>` is unset ``None``, the :ref:`current time zone <default-current-time-zone>` is unset
on entry with :func:`deactivate()` instead. 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 This function is used by the template engine to convert datetimes to local
time where appropriate. time where appropriate.
Expand Down
24 changes: 13 additions & 11 deletions docs/topics/i18n/timezones.txt
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -330,34 +330,36 @@ These filters accept both aware and naive datetimes. For conversion purposes,
they assume that naive datetimes are in the default time zone. They always they assume that naive datetimes are in the default time zone. They always
return aware datetimes. return aware datetimes.


.. templatefilter:: aslocaltime .. templatefilter:: localtime


aslocaltime localtime
~~~~~~~~~~~ ~~~~~~~~~


Forces conversion of a single value to the current time zone. Forces conversion of a single value to the current time zone.


For example:: For example::


{% load tz %} {% load tz %}


{{ value|aslocaltime }} {{ value|localtime }}


.. templatefilter:: asutc .. templatefilter:: utc


asutc utc
~~~~~ ~~~


Forces conversion of a single value to UTC. Forces conversion of a single value to UTC.


For example:: For example::


{% load tz %} {% load tz %}


{{ value|asutc }} {{ value|utc }}


astimezone .. templatefilter:: timezone
~~~~~~~~~~
timezone
~~~~~~~~


Forces conversion of a single value to an arbitrary timezone. Forces conversion of a single value to an arbitrary timezone.


Expand All @@ -368,7 +370,7 @@ For example::


{% load tz %} {% load tz %}


{{ value|astimezone:"Europe/Paris" }} {{ value|timezone:"Europe/Paris" }}


.. _time-zones-migration-guide: .. _time-zones-migration-guide:


Expand Down
22 changes: 11 additions & 11 deletions tests/modeltests/timezones/tests.py
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -537,10 +537,10 @@ def test_localtime_templatetag_and_filters(self):
'naive': datetime.datetime(2011, 9, 1, 13, 20, 30), 'naive': datetime.datetime(2011, 9, 1, 13, 20, 30),
} }
templates = { templates = {
'notag': Template("{% load tz %}{{ dt }}|{{ dt|aslocaltime }}|{{ dt|asutc }}|{{ dt|astimezone:ICT }}"), 'notag': Template("{% load tz %}{{ dt }}|{{ dt|localtime }}|{{ dt|utc }}|{{ dt|timezone:ICT }}"),
'noarg': Template("{% load tz %}{% localtime %}{{ dt }}|{{ dt|aslocaltime }}|{{ dt|asutc }}|{{ dt|astimezone:ICT }}{% endlocaltime %}"), 'noarg': Template("{% load tz %}{% localtime %}{{ dt }}|{{ dt|localtime }}|{{ dt|utc }}|{{ dt|timezone:ICT }}{% endlocaltime %}"),
'on': Template("{% load tz %}{% localtime on %}{{ dt }}|{{ dt|aslocaltime }}|{{ dt|asutc }}|{{ dt|astimezone: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|aslocaltime }}|{{ dt|asutc }}|{{ dt|astimezone: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 # Transform a list of keys in 'datetimes' to the expected template
Expand Down Expand Up @@ -600,10 +600,10 @@ def t(*result):
@skipIf(pytz is None, "this test requires pytz") @skipIf(pytz is None, "this test requires pytz")
def test_localtime_filters_with_pytz(self): 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 # 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)}) ctx = Context({'dt': datetime.datetime(2011, 9, 1, 12, 20, 30)})


timezone._localtime = None timezone._localtime = None
Expand All @@ -612,13 +612,13 @@ def test_localtime_filters_with_pytz(self):
timezone._localtime = None timezone._localtime = None


# Use a pytz timezone as argument # 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), ctx = Context({'dt': datetime.datetime(2011, 9, 1, 13, 20, 30),
'tz': pytz.timezone('Europe/Paris')}) 'tz': pytz.timezone('Europe/Paris')})
self.assertEqual(tpl.render(ctx), "2011-09-01T12:20:30+02:00") self.assertEqual(tpl.render(ctx), "2011-09-01T12:20:30+02:00")


# Use a pytz timezone name as argument # 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), ctx = Context({'dt': datetime.datetime(2011, 9, 1, 13, 20, 30),
'tz': pytz.timezone('Europe/Paris')}) 'tz': pytz.timezone('Europe/Paris')})
self.assertEqual(tpl.render(ctx), "2011-09-01T12:20:30+02:00") self.assertEqual(tpl.render(ctx), "2011-09-01T12:20:30+02:00")
Expand All @@ -629,17 +629,17 @@ def test_localtime_templatetag_invalid_argument(self):


def test_localtime_filters_do_not_raise_exceptions(self): 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): with self.settings(USE_TZ=True):
# bad datetime value # bad datetime value
ctx = Context({'dt': None, 'tz': ICT}) ctx = Context({'dt': None, 'tz': ICT})
self.assertEqual(tpl.render(ctx), "None|||") self.assertEqual(tpl.render(ctx), "None|||")
ctx = Context({'dt': 'not a date', 'tz': ICT}) ctx = Context({'dt': 'not a date', 'tz': ICT})
self.assertEqual(tpl.render(ctx), "not a date|||") self.assertEqual(tpl.render(ctx), "not a date|||")
# bad timezone value # 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}) ctx = Context({'dt': datetime.datetime(2011, 9, 1, 13, 20, 30), 'tz': None})
self.assertEqual(tpl.render(ctx), "") self.assertEqual(tpl.render(ctx), "")
ctx = Context({'dt': datetime.datetime(2011, 9, 1, 13, 20, 30), 'tz': 'not a tz'}) ctx = Context({'dt': datetime.datetime(2011, 9, 1, 13, 20, 30), 'tz': 'not a tz'})
Expand Down

0 comments on commit 6f66b55

Please sign in to comment.