Repository: jmoiron/humanize

Issue:
naturaldate returns ambiguous values
```pycon
>>> import humanize
>>> from datetime import datetime, timedelta
>>> humanize.naturaldate(datetime.now()-timedelta(3))
'Jan 15'
>>> humanize.naturaldate(datetime.now()+timedelta(362))
'Jan 15'
```

I'd suggest to add the year for all dates that are more than about five months away. This would lead to the following output:

| date | naturaldate (executed in Jan 2015) |
| --- | --- |
| 2014-08-20 | Aug 20 |
| 2015-08-20 | Aug 20 2015 |
| 2014-06-20 | Jun 20 2014 |
| 2015-06-20 | Jun 20 |

(Even when only used for dates that are necessarily in the past, like "comment posted on ...", the current behaviour is not perfect: If I read "Jan 19" on Jan 18, 2015, I won't not assume it means Jan 19, 2014.)


Discussion:

Patch:
diff --git a/src/humanize/time.py b/src/humanize/time.py
index 7f68ff9..716648a 100644
--- a/src/humanize/time.py
+++ b/src/humanize/time.py
@@ -196,8 +196,8 @@ def naturalday(value, format="%b %d"):
 
 
 def naturaldate(value):
-    """Like naturalday, but will append a year for dates that are a year
-    ago or more."""
+    """Like naturalday, but append a year for dates more than about five months away.
+    """
     try:
         value = dt.date(value.year, value.month, value.day)
     except AttributeError:
@@ -207,6 +207,6 @@ def naturaldate(value):
         # Date arguments out of range
         return value
     delta = abs_timedelta(value - dt.date.today())
-    if delta.days >= 365:
+    if delta.days >= 5 * 365 / 12:
         return naturalday(value, "%b %d %Y")
     return naturalday(value)


Test patch:
diff --git a/tests/test_time.py b/tests/test_time.py
index 7217c64..f9f0be7 100644
--- a/tests/test_time.py
+++ b/tests/test_time.py
@@ -314,13 +314,13 @@ def test_naturalday(test_args, expected):
         (VALUE_ERROR_TEST, VALUE_ERROR_TEST),
         (OVERFLOW_ERROR_TEST, OVERFLOW_ERROR_TEST),
         (dt.date(2019, 2, 2), "Feb 02 2019"),
-        (dt.date(2019, 3, 2), "Mar 02"),
-        (dt.date(2019, 4, 2), "Apr 02"),
-        (dt.date(2019, 5, 2), "May 02"),
-        (dt.date(2019, 6, 2), "Jun 02"),
-        (dt.date(2019, 7, 2), "Jul 02"),
-        (dt.date(2019, 8, 2), "Aug 02"),
-        (dt.date(2019, 9, 2), "Sep 02"),
+        (dt.date(2019, 3, 2), "Mar 02 2019"),
+        (dt.date(2019, 4, 2), "Apr 02 2019"),
+        (dt.date(2019, 5, 2), "May 02 2019"),
+        (dt.date(2019, 6, 2), "Jun 02 2019"),
+        (dt.date(2019, 7, 2), "Jul 02 2019"),
+        (dt.date(2019, 8, 2), "Aug 02 2019"),
+        (dt.date(2019, 9, 2), "Sep 02 2019"),
         (dt.date(2019, 10, 2), "Oct 02"),
         (dt.date(2019, 11, 2), "Nov 02"),
         (dt.date(2019, 12, 2), "Dec 02"),
@@ -331,12 +331,12 @@ def test_naturalday(test_args, expected):
         (dt.date(2020, 5, 2), "May 02"),
         (dt.date(2020, 6, 2), "Jun 02"),
         (dt.date(2020, 7, 2), "Jul 02"),
-        (dt.date(2020, 8, 2), "Aug 02"),
-        (dt.date(2020, 9, 2), "Sep 02"),
-        (dt.date(2020, 10, 2), "Oct 02"),
-        (dt.date(2020, 11, 2), "Nov 02"),
-        (dt.date(2020, 12, 2), "Dec 02"),
-        (dt.date(2021, 1, 2), "Jan 02"),
+        (dt.date(2020, 8, 2), "Aug 02 2020"),
+        (dt.date(2020, 9, 2), "Sep 02 2020"),
+        (dt.date(2020, 10, 2), "Oct 02 2020"),
+        (dt.date(2020, 11, 2), "Nov 02 2020"),
+        (dt.date(2020, 12, 2), "Dec 02 2020"),
+        (dt.date(2021, 1, 2), "Jan 02 2021"),
         (dt.date(2021, 2, 2), "Feb 02 2021"),
     ],
 )