From 6aaff28c139642593f97c157389f3f70ecafde41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adeodato=20Sim=C3=B3?= Date: Tue, 14 Nov 2023 20:27:44 -0300 Subject: [PATCH] Accept argument in naturalday_partial, downcast format if necessary --- bookwyrm/templatetags/date_ext.py | 22 +++++++++----- bookwyrm/tests/templatetags/test_date_ext.py | 31 ++++++++++++++++++++ 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/bookwyrm/templatetags/date_ext.py b/bookwyrm/templatetags/date_ext.py index d2490c13f..6dc320bed 100644 --- a/bookwyrm/templatetags/date_ext.py +++ b/bookwyrm/templatetags/date_ext.py @@ -8,15 +8,23 @@ from bookwyrm.utils.partial_date import PartialDate register = template.Library() -@register.filter(expects_localtime=True, is_safe=False) -def naturalday_partial(date): - """allow templates to easily format PartialDate objects""" +@register.filter(expects_localtime=True) +def naturalday_partial(date, arg=None): + """chooses appropriate precision if date is a PartialDate object + + If arg is a Django-defined format such as "DATE_FORMAT", it will be adjusted + so that the precision of the PartialDate object is honored. + """ + django_formats = ("DATE_FORMAT", "SHORT_DATE_FORMAT", "YEAR_MONTH_FORMAT") if not isinstance(date, PartialDate): - return defaultfilters.date(date) + return defaultfilters.date(date, arg) + if arg is None: + arg = "DATE_FORMAT" if date.has_day: - fmt = "DATE_FORMAT" + fmt = arg elif date.has_month: - fmt = "YEAR_MONTH_FORMAT" + # there is no SHORT_YEAR_MONTH_FORMAT, so we ignore SHORT_DATE_FORMAT :( + fmt = "YEAR_MONTH_FORMAT" if arg == "DATE_FORMAT" else arg else: - fmt = "Y" + fmt = "Y" if arg in django_formats else arg return naturalday(date, fmt) diff --git a/bookwyrm/tests/templatetags/test_date_ext.py b/bookwyrm/tests/templatetags/test_date_ext.py index a8eeb4233..f7ea73891 100644 --- a/bookwyrm/tests/templatetags/test_date_ext.py +++ b/bookwyrm/tests/templatetags/test_date_ext.py @@ -29,3 +29,34 @@ class PartialDateTags(TestCase): self.assertEqual("2023", date_ext.naturalday_partial(self._partial_year)) self.assertEqual("June 2023", date_ext.naturalday_partial(self._partial_month)) self.assertEqual("30 Jun 2023", date_ext.naturalday_partial(self._partial_day)) + + def test_format_arg_is_used(self): + """the provided format should be used by default""" + self.assertEqual("Dec.31", date_ext.naturalday_partial(self._dt, "M.j")) + self.assertEqual("Dec.31", date_ext.naturalday_partial(self._date, "M.j")) + self.assertEqual("June", date_ext.naturalday_partial(self._partial_day, "F")) + + def test_month_precision_downcast(self): + """precision is adjusted for well-known date formats""" + self.assertEqual( + "June 2023", date_ext.naturalday_partial(self._partial_month, "DATE_FORMAT") + ) + + def test_year_precision_downcast(self): + """precision is adjusted for well-known date formats""" + for fmt in "DATE_FORMAT", "SHORT_DATE_FORMAT", "YEAR_MONTH_FORMAT": + with self.subTest(desc=fmt): + self.assertEqual( + "2023", date_ext.naturalday_partial(self._partial_year, fmt) + ) + + def test_nonstandard_formats_passthru(self): + """garbage-in, garbage-out: we don't mess with unknown date formats""" + # Expected because there is no SHORT_YEAR_MONTH_FORMAT in Django that we can use + self.assertEqual( + "30/06/2023", + date_ext.naturalday_partial(self._partial_month, "SHORT_DATE_FORMAT"), + ) + self.assertEqual( + "December.31", date_ext.naturalday_partial(self._partial_year, "F.j") + )