Fixed #15921 -- Refined naturaltime filter added in r16071 to use timesince and timeuntil filters as fallbacks instead of date filter.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@16233 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
9ad005ec1c
commit
578a31fea3
Binary file not shown.
|
@ -4,7 +4,7 @@ msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: Django\n"
|
"Project-Id-Version: Django\n"
|
||||||
"Report-Msgid-Bugs-To: \n"
|
"Report-Msgid-Bugs-To: \n"
|
||||||
"POT-Creation-Date: 2011-05-07 21:53+0200\n"
|
"POT-Creation-Date: 2011-05-16 17:30+0200\n"
|
||||||
"PO-Revision-Date: 2010-05-13 15:35+0200\n"
|
"PO-Revision-Date: 2010-05-13 15:35+0200\n"
|
||||||
"Last-Translator: Django team\n"
|
"Last-Translator: Django team\n"
|
||||||
"Language-Team: English <en@li.org>\n"
|
"Language-Team: English <en@li.org>\n"
|
||||||
|
@ -12,133 +12,166 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
|
|
||||||
#: templatetags/humanize.py:21
|
#: templatetags/humanize.py:25
|
||||||
msgid "th"
|
msgid "th"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templatetags/humanize.py:21
|
#: templatetags/humanize.py:25
|
||||||
msgid "st"
|
msgid "st"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templatetags/humanize.py:21
|
#: templatetags/humanize.py:25
|
||||||
msgid "nd"
|
msgid "nd"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templatetags/humanize.py:21
|
#: templatetags/humanize.py:25
|
||||||
msgid "rd"
|
msgid "rd"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templatetags/humanize.py:74
|
#: templatetags/humanize.py:78
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(value).1f million"
|
msgid "%(value).1f million"
|
||||||
msgid_plural "%(value).1f million"
|
msgid_plural "%(value).1f million"
|
||||||
msgstr[0] ""
|
msgstr[0] ""
|
||||||
msgstr[1] ""
|
msgstr[1] ""
|
||||||
|
|
||||||
#: templatetags/humanize.py:75
|
#: templatetags/humanize.py:79
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(value)s million"
|
msgid "%(value)s million"
|
||||||
msgid_plural "%(value)s million"
|
msgid_plural "%(value)s million"
|
||||||
msgstr[0] ""
|
msgstr[0] ""
|
||||||
msgstr[1] ""
|
msgstr[1] ""
|
||||||
|
|
||||||
#: templatetags/humanize.py:80
|
#: templatetags/humanize.py:84
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(value).1f billion"
|
msgid "%(value).1f billion"
|
||||||
msgid_plural "%(value).1f billion"
|
msgid_plural "%(value).1f billion"
|
||||||
msgstr[0] ""
|
msgstr[0] ""
|
||||||
msgstr[1] ""
|
msgstr[1] ""
|
||||||
|
|
||||||
#: templatetags/humanize.py:81
|
#: templatetags/humanize.py:85
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(value)s billion"
|
msgid "%(value)s billion"
|
||||||
msgid_plural "%(value)s billion"
|
msgid_plural "%(value)s billion"
|
||||||
msgstr[0] ""
|
msgstr[0] ""
|
||||||
msgstr[1] ""
|
msgstr[1] ""
|
||||||
|
|
||||||
#: templatetags/humanize.py:86
|
#: templatetags/humanize.py:90
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(value).1f trillion"
|
msgid "%(value).1f trillion"
|
||||||
msgid_plural "%(value).1f trillion"
|
msgid_plural "%(value).1f trillion"
|
||||||
msgstr[0] ""
|
msgstr[0] ""
|
||||||
msgstr[1] ""
|
msgstr[1] ""
|
||||||
|
|
||||||
#: templatetags/humanize.py:87
|
#: templatetags/humanize.py:91
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%(value)s trillion"
|
msgid "%(value)s trillion"
|
||||||
msgid_plural "%(value)s trillion"
|
msgid_plural "%(value)s trillion"
|
||||||
msgstr[0] ""
|
msgstr[0] ""
|
||||||
msgstr[1] ""
|
msgstr[1] ""
|
||||||
|
|
||||||
#: templatetags/humanize.py:104
|
#: templatetags/humanize.py:108
|
||||||
msgid "one"
|
msgid "one"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templatetags/humanize.py:104
|
#: templatetags/humanize.py:108
|
||||||
msgid "two"
|
msgid "two"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templatetags/humanize.py:104
|
#: templatetags/humanize.py:108
|
||||||
msgid "three"
|
msgid "three"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templatetags/humanize.py:104
|
#: templatetags/humanize.py:108
|
||||||
msgid "four"
|
msgid "four"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templatetags/humanize.py:104
|
#: templatetags/humanize.py:108
|
||||||
msgid "five"
|
msgid "five"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templatetags/humanize.py:104
|
#: templatetags/humanize.py:108
|
||||||
msgid "six"
|
msgid "six"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templatetags/humanize.py:104
|
#: templatetags/humanize.py:108
|
||||||
msgid "seven"
|
msgid "seven"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templatetags/humanize.py:104
|
#: templatetags/humanize.py:108
|
||||||
msgid "eight"
|
msgid "eight"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templatetags/humanize.py:104
|
#: templatetags/humanize.py:108
|
||||||
msgid "nine"
|
msgid "nine"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templatetags/humanize.py:127
|
#: templatetags/humanize.py:131
|
||||||
msgid "today"
|
msgid "today"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templatetags/humanize.py:129
|
#: templatetags/humanize.py:133
|
||||||
msgid "tomorrow"
|
msgid "tomorrow"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templatetags/humanize.py:131
|
#: templatetags/humanize.py:135
|
||||||
msgid "yesterday"
|
msgid "yesterday"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templatetags/humanize.py:153
|
#: templatetags/humanize.py:160
|
||||||
|
#, python-format
|
||||||
|
msgctxt "naturaltime"
|
||||||
|
msgid "%(delta)s ago"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templatetags/humanize.py:163 templatetags/humanize.py:185
|
||||||
msgid "now"
|
msgid "now"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: templatetags/humanize.py:155
|
#: templatetags/humanize.py:166
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "%s seconds ago"
|
msgid "a second ago"
|
||||||
msgid_plural "%s seconds ago"
|
msgid_plural "%(count)s seconds ago"
|
||||||
msgstr[0] ""
|
msgstr[0] ""
|
||||||
msgstr[1] ""
|
msgstr[1] ""
|
||||||
|
|
||||||
#: templatetags/humanize.py:157
|
#: templatetags/humanize.py:171
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "a minute ago"
|
msgid "a minute ago"
|
||||||
msgid_plural "%s minutes ago"
|
msgid_plural "%(count)s minutes ago"
|
||||||
msgstr[0] ""
|
msgstr[0] ""
|
||||||
msgstr[1] ""
|
msgstr[1] ""
|
||||||
|
|
||||||
#: templatetags/humanize.py:159
|
#: templatetags/humanize.py:176
|
||||||
#, python-format
|
#, python-format
|
||||||
msgid "an hour ago"
|
msgid "an hour ago"
|
||||||
msgid_plural "%s hours ago"
|
msgid_plural "%(count)s hours ago"
|
||||||
|
msgstr[0] ""
|
||||||
|
msgstr[1] ""
|
||||||
|
|
||||||
|
#: templatetags/humanize.py:182
|
||||||
|
#, python-format
|
||||||
|
msgctxt "naturaltime"
|
||||||
|
msgid "%(delta)s from now"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: templatetags/humanize.py:188
|
||||||
|
#, python-format
|
||||||
|
msgid "a second from now"
|
||||||
|
msgid_plural "%(count)s seconds from now"
|
||||||
|
msgstr[0] ""
|
||||||
|
msgstr[1] ""
|
||||||
|
|
||||||
|
#: templatetags/humanize.py:193
|
||||||
|
#, python-format
|
||||||
|
msgid "a minute from now"
|
||||||
|
msgid_plural "%(count)s minutes from now"
|
||||||
|
msgstr[0] ""
|
||||||
|
msgstr[1] ""
|
||||||
|
|
||||||
|
#: templatetags/humanize.py:198
|
||||||
|
#, python-format
|
||||||
|
msgid "an hour from now"
|
||||||
|
msgid_plural "%(count)s hours from now"
|
||||||
msgstr[0] ""
|
msgstr[0] ""
|
||||||
msgstr[1] ""
|
msgstr[1] ""
|
||||||
|
|
|
@ -1,11 +1,15 @@
|
||||||
from django.utils.translation import ungettext, ugettext as _
|
import re
|
||||||
|
from datetime import date, datetime, timedelta
|
||||||
|
|
||||||
|
from django import template
|
||||||
|
from django.conf import settings
|
||||||
|
from django.template import defaultfilters
|
||||||
|
from django.utils.datetime_safe import datetime, date
|
||||||
from django.utils.encoding import force_unicode
|
from django.utils.encoding import force_unicode
|
||||||
from django.utils.formats import number_format
|
from django.utils.formats import number_format
|
||||||
from django import template
|
from django.utils.translation import pgettext, ungettext, ugettext as _
|
||||||
from django.template import defaultfilters
|
from django.utils.tzinfo import LocalTimezone
|
||||||
from django.conf import settings
|
|
||||||
from datetime import date, datetime
|
|
||||||
import re
|
|
||||||
|
|
||||||
register = template.Library()
|
register = template.Library()
|
||||||
|
|
||||||
|
@ -132,11 +136,10 @@ def naturalday(value, arg=None):
|
||||||
return defaultfilters.date(value, arg)
|
return defaultfilters.date(value, arg)
|
||||||
|
|
||||||
@register.filter
|
@register.filter
|
||||||
def naturaltime(value, arg=None):
|
def naturaltime(value):
|
||||||
"""
|
"""
|
||||||
For date and time values shows how many seconds, minutes or hours ago compared to
|
For date and time values shows how many seconds, minutes or hours ago
|
||||||
current timestamp returns representing string. Otherwise, returns a string
|
compared to current timestamp returns representing string.
|
||||||
formatted according to settings.DATE_FORMAT
|
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
value = datetime(value.year, value.month, value.day, value.hour, value.minute, value.second)
|
value = datetime(value.year, value.month, value.day, value.hour, value.minute, value.second)
|
||||||
|
@ -145,16 +148,52 @@ def naturaltime(value, arg=None):
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return value
|
return value
|
||||||
|
|
||||||
delta = datetime.now() - value
|
if getattr(value, 'tzinfo', None):
|
||||||
|
now = datetime.now(LocalTimezone(value))
|
||||||
|
else:
|
||||||
|
now = datetime.now()
|
||||||
|
now = now - timedelta(0, 0, now.microsecond)
|
||||||
|
if value < now:
|
||||||
|
delta = now - value
|
||||||
if delta.days != 0:
|
if delta.days != 0:
|
||||||
value = date(value.year, value.month, value.day)
|
return pgettext(
|
||||||
return naturalday(value, arg)
|
'naturaltime', '%(delta)s ago'
|
||||||
|
) % {'delta': defaultfilters.timesince(value)}
|
||||||
elif delta.seconds == 0:
|
elif delta.seconds == 0:
|
||||||
return _(u'now')
|
return _(u'now')
|
||||||
elif delta.seconds < 60:
|
elif delta.seconds < 60:
|
||||||
return ungettext(u'%s seconds ago', u'%s seconds ago', delta.seconds)
|
return ungettext(
|
||||||
|
u'a second ago', u'%(count)s seconds ago', delta.seconds
|
||||||
|
) % {'count': delta.seconds}
|
||||||
elif delta.seconds / 60 < 60:
|
elif delta.seconds / 60 < 60:
|
||||||
return ungettext(u'a minute ago', u'%s minutes ago', delta.seconds/60)
|
count = delta.seconds / 60
|
||||||
elif delta.seconds / 60 / 60 < 24:
|
return ungettext(
|
||||||
return ungettext(u'an hour ago', u'%s hours ago', delta.seconds/60/60)
|
u'a minute ago', u'%(count)s minutes ago', count
|
||||||
return naturalday(value, arg)
|
) % {'count': count}
|
||||||
|
else:
|
||||||
|
count = delta.seconds / 60 / 60
|
||||||
|
return ungettext(
|
||||||
|
u'an hour ago', u'%(count)s hours ago', count
|
||||||
|
) % {'count': count}
|
||||||
|
else:
|
||||||
|
delta = value - now
|
||||||
|
if delta.days != 0:
|
||||||
|
return pgettext(
|
||||||
|
'naturaltime', '%(delta)s from now'
|
||||||
|
) % {'delta': defaultfilters.timeuntil(value)}
|
||||||
|
elif delta.seconds == 0:
|
||||||
|
return _(u'now')
|
||||||
|
elif delta.seconds < 60:
|
||||||
|
return ungettext(
|
||||||
|
u'a second from now', u'%(count)s seconds from now', delta.seconds
|
||||||
|
) % {'count': delta.seconds}
|
||||||
|
elif delta.seconds / 60 < 60:
|
||||||
|
count = delta.seconds / 60
|
||||||
|
return ungettext(
|
||||||
|
u'a minute from now', u'%(count)s minutes from now', count
|
||||||
|
) % {'count': count}
|
||||||
|
else:
|
||||||
|
count = delta.seconds / 60 / 60
|
||||||
|
return ungettext(
|
||||||
|
u'an hour from now', u'%(count)s hours from now', count
|
||||||
|
) % {'count': count}
|
||||||
|
|
|
@ -104,9 +104,8 @@ naturaltime
|
||||||
|
|
||||||
For datetime values, returns a string representing how many seconds,
|
For datetime values, returns a string representing how many seconds,
|
||||||
minutes or hours ago it was -- falling back to a longer date format if the
|
minutes or hours ago it was -- falling back to a longer date format if the
|
||||||
value is more than a day old.
|
value is more than a day old. In case the datetime value is in the future
|
||||||
|
the return value will automatically use an appropriate phrase.
|
||||||
**Argument:** Date formatting string as described in the :tfilter:`date` tag.
|
|
||||||
|
|
||||||
Examples (when 'now' is 17 Feb 2007 16:30:00):
|
Examples (when 'now' is 17 Feb 2007 16:30:00):
|
||||||
|
|
||||||
|
@ -116,9 +115,13 @@ Examples (when 'now' is 17 Feb 2007 16:30:00):
|
||||||
* ``17 Feb 2007 16:25:35`` becomes ``4 minutes ago``.
|
* ``17 Feb 2007 16:25:35`` becomes ``4 minutes ago``.
|
||||||
* ``17 Feb 2007 15:30:29`` becomes ``an hour ago``.
|
* ``17 Feb 2007 15:30:29`` becomes ``an hour ago``.
|
||||||
* ``17 Feb 2007 13:31:29`` becomes ``2 hours ago``.
|
* ``17 Feb 2007 13:31:29`` becomes ``2 hours ago``.
|
||||||
* ``16 Feb 2007 13:31:29`` becomes ``yesterday``.
|
* ``16 Feb 2007 13:31:29`` becomes ``1 day ago``.
|
||||||
* Any other day is formatted according to given argument or the
|
* ``17 Feb 2007 16:30:30`` becomes ``29 seconds from now``.
|
||||||
:setting:`DATE_FORMAT` setting if no argument is given.
|
* ``17 Feb 2007 16:31:00`` becomes ``a minute from now``.
|
||||||
|
* ``17 Feb 2007 16:34:35`` becomes ``4 minutes from now``.
|
||||||
|
* ``17 Feb 2007 16:30:29`` becomes ``an hour from now``.
|
||||||
|
* ``17 Feb 2007 18:31:29`` becomes ``2 hours from now``.
|
||||||
|
* ``18 Feb 2007 16:31:29`` becomes ``1 day from now``.
|
||||||
|
|
||||||
.. templatefilter:: ordinal
|
.. templatefilter:: ordinal
|
||||||
|
|
||||||
|
|
|
@ -89,31 +89,6 @@ class HumanizeTests(TestCase):
|
||||||
someday_result, u"I'm not a date value", None)
|
someday_result, u"I'm not a date value", None)
|
||||||
self.humanize_tester(test_list, result_list, 'naturalday')
|
self.humanize_tester(test_list, result_list, 'naturalday')
|
||||||
|
|
||||||
def test_naturaltime(self):
|
|
||||||
from django.template import defaultfilters
|
|
||||||
now = datetime.now()
|
|
||||||
seconds_ago = now - timedelta(seconds=30)
|
|
||||||
a_minute_ago = now - timedelta(minutes=1, seconds=30)
|
|
||||||
minutes_ago = now - timedelta(minutes=2)
|
|
||||||
an_hour_ago = now - timedelta(hours=1, minutes=30, seconds=30)
|
|
||||||
hours_ago = now - timedelta(hours=23, minutes=50, seconds=50)
|
|
||||||
|
|
||||||
test_list = (now, a_minute_ago, an_hour_ago)
|
|
||||||
result_list = (_(u'now'), _(u'a minute ago'), _(u'an hour ago'))
|
|
||||||
self.humanize_tester(test_list, result_list, 'naturaltime')
|
|
||||||
|
|
||||||
t = Template('{{ seconds_ago|%s }}' % 'naturaltime')
|
|
||||||
rendered = t.render(Context(locals())).strip()
|
|
||||||
self.assertTrue(u' seconds ago' in rendered)
|
|
||||||
|
|
||||||
t = Template('{{ minutes_ago|%s }}' % 'naturaltime')
|
|
||||||
rendered = t.render(Context(locals())).strip()
|
|
||||||
self.assertTrue(u' minutes ago' in rendered)
|
|
||||||
|
|
||||||
t = Template('{{ hours_ago|%s }}' % 'naturaltime')
|
|
||||||
rendered = t.render(Context(locals())).strip()
|
|
||||||
self.assertTrue(u' hours ago' in rendered)
|
|
||||||
|
|
||||||
def test_naturalday_tz(self):
|
def test_naturalday_tz(self):
|
||||||
from django.contrib.humanize.templatetags.humanize import naturalday
|
from django.contrib.humanize.templatetags.humanize import naturalday
|
||||||
|
|
||||||
|
@ -130,3 +105,45 @@ class HumanizeTests(TestCase):
|
||||||
|
|
||||||
# As 24h of difference they will never be the same
|
# As 24h of difference they will never be the same
|
||||||
self.assertNotEqual(naturalday_one, naturalday_two)
|
self.assertNotEqual(naturalday_one, naturalday_two)
|
||||||
|
|
||||||
|
def test_naturaltime(self):
|
||||||
|
now = datetime.now()
|
||||||
|
test_list = [
|
||||||
|
now,
|
||||||
|
now - timedelta(seconds=1),
|
||||||
|
now - timedelta(seconds=30),
|
||||||
|
now - timedelta(minutes=1, seconds=30),
|
||||||
|
now - timedelta(minutes=2),
|
||||||
|
now - timedelta(hours=1, minutes=30, seconds=30),
|
||||||
|
now - timedelta(hours=23, minutes=50, seconds=50),
|
||||||
|
now - timedelta(days=1),
|
||||||
|
now - timedelta(days=500),
|
||||||
|
now + timedelta(seconds=1),
|
||||||
|
now + timedelta(seconds=30),
|
||||||
|
now + timedelta(minutes=1, seconds=30),
|
||||||
|
now + timedelta(minutes=2),
|
||||||
|
now + timedelta(hours=1, minutes=30, seconds=30),
|
||||||
|
now + timedelta(hours=23, minutes=50, seconds=50),
|
||||||
|
now + timedelta(days=1),
|
||||||
|
now + timedelta(days=500),
|
||||||
|
]
|
||||||
|
result_list = [
|
||||||
|
'now',
|
||||||
|
'a second ago',
|
||||||
|
'30 seconds ago',
|
||||||
|
'a minute ago',
|
||||||
|
'2 minutes ago',
|
||||||
|
'an hour ago',
|
||||||
|
'23 hours ago',
|
||||||
|
'1 day ago',
|
||||||
|
'1 year, 4 months ago',
|
||||||
|
'a second from now',
|
||||||
|
'30 seconds from now',
|
||||||
|
'a minute from now',
|
||||||
|
'2 minutes from now',
|
||||||
|
'an hour from now',
|
||||||
|
'23 hours from now',
|
||||||
|
'1 day from now',
|
||||||
|
'1 year, 4 months from now',
|
||||||
|
]
|
||||||
|
self.humanize_tester(test_list, result_list, 'naturaltime')
|
||||||
|
|
Loading…
Reference in New Issue