Fixed #7201 -- Fixed the timeuntil filter to work correctly with timezone-aware
times. Patch from Jeremy Carbaugh. This is backwards incompatible in the sense that previously, if you tried to compare timezone-aware and timezone-naive values, you got an incorrect result. Now you get an empty string. So your previously incorrect code returns a different incorrect result. git-svn-id: http://code.djangoproject.com/svn/django/trunk@8579 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
61957df17f
commit
3111d7f60b
1
AUTHORS
1
AUTHORS
|
@ -88,6 +88,7 @@ answer newbie questions, and generally made Django that much better:
|
|||
Juan Manuel Caicedo <juan.manuel.caicedo@gmail.com>
|
||||
Trevor Caira <trevor@caira.com>
|
||||
Ricardo Javier Cárdenes Medina <ricardo.cardenes@gmail.com>
|
||||
Jeremy Carbaugh <jcarbaugh@gmail.com>
|
||||
Graham Carlyle <graham.carlyle@maplecroft.net>
|
||||
Antonio Cavedoni <http://cavedoni.com/>
|
||||
C8E
|
||||
|
|
|
@ -646,20 +646,24 @@ def timesince(value, arg=None):
|
|||
from django.utils.timesince import timesince
|
||||
if not value:
|
||||
return u''
|
||||
if arg:
|
||||
return timesince(value, arg)
|
||||
return timesince(value)
|
||||
try:
|
||||
if arg:
|
||||
return timesince(value, arg)
|
||||
return timesince(value)
|
||||
except (ValueError, TypeError):
|
||||
return u''
|
||||
timesince.is_safe = False
|
||||
|
||||
def timeuntil(value, arg=None):
|
||||
"""Formats a date as the time until that date (i.e. "4 days, 6 hours")."""
|
||||
from django.utils.timesince import timesince
|
||||
from django.utils.timesince import timeuntil
|
||||
from datetime import datetime
|
||||
if not value:
|
||||
return u''
|
||||
if arg:
|
||||
return timesince(arg, value)
|
||||
return timesince(datetime.now(), value)
|
||||
try:
|
||||
return timeuntil(value, arg)
|
||||
except (ValueError, TypeError):
|
||||
return u''
|
||||
timeuntil.is_safe = False
|
||||
|
||||
###################
|
||||
|
|
|
@ -28,15 +28,12 @@ def timesince(d, now=None):
|
|||
# Convert datetime.date to datetime.datetime for comparison
|
||||
if d.__class__ is not datetime.datetime:
|
||||
d = datetime.datetime(d.year, d.month, d.day)
|
||||
if now:
|
||||
t = now.timetuple()
|
||||
else:
|
||||
t = time.localtime()
|
||||
if d.tzinfo:
|
||||
tz = LocalTimezone(d)
|
||||
else:
|
||||
tz = None
|
||||
now = datetime.datetime(t[0], t[1], t[2], t[3], t[4], t[5], tzinfo=tz)
|
||||
|
||||
if not now:
|
||||
if d.tzinfo:
|
||||
now = datetime.datetime.now(LocalTimezone(d))
|
||||
else:
|
||||
now = datetime.datetime.now()
|
||||
|
||||
# ignore microsecond part of 'd' since we removed it from 'now'
|
||||
delta = now - (d - datetime.timedelta(0, 0, d.microsecond))
|
||||
|
@ -62,6 +59,9 @@ def timeuntil(d, now=None):
|
|||
Like timesince, but returns a string measuring the time until
|
||||
the given time.
|
||||
"""
|
||||
if now == None:
|
||||
now = datetime.datetime.now()
|
||||
if not now:
|
||||
if d.tzinfo:
|
||||
now = datetime.datetime.now(LocalTimezone(d))
|
||||
else:
|
||||
now = datetime.datetime.now()
|
||||
return timesince(now, d)
|
||||
|
|
|
@ -1332,6 +1332,8 @@ For example, if ``blog_date`` is a date instance representing midnight on 1
|
|||
June 2006, and ``comment_date`` is a date instance for 08:00 on 1 June 2006,
|
||||
then ``{{ blog_date|timesince:comment_date }}`` would return "8 hours".
|
||||
|
||||
Comparing offset-naive and offset-aware datetimes will return an empty string.
|
||||
|
||||
Minutes is the smallest unit used, and "0 minutes" will be returned for any
|
||||
date that is in the future relative to the comparison point.
|
||||
|
||||
|
@ -1349,6 +1351,8 @@ Takes an optional argument that is a variable containing the date to use as
|
|||
the comparison point (instead of *now*). If ``from_date`` contains 22 June
|
||||
2006, then ``{{ conference_date|timeuntil:from_date }}`` will return "1 week".
|
||||
|
||||
Comparing offset-naive and offset-aware datetimes will return an empty string.
|
||||
|
||||
Minutes is the smallest unit used, and "0 minutes" will be returned for any
|
||||
date that is in the past relative to the comparison point.
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ consistent.
|
|||
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from django.utils.tzinfo import LocalTimezone
|
||||
from django.utils.tzinfo import LocalTimezone, FixedOffset
|
||||
from django.utils.safestring import mark_safe
|
||||
|
||||
# These two classes are used to test auto-escaping of __unicode__ output.
|
||||
|
@ -27,6 +27,7 @@ class SafeClass:
|
|||
def get_filter_tests():
|
||||
now = datetime.now()
|
||||
now_tz = datetime.now(LocalTimezone(now))
|
||||
now_tz_i = datetime.now(FixedOffset((3 * 60) + 15)) # imaginary time zone
|
||||
return {
|
||||
# Default compare with datetime.now()
|
||||
'filter-timesince01' : ('{{ a|timesince }}', {'a': datetime.now() + timedelta(minutes=-1, seconds = -10)}, '1 minute'),
|
||||
|
@ -46,6 +47,14 @@ def get_filter_tests():
|
|||
'filter-timesince09': ('{{ later|timesince }}', { 'later': now + timedelta(days=7) }, '0 minutes'),
|
||||
'filter-timesince10': ('{{ later|timesince:now }}', { 'now': now, 'later': now + timedelta(days=7) }, '0 minutes'),
|
||||
|
||||
# Ensures that differing timezones are calculated correctly
|
||||
'filter-timesince11' : ('{{ a|timesince }}', {'a': now}, '0 minutes'),
|
||||
'filter-timesince12' : ('{{ a|timesince }}', {'a': now_tz}, '0 minutes'),
|
||||
'filter-timesince13' : ('{{ a|timesince }}', {'a': now_tz_i}, '0 minutes'),
|
||||
'filter-timesince14' : ('{{ a|timesince:b }}', {'a': now_tz, 'b': now_tz_i}, '0 minutes'),
|
||||
'filter-timesince15' : ('{{ a|timesince:b }}', {'a': now, 'b': now_tz_i}, ''),
|
||||
'filter-timesince16' : ('{{ a|timesince:b }}', {'a': now_tz_i, 'b': now}, ''),
|
||||
|
||||
# Default compare with datetime.now()
|
||||
'filter-timeuntil01' : ('{{ a|timeuntil }}', {'a':datetime.now() + timedelta(minutes=2, seconds = 10)}, '2 minutes'),
|
||||
'filter-timeuntil02' : ('{{ a|timeuntil }}', {'a':(datetime.now() + timedelta(days=1, seconds = 10))}, '1 day'),
|
||||
|
@ -61,6 +70,9 @@ def get_filter_tests():
|
|||
'filter-timeuntil08': ('{{ later|timeuntil }}', { 'later': now + timedelta(days=7, hours=1) }, '1 week'),
|
||||
'filter-timeuntil09': ('{{ later|timeuntil:now }}', { 'now': now, 'later': now + timedelta(days=7) }, '1 week'),
|
||||
|
||||
# Ensures that differing timezones are calculated correctly
|
||||
'filter-timeuntil10' : ('{{ a|timeuntil }}', {'a': now_tz_i}, '0 minutes'),
|
||||
'filter-timeuntil11' : ('{{ a|timeuntil:b }}', {'a': now_tz_i, 'b': now_tz}, '0 minutes'),
|
||||
|
||||
'filter-addslash01': ("{% autoescape off %}{{ a|addslashes }} {{ b|addslashes }}{% endautoescape %}", {"a": "<a>'", "b": mark_safe("<a>'")}, ur"<a>\' <a>\'"),
|
||||
'filter-addslash02': ("{{ a|addslashes }} {{ b|addslashes }}", {"a": "<a>'", "b": mark_safe("<a>'")}, ur"<a>\' <a>\'"),
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
"""
|
||||
>>> from datetime import datetime, timedelta
|
||||
>>> from django.utils.timesince import timesince
|
||||
>>> from django.utils.timesince import timesince, timeuntil
|
||||
>>> from django.utils.tzinfo import LocalTimezone, FixedOffset
|
||||
|
||||
>>> t = datetime(2007, 8, 14, 13, 46, 0)
|
||||
|
||||
|
@ -74,4 +75,15 @@ u'0 minutes'
|
|||
u'0 minutes'
|
||||
>>> timesince(t, t-4*oneday-5*oneminute)
|
||||
u'0 minutes'
|
||||
|
||||
# When using two different timezones.
|
||||
>>> now = datetime.now()
|
||||
>>> now_tz = datetime.now(LocalTimezone(now))
|
||||
>>> now_tz_i = datetime.now(FixedOffset((3 * 60) + 15))
|
||||
>>> timesince(now)
|
||||
u'0 minutes'
|
||||
>>> timesince(now_tz)
|
||||
u'0 minutes'
|
||||
>>> timeuntil(now_tz, now_tz_i)
|
||||
u'0 minutes'
|
||||
"""
|
||||
|
|
Loading…
Reference in New Issue