sdispater / pendulum

Python datetimes made easy
https://pendulum.eustace.io
MIT License
6.13k stars 374 forks source link

Precision of diff_for_humans() #169

Open thijsvandien opened 6 years ago

thijsvandien commented 6 years ago

diff_for_humans() seems to always provide a very rough indication compared to in_words():

>>> this_moment = pendulum.now()
>>> later_moment = this_moment.add(weeks=5, days=4, seconds=20)
>>> later_moment.diff_for_humans()
'1 month from now'
>>> (later_moment - this_moment).in_words()
'1 month 1 week 1 day 20 seconds'

This encourages users to do something like (later_moment - this_moment).in_words() + ' from now', which is bad for localization.

How about adding an option to specify the desired precision? Forcing it to be fully precise is the opposite extreme, so I would rather go for something like a maximum number of units to use. For example:

>>> later_moment.diff_for_humans(precision=2)
'1 month and 1 week from now'
>>> later_moment.diff_for_humans(precision=3)
'1 month, 1 week and 1 day from now'
>>> this_moment.add(months=1).diff_for_humans(precision=3)
'1 month from now'

We could have a default precision=1 for backward compatibility.

sdispater commented 6 years ago

This is intended : diff_for_humans() is supposed to be a loose approximation. This is typically what you would see on websites (1 month ago).

This is not the same as in_words() which represents exactly a period or a duration in words.

They do not serve the same purpose, that's the main reason why I changed the Period.for_humans() method to Period.in_words(), to avoid this confusion.

So, for now, I don't plan on changing the diff_for_humans() method to introduce a precision setting , especially since it would lead to handling the translation for the and keyword in all supported languages for this specific use case.

Thanks for the suggestion though and thanks for your interest in Pendulum :-)

alertedsnake commented 4 years ago

I'd say "very rough" as to be almost unusable:

>>> now.diff(then).in_words()
'1 day 18 hours 45 minutes 24 seconds'
>>> now.diff(then).in_days()
2
>>> now.diff_for_humans(then, absolute=True)
'1 day'

I'm not sure this is a precision issue, it seems like a weird rounding issue to me. Why would diff_for_humans round down here?