Fixed #2675 -- Changed the `timeuntil` and `timesince` template filters to display "0 minutes" when passed a past or future date respectively instead of "-1 years, 12 months". Thanks to nickefford for the patch.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@6366 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
771481695f
commit
66203fc9ee
|
@ -4,8 +4,15 @@ from django.utils.translation import ungettext, ugettext
|
|||
|
||||
def timesince(d, now=None):
|
||||
"""
|
||||
Takes two datetime objects and returns the time between then and now
|
||||
as a nicely formatted string, e.g "10 minutes"
|
||||
Takes two datetime objects and returns the time between d and now
|
||||
as a nicely formatted string, e.g. "10 minutes". If d occurs after now,
|
||||
then "0 minutes" is returned.
|
||||
|
||||
Units used are years, months, weeks, days, hours, and minutes.
|
||||
Seconds and microseconds are ignored. Up to two adjacent units will be
|
||||
displayed. For example, "2 weeks, 3 days" and "1 year, 3 months" are
|
||||
possible outputs, but "2 weeks, 3 hours" and "1 year, 5 days" are not.
|
||||
|
||||
Adapted from http://blog.natbat.co.uk/archive/2003/Jun/14/time_since
|
||||
"""
|
||||
chunks = (
|
||||
|
@ -32,6 +39,9 @@ def timesince(d, now=None):
|
|||
# ignore microsecond part of 'd' since we removed it from 'now'
|
||||
delta = now - (d - datetime.timedelta(0, 0, d.microsecond))
|
||||
since = delta.days * 24 * 60 * 60 + delta.seconds
|
||||
if since <= 0:
|
||||
# d is in the future compared to now, stop processing.
|
||||
return u'0 ' + ugettext('minutes')
|
||||
for i, (seconds, name) in enumerate(chunks):
|
||||
count = since // seconds
|
||||
if count != 0:
|
||||
|
|
|
@ -1275,17 +1275,23 @@ 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 ``{{ comment_date|timesince:blog_date }}`` would return "8 hours".
|
||||
|
||||
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.
|
||||
|
||||
timeuntil
|
||||
~~~~~~~~~
|
||||
|
||||
Similar to ``timesince``, except that it measures the time from now until the
|
||||
given date or datetime. For example, if today is 1 June 2006 and
|
||||
``conference_date`` is a date instance holding 29 June 2006, then
|
||||
``{{ conference_date|timeuntil }}`` will return "28 days".
|
||||
``{{ conference_date|timeuntil }}`` will return "4 weeks".
|
||||
|
||||
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 "7 days".
|
||||
2006, then ``{{ conference_date|timeuntil:from_date }}`` will return "1 week".
|
||||
|
||||
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.
|
||||
|
||||
title
|
||||
~~~~~
|
||||
|
|
|
@ -771,6 +771,10 @@ class Templates(unittest.TestCase):
|
|||
# Check that timezone is respected
|
||||
'timesince06' : ('{{ a|timesince:b }}', {'a':NOW_tz + timedelta(hours=8), 'b':NOW_tz}, '8 hours'),
|
||||
|
||||
# Check times in the future.
|
||||
'timesince07' : ('{{ a|timesince }}', {'a':datetime.now() + timedelta(minutes=1, seconds=10)}, '0 minutes'),
|
||||
'timesince08' : ('{{ a|timesince }}', {'a':datetime.now() + timedelta(days=1, minutes=1)}, '0 minutes'),
|
||||
|
||||
### TIMEUNTIL TAG ##################################################
|
||||
# Default compare with datetime.now()
|
||||
'timeuntil01' : ('{{ a|timeuntil }}', {'a':datetime.now() + timedelta(minutes=2, seconds = 10)}, '2 minutes'),
|
||||
|
@ -781,6 +785,10 @@ class Templates(unittest.TestCase):
|
|||
'timeuntil04' : ('{{ a|timeuntil:b }}', {'a':NOW - timedelta(days=1), 'b':NOW - timedelta(days=2)}, '1 day'),
|
||||
'timeuntil05' : ('{{ a|timeuntil:b }}', {'a':NOW - timedelta(days=2), 'b':NOW - timedelta(days=2, minutes=1)}, '1 minute'),
|
||||
|
||||
# Check times in the past.
|
||||
'timeuntil07' : ('{{ a|timeuntil }}', {'a':datetime.now() - timedelta(minutes=1, seconds=10)}, '0 minutes'),
|
||||
'timeuntil08' : ('{{ a|timeuntil }}', {'a':datetime.now() - timedelta(days=1, minutes=1)}, '0 minutes'),
|
||||
|
||||
### URL TAG ########################################################
|
||||
# Successes
|
||||
'url01' : ('{% url regressiontests.templates.views.client client.id %}', {'client': {'id': 1}}, '/url_tag/client/1/'),
|
||||
|
|
|
@ -6,6 +6,8 @@ from unittest import TestCase
|
|||
|
||||
from django.utils import html
|
||||
|
||||
from timesince import timesince_tests
|
||||
|
||||
class TestUtilsHtml(TestCase):
|
||||
|
||||
def check_output(self, function, value, output=None):
|
||||
|
@ -113,3 +115,11 @@ class TestUtilsHtml(TestCase):
|
|||
)
|
||||
for value, output in items:
|
||||
self.check_output(f, value, output)
|
||||
|
||||
__test__ = {
|
||||
'timesince_tests': timesince_tests,
|
||||
}
|
||||
|
||||
if __name__ == "__main__":
|
||||
import doctest
|
||||
doctest.testmod()
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
timesince_tests = """
|
||||
>>> from datetime import datetime, timedelta
|
||||
>>> from django.utils.timesince import timesince
|
||||
|
||||
>>> t = datetime(2007, 8, 14, 13, 46, 0)
|
||||
|
||||
>>> onemicrosecond = timedelta(microseconds=1)
|
||||
>>> onesecond = timedelta(seconds=1)
|
||||
>>> oneminute = timedelta(minutes=1)
|
||||
>>> onehour = timedelta(hours=1)
|
||||
>>> oneday = timedelta(days=1)
|
||||
>>> oneweek = timedelta(days=7)
|
||||
>>> onemonth = timedelta(days=30)
|
||||
>>> oneyear = timedelta(days=365)
|
||||
|
||||
# equal datetimes.
|
||||
>>> timesince(t, t)
|
||||
u'0 minutes'
|
||||
|
||||
# Microseconds and seconds are ignored.
|
||||
>>> timesince(t, t+onemicrosecond)
|
||||
u'0 minutes'
|
||||
>>> timesince(t, t+onesecond)
|
||||
u'0 minutes'
|
||||
|
||||
# Test other units.
|
||||
>>> timesince(t, t+oneminute)
|
||||
u'1 minute'
|
||||
>>> timesince(t, t+onehour)
|
||||
u'1 hour'
|
||||
>>> timesince(t, t+oneday)
|
||||
u'1 day'
|
||||
>>> timesince(t, t+oneweek)
|
||||
u'1 week'
|
||||
>>> timesince(t, t+onemonth)
|
||||
u'1 month'
|
||||
>>> timesince(t, t+oneyear)
|
||||
u'1 year'
|
||||
|
||||
# Test multiple units.
|
||||
>>> timesince(t, t+2*oneday+6*onehour)
|
||||
u'2 days, 6 hours'
|
||||
>>> timesince(t, t+2*oneweek+2*oneday)
|
||||
u'2 weeks, 2 days'
|
||||
|
||||
# If the two differing units aren't adjacent, only the first unit is displayed.
|
||||
>>> timesince(t, t+2*oneweek+3*onehour+4*oneminute)
|
||||
u'2 weeks'
|
||||
>>> timesince(t, t+4*oneday+5*oneminute)
|
||||
u'4 days'
|
||||
|
||||
# When the second date occurs before the first, we should always get 0 minutes.
|
||||
>>> timesince(t, t-onemicrosecond)
|
||||
u'0 minutes'
|
||||
>>> timesince(t, t-onesecond)
|
||||
u'0 minutes'
|
||||
>>> timesince(t, t-oneminute)
|
||||
u'0 minutes'
|
||||
>>> timesince(t, t-onehour)
|
||||
u'0 minutes'
|
||||
>>> timesince(t, t-oneday)
|
||||
u'0 minutes'
|
||||
>>> timesince(t, t-oneweek)
|
||||
u'0 minutes'
|
||||
>>> timesince(t, t-onemonth)
|
||||
u'0 minutes'
|
||||
>>> timesince(t, t-oneyear)
|
||||
u'0 minutes'
|
||||
>>> timesince(t, t-2*oneday-6*onehour)
|
||||
u'0 minutes'
|
||||
>>> timesince(t, t-2*oneweek-2*oneday)
|
||||
u'0 minutes'
|
||||
>>> timesince(t, t-2*oneweek-3*onehour-4*oneminute)
|
||||
u'0 minutes'
|
||||
>>> timesince(t, t-4*oneday-5*oneminute)
|
||||
u'0 minutes'
|
||||
"""
|
Loading…
Reference in New Issue