Browse Source

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
Jannis Leidel 14 years ago
parent
commit
578a31fea3

BIN
django/contrib/humanize/locale/en/LC_MESSAGES/django.mo


+ 64 - 31
django/contrib/humanize/locale/en/LC_MESSAGES/django.po

@@ -4,7 +4,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: Django\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"
 "Last-Translator: Django team\n"
 "Language-Team: English <en@li.org>\n"
@@ -12,133 +12,166 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: templatetags/humanize.py:21
+#: templatetags/humanize.py:25
 msgid "th"
 msgstr ""
 
-#: templatetags/humanize.py:21
+#: templatetags/humanize.py:25
 msgid "st"
 msgstr ""
 
-#: templatetags/humanize.py:21
+#: templatetags/humanize.py:25
 msgid "nd"
 msgstr ""
 
-#: templatetags/humanize.py:21
+#: templatetags/humanize.py:25
 msgid "rd"
 msgstr ""
 
-#: templatetags/humanize.py:74
+#: templatetags/humanize.py:78
 #, python-format
 msgid "%(value).1f million"
 msgid_plural "%(value).1f million"
 msgstr[0] ""
 msgstr[1] ""
 
-#: templatetags/humanize.py:75
+#: templatetags/humanize.py:79
 #, python-format
 msgid "%(value)s million"
 msgid_plural "%(value)s million"
 msgstr[0] ""
 msgstr[1] ""
 
-#: templatetags/humanize.py:80
+#: templatetags/humanize.py:84
 #, python-format
 msgid "%(value).1f billion"
 msgid_plural "%(value).1f billion"
 msgstr[0] ""
 msgstr[1] ""
 
-#: templatetags/humanize.py:81
+#: templatetags/humanize.py:85
 #, python-format
 msgid "%(value)s billion"
 msgid_plural "%(value)s billion"
 msgstr[0] ""
 msgstr[1] ""
 
-#: templatetags/humanize.py:86
+#: templatetags/humanize.py:90
 #, python-format
 msgid "%(value).1f trillion"
 msgid_plural "%(value).1f trillion"
 msgstr[0] ""
 msgstr[1] ""
 
-#: templatetags/humanize.py:87
+#: templatetags/humanize.py:91
 #, python-format
 msgid "%(value)s trillion"
 msgid_plural "%(value)s trillion"
 msgstr[0] ""
 msgstr[1] ""
 
-#: templatetags/humanize.py:104
+#: templatetags/humanize.py:108
 msgid "one"
 msgstr ""
 
-#: templatetags/humanize.py:104
+#: templatetags/humanize.py:108
 msgid "two"
 msgstr ""
 
-#: templatetags/humanize.py:104
+#: templatetags/humanize.py:108
 msgid "three"
 msgstr ""
 
-#: templatetags/humanize.py:104
+#: templatetags/humanize.py:108
 msgid "four"
 msgstr ""
 
-#: templatetags/humanize.py:104
+#: templatetags/humanize.py:108
 msgid "five"
 msgstr ""
 
-#: templatetags/humanize.py:104
+#: templatetags/humanize.py:108
 msgid "six"
 msgstr ""
 
-#: templatetags/humanize.py:104
+#: templatetags/humanize.py:108
 msgid "seven"
 msgstr ""
 
-#: templatetags/humanize.py:104
+#: templatetags/humanize.py:108
 msgid "eight"
 msgstr ""
 
-#: templatetags/humanize.py:104
+#: templatetags/humanize.py:108
 msgid "nine"
 msgstr ""
 
-#: templatetags/humanize.py:127
+#: templatetags/humanize.py:131
 msgid "today"
 msgstr ""
 
-#: templatetags/humanize.py:129
+#: templatetags/humanize.py:133
 msgid "tomorrow"
 msgstr ""
 
-#: templatetags/humanize.py:131
+#: templatetags/humanize.py:135
 msgid "yesterday"
 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"
 msgstr ""
 
-#: templatetags/humanize.py:155
+#: templatetags/humanize.py:166
 #, python-format
-msgid "%s seconds ago"
-msgid_plural "%s seconds ago"
+msgid "a second ago"
+msgid_plural "%(count)s seconds ago"
 msgstr[0] ""
 msgstr[1] ""
 
-#: templatetags/humanize.py:157
+#: templatetags/humanize.py:171
 #, python-format
 msgid "a minute ago"
-msgid_plural "%s minutes ago"
+msgid_plural "%(count)s minutes ago"
 msgstr[0] ""
 msgstr[1] ""
 
-#: templatetags/humanize.py:159
+#: templatetags/humanize.py:176
 #, python-format
 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[1] ""

+ 62 - 23
django/contrib/humanize/templatetags/humanize.py

@@ -1,11 +1,15 @@
-from django.utils.translation import ungettext, ugettext as _
-from django.utils.encoding import force_unicode
-from django.utils.formats import number_format
+import re
+from datetime import date, datetime, timedelta
+
 from django import template
-from django.template import defaultfilters
 from django.conf import settings
-from datetime import date, datetime
-import re
+from django.template import defaultfilters
+from django.utils.datetime_safe import datetime, date
+from django.utils.encoding import force_unicode
+from django.utils.formats import number_format
+from django.utils.translation import pgettext, ungettext, ugettext as _
+from django.utils.tzinfo import LocalTimezone
+
 
 register = template.Library()
 
@@ -132,11 +136,10 @@ def naturalday(value, arg=None):
     return defaultfilters.date(value, arg)
 
 @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
-    current timestamp returns representing string. Otherwise, returns a string
-    formatted according to settings.DATE_FORMAT
+    For date and time values shows how many seconds, minutes or hours ago
+    compared to current timestamp returns representing string.
     """
     try:
         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:
         return value
 
-    delta = datetime.now() - value
-    if delta.days != 0:
-        value = date(value.year, value.month, value.day)
-        return naturalday(value, arg)
-    elif delta.seconds == 0:
-        return _(u'now')
-    elif delta.seconds < 60:
-        return ungettext(u'%s seconds ago', u'%s seconds ago', delta.seconds)
-    elif delta.seconds / 60 < 60:
-        return ungettext(u'a minute ago', u'%s minutes ago', delta.seconds/60)
-    elif delta.seconds / 60 / 60 < 24:
-        return ungettext(u'an hour ago', u'%s hours ago', delta.seconds/60/60)
-    return naturalday(value, arg)
+    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:
+            return pgettext(
+                'naturaltime', '%(delta)s ago'
+            ) % {'delta': defaultfilters.timesince(value)}
+        elif delta.seconds == 0:
+            return _(u'now')
+        elif delta.seconds < 60:
+            return ungettext(
+                u'a second ago', u'%(count)s seconds ago', delta.seconds
+            ) % {'count': delta.seconds}
+        elif delta.seconds / 60 < 60:
+            count = delta.seconds / 60
+            return ungettext(
+                u'a minute ago', u'%(count)s minutes ago', count
+            ) % {'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}

+ 9 - 6
docs/ref/contrib/humanize.txt

@@ -104,9 +104,8 @@ naturaltime
 
 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
-value is more than a day old.
-
-**Argument:** Date formatting string as described in the :tfilter:`date` tag.
+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.
 
 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 15:30:29`` becomes ``an hour ago``.
     * ``17 Feb 2007 13:31:29`` becomes ``2 hours ago``.
-    * ``16 Feb 2007 13:31:29`` becomes ``yesterday``.
-    * Any other day is formatted according to given argument or the
-      :setting:`DATE_FORMAT` setting if no argument is given.
+    * ``16 Feb 2007 13:31:29`` becomes ``1 day ago``.
+    * ``17 Feb 2007 16:30:30`` becomes ``29 seconds from now``.
+    * ``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
 

+ 42 - 25
tests/regressiontests/humanize/tests.py

@@ -89,31 +89,6 @@ class HumanizeTests(TestCase):
                        someday_result, u"I'm not a date value", None)
         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):
         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
         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')