diff --git a/AUTHORS b/AUTHORS
index ba18382a1c..c2d377f08c 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -226,6 +226,7 @@ answer newbie questions, and generally made Django that much better:
plisk
Daniel Poelzleithner
polpak@yahoo.com
+ Jyrki Pulliainen
Johann Queuniet
J. Rademaker
Michael Radziej
diff --git a/django/contrib/humanize/templatetags/humanize.py b/django/contrib/humanize/templatetags/humanize.py
index 699d9300b8..19591606f9 100644
--- a/django/contrib/humanize/templatetags/humanize.py
+++ b/django/contrib/humanize/templatetags/humanize.py
@@ -1,6 +1,9 @@
from django.utils.translation import ungettext, ugettext as _
from django.utils.encoding import force_unicode
from django import template
+from django.template import defaultfilters
+from django.conf import settings
+from datetime import date, timedelta
import re
register = template.Library()
@@ -67,3 +70,27 @@ def apnumber(value):
return value
return (_('one'), _('two'), _('three'), _('four'), _('five'), _('six'), _('seven'), _('eight'), _('nine'))[value-1]
register.filter(apnumber)
+
+def naturalday(value, arg=None):
+ """
+ For date values that are tomorrow, today or yesterday compared to
+ present day returns representing string. Otherwise, returns a string
+ formatted according to settings.DATE_FORMAT.
+ """
+ try:
+ value = 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()
+ if delta.days == 0:
+ return _(u'today')
+ elif delta.days == 1:
+ return _(u'tomorrow')
+ elif delta.days == -1:
+ return _(u'yesterday')
+ return defaultfilters.date(value, arg)
+register.filter(naturalday)
diff --git a/docs/add_ons.txt b/docs/add_ons.txt
index 8682208970..a1d78b8685 100644
--- a/docs/add_ons.txt
+++ b/docs/add_ons.txt
@@ -138,6 +138,29 @@ Examples:
You can pass in either an integer or a string representation of an integer.
+naturalday
+----------
+
+**New in Django development version**
+
+For dates that are the current day or within one day, return "today",
+"tomorrow" or "yesterday", as appropriate. Otherwise, format the date using
+the passed in format string.
+
+**Argument:** Date formatting string as described in default tag now_.
+
+.. _now: ../templates/#now
+
+Examples (when 'today' is 17 Feb 2007):
+
+ * ``16 Feb 2007`` becomes ``yesterday``.
+ * ``17 Feb 2007`` becomes ``today``.
+ * ``18 Feb 2007`` becomes ``tomorrow``.
+ * Any other day is formatted according to given argument or the
+ `DATE_FORMAT`_ setting if no argument is given.
+
+.. _DATE_FORMAT: ../settings/#date_format
+
flatpages
=========
diff --git a/tests/regressiontests/humanize/tests.py b/tests/regressiontests/humanize/tests.py
index f94d642973..196488ba6e 100644
--- a/tests/regressiontests/humanize/tests.py
+++ b/tests/regressiontests/humanize/tests.py
@@ -1,5 +1,8 @@
import unittest
+from datetime import timedelta, date
from django.template import Template, Context, add_to_builtins
+from django.utils.dateformat import DateFormat
+from django.utils.translation import ugettext as _
add_to_builtins('django.contrib.humanize.templatetags.humanize')
@@ -8,13 +11,12 @@ class HumanizeTests(unittest.TestCase):
def humanize_tester(self, test_list, result_list, method):
# Using max below ensures we go through both lists
# However, if the lists are not equal length, this raises an exception
- for index in xrange(len(max(test_list,result_list))):
+ for index in xrange(max(len(test_list), len(result_list))):
test_content = test_list[index]
t = Template('{{ test_content|%s }}' % method)
rendered = t.render(Context(locals())).strip()
self.assertEqual(rendered, result_list[index],
- msg="""%s test failed, produced %s,
-should've produced %s""" % (method, rendered, result_list[index]))
+ msg="%s test failed, produced %s, should've produced %s" % (method, rendered, result_list[index]))
def test_ordinal(self):
test_list = ('1','2','3','4','11','12',
@@ -49,6 +51,20 @@ should've produced %s""" % (method, rendered, result_list[index]))
self.humanize_tester(test_list, result_list, 'apnumber')
+ 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)
+ notdate = u"I'm not a date value"
+
+ test_list = (today, yesterday, tomorrow, someday, notdate)
+ someday_result = defaultfilters.date(someday)
+ 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')
+
if __name__ == '__main__':
unittest.main()