Index: django/contrib/humanize/templatetags/humanize.py
===================================================================
--- django/contrib/humanize/templatetags/humanize.py	(revision 11726)
+++ django/contrib/humanize/templatetags/humanize.py	(working copy)
@@ -2,7 +2,7 @@
 from django.utils.encoding import force_unicode
 from django import template
 from django.template import defaultfilters
-from datetime import date
+import datetime
 import re
 
 register = template.Library()
@@ -81,14 +81,14 @@
     formatted according to settings.DATE_FORMAT.
     """
     try: 
-        value = date(value.year, value.month, value.day)
+        value = datetime.date(value.year, value.month, value.day)
     except AttributeError:
         # Passed value wasn't a date object
         return value
     except ValueError:
         # Date arguments out of range
         return value
-    delta = value - date.today()
+    delta = value - datetime.date.today()
     if delta.days == 0:
         return _(u'today')
     elif delta.days == 1:
@@ -97,3 +97,48 @@
         return _(u'yesterday')
     return defaultfilters.date(value, arg)
 register.filter(naturalday)
+
+def natural_timedelta(time1, time2=datetime.datetime.now()):
+    """
+    Express the difference in time between time1 and time2 (which defaults to
+    now) in a human-friendly way (e.g. 'about a minute').
+    """
+    try:
+        delta = abs(time1 - time2)
+        delta.days
+    except (ValueError, AttributeError, TypeError):
+        return time1
+    if delta.days == 0:
+        delta_days = 0
+        delta_minutes = int(round(delta.seconds / 60.0))
+        if delta.seconds in range(0, 50):
+            if delta.seconds in range(0, 5):
+                return _(u'less than %(count)d seconds') % {'count': 5}
+            elif delta.seconds in range(5, 10):
+                return _(u'less than %(count)d seconds') % {'count': 10}
+            elif delta.seconds in range(10, 20):
+                return _(u'less than %(count)d seconds') % {'count': 20}
+            elif delta.seconds in range(20, 40):
+                return _(u'about half a minute')
+            elif delta.seconds in range(40, 50):
+                return _(u'less than a minute')
+        elif delta_minutes in range(1, 20):
+            return ungettext(u'about a minute', u'about %(count)d minutes', delta_minutes) % {'count': delta_minutes}
+        elif delta_minutes in range(20, 45):
+            return _(u'about half an hour')
+        elif delta_minutes in range(45, 90):
+            return _(u'about an hour')
+        elif delta_minutes in range(90, 1440):
+            return _(u'about %(count)d hours') % {'count': int(round(delta_minutes / 60.0))}
+    else:
+        # Get a rounded number of days instead of timedelta's truncated days.
+        delta_days = int(round(delta.days + (delta.seconds / 86400.0)))
+    if delta_days in range(1, 30):
+        return ungettext(u'about a day', u'about %(count)d days', delta_days) % {'count': delta_days}
+    elif delta_days in range(30, 365):
+        count = round(delta_days / 30.4)
+        return ungettext(u'about a month', u'about %(count)d months', count) % {'count': count}
+    elif delta_days >= 365:
+        count = round(delta_days / 365.25)
+        return ungettext(u'about a year', u'about %(count)d years', count) % {'count': count}
+register.filter(natural_timedelta)
Index: tests/regressiontests/humanize/tests.py
===================================================================
--- tests/regressiontests/humanize/tests.py	(revision 11726)
+++ tests/regressiontests/humanize/tests.py	(working copy)
@@ -1,5 +1,5 @@
 import unittest
-from datetime import timedelta, date
+import datetime
 from django.template import Template, Context, add_to_builtins
 from django.utils.dateformat import DateFormat
 from django.utils.translation import ugettext as _
@@ -54,10 +54,10 @@
 
     def test_naturalday(self):
         from django.template import defaultfilters
-        today = date.today()
-        yesterday = today - timedelta(days=1)
-        tomorrow = today + timedelta(days=1)
-        someday = today - timedelta(days=10)
+        today = datetime.date.today()
+        yesterday = today - datetime.timedelta(days=1)
+        tomorrow = today + datetime.timedelta(days=1)
+        someday = today - datetime.timedelta(days=10)
         notdate = u"I'm not a date value"
 
         test_list = (today, yesterday, tomorrow, someday, notdate)
@@ -65,6 +65,73 @@
         result_list = (_(u'today'), _(u'yesterday'), _(u'tomorrow'),
                        someday_result, u"I'm not a date value")
         self.humanize_tester(test_list, result_list, 'naturalday')
+    
+    def test_natural_timedelta(self):
+        now = datetime.datetime.now()
+        
+        test_list = (
+            now,
+            now + datetime.timedelta(microseconds=4),
+            now + datetime.timedelta(seconds=4),
+            now + datetime.timedelta(seconds=9),
+            now + datetime.timedelta(seconds=19),
+            now + datetime.timedelta(seconds=31),
+            now + datetime.timedelta(seconds=45),
+            now + datetime.timedelta(seconds=55),
+            now + datetime.timedelta(seconds=60),
+            now + datetime.timedelta(seconds=121),
+            now + datetime.timedelta(seconds=400),
+            now + datetime.timedelta(seconds=1800),
+            now + datetime.timedelta(seconds=2700),
+            now + datetime.timedelta(seconds=3660),
+            now + datetime.timedelta(seconds=11880),
+            now + datetime.timedelta(seconds=82800),
+            now + datetime.timedelta(days=1),
+            now + datetime.timedelta(days=1.5),
+            now + datetime.timedelta(days=29),
+            now + datetime.timedelta(days=30),
+            now + datetime.timedelta(days=60),
+            now + datetime.timedelta(days=340),
+            now + datetime.timedelta(days=365),
+            now + datetime.timedelta(days=730.5),
+            now + datetime.timedelta(days=2922),
+            now - datetime.timedelta(seconds=45),
+            # Non-time-related inputs.
+            u'spam',
+            1,
+        )
+        result_list = (
+            _(u'less than 5 seconds'),
+            _(u'less than 5 seconds'),
+            _(u'less than 5 seconds'),
+            _(u'less than 10 seconds'),
+            _(u'less than 20 seconds'),
+            _(u'about half a minute'),
+            _(u'less than a minute'),
+            _(u'about a minute'),
+            _(u'about a minute'),
+            _(u'about 2 minutes'),
+            _(u'about 7 minutes'),
+            _(u'about half an hour'),
+            _(u'about an hour'),
+            _(u'about an hour'),
+            _(u'about 3 hours'),
+            _(u'about 23 hours'),
+            _(u'about a day'),
+            _(u'about 2 days'),
+            _(u'about 29 days'),
+            _(u'about a month'),
+            _(u'about 2 months'),
+            _(u'about 11 months'),
+            _(u'about a year'),
+            _(u'about 2 years'),
+            _(u'about 8 years'),
+            _(u'less than a minute'),
+            # Non-time-related outputs.
+            u'spam',
+            1,
+        )
+        self.humanize_tester(test_list, result_list, 'natural_timedelta')
 
 if __name__ == '__main__':
     unittest.main()
Index: docs/ref/contrib/humanize.txt
===================================================================
--- docs/ref/contrib/humanize.txt	(revision 11726)
+++ docs/ref/contrib/humanize.txt	(working copy)
@@ -89,3 +89,23 @@
     * ``18 Feb 2007`` becomes ``tomorrow``.
     * Any other day is formatted according to given argument or the
       :setting:`DATE_FORMAT` setting if no argument is given.
+
+natural_timedelta
+-----------------
+
+.. versionadded:: 1.2
+
+Determine the difference between one date and/or time object and another and
+return that difference in a human-friendly format.
+
+**Argument:** A date and/or time object (i.e. ``datetime.date``,
+``datetime.time`` or ``datetime.datetime``). Defaults to
+``datetime.datetime.now()`` if not given.
+
+Examples:
+
+    * A difference of 9 seconds becomes ``less than 10 seconds``.
+    * A difference of 30 seconds becomes ``about half a minute``.
+    * A difference of 1 minute, 10 seconds becomes ``about a minute``.
+    * A difference of 30 days becomes ``about a month``.
+    * A difference of 365 days becomes ``about a year``.
