From 14b5e074ba7a57a5421d5b7217141c63c9c481d5 Mon Sep 17 00:00:00 2001 From: Malcolm Tredinnick Date: Mon, 20 Aug 2007 08:50:08 +0000 Subject: [PATCH] Fixed #3311 -- Added naturalday filter to contrib.humanize. Thanks, Jyrki Pulliainen. git-svn-id: http://code.djangoproject.com/svn/django/trunk@5985 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- AUTHORS | 1 + .../contrib/humanize/templatetags/humanize.py | 27 +++++++++++++++++++ docs/add_ons.txt | 23 ++++++++++++++++ tests/regressiontests/humanize/tests.py | 22 ++++++++++++--- 4 files changed, 70 insertions(+), 3 deletions(-) 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()