Often there is a task to bring the date and/or time from the standard absolute view (18:03) to the view which is relative to the current moment (5 minutes ago). This task is called humanization. Indeed, in many cases it is more convenient to understand that the event happened 'a minute ago', '2 days ago', 'a week ago' rather than trying to gure out the difference yourself.
If you like to do everything yourself, then it's easy to write the appropriate function to fit your needs. It might look like this, for example.
from datetime import datetime, timedelta
def my_humanize(dt):
# get the interval from the < dt > to the current moment in seconds
interval = int((datetime.now() - dt).total_seconds())
# edge case of < dt> is now
if interval == 0:
return "just now"
elif interval > 0:
keyword = "ago"
else:
keyword = "later"
interval = -interval
names = ["second", "minute", "hour", "day", "week", "month", "year"]
multipliers = [1, 60, 3600, 3600*24, 3600*24*7, 3660*24*30, 3660*24*30*12]
pretty = ""
for i, m in enumerate(multipliers[::-1]):
value = interval // m
interval -= value * m
if value != 0:
if value == 1: # take the singular into account
pretty += f"{value} {names[-(i+1)]} "
else:
pretty += f"{value} {names[-(i+1)]}s "
return pretty + keyword
print(my_humanize(datetime.now() - timedelta(hours=3, minutes=2, seconds = 1)))
print(my_humanize(datetime.now() - timedelta(hours = 50000, minutes = 15, seconds = 12)))
print(my_humanize(datetime.now() + timedelta(hours = 15)))
print(my_humanize(datetime.now()))
3 hours 2 minutes 1 second ago
5 years 8 months 1 week 2 days 8 hours 15 minutes 12 seconds ago
14 hours 59 minutes 59 seconds later
just now.
We calculate the interval from the argument < dt > to the current moment in seconds. Then we calculate the result of dividing without remainder by each factor from year to second sequentially. And each time we pass only the remainder to the next iteration.
This approach, when you write everything yourself, may not always be appropriate. A more pythonic way is to nd a suitable published module. One of these modules is humanize. You can install it by the following command.
pip install humanize
Requirement already satisfied: humanize in /usr/local/lib/python3.6/dist-packages (0
Then you can import the module and try it. This module contains several functions for the humanized display of various data. The function for humanizing the date is called naturaltime.
from humanize import naturaltime from datetime import datetime, timedelta print(naturaltime(datetime.now() - timedelta(seconds = 1))) print(naturaltime(datetime.now() - timedelta(hours = 50000, minutes = 15, seconds = 12))) print(naturaltime(datetime.now() + timedelta(hours = 15))) print(naturaltime(datetime.now()))
a second ago 5 years ago 14 hours from now now
One of the key advantages of this module is embedded localization for many languages. In particular for Russian, German, Spanish, French, Chinese. You can find more details in the module documentation. For example, you can enable the French localization like this.
_t = humanize.i18n.activate('fr') print(naturaltime(datetime.now() + timedelta(hours = 15))) print(naturaltime(datetime.now()))
dans 14 heures maintenant
To deactivate localization.
humanize.i18n.deactivate()
There is another interesting module called arrow. Let's install and try it too.
pip install arrow
Collecting arrow Downloading https://files.pythonhosted.org/packages/ca/bc/ebc1afb3c54377e128a01024c |████████████████████████████████| 51kB 2.3MB/s Requirement already satisfied: python-dateutil>=2.7.0 in /usr/local/lib/python3.6/dis Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.6/dist-packages (fr Installing collected packages: arrow Successfully installed arrow-0.17.0
A feature of this module is the use of its own time format. This can be both an advantage and a disadvantage. The display of this format is often more convenient than the standard datetime object. But to use a standard datetime object it needs to be converted. To humanize date we use humanize method of arrow datetime object.
import arrow time1 = arrow.get(datetime.now() - timedelta(seconds = 10)) print(time1.humanize()) time2 = arrow.get(datetime.now() - timedelta(hours = 50000, minutes = 15, seconds = 12)) print(time2.humanize()) time3 = arrow.get(datetime.now() + timedelta(hours = 50, minutes = 15, seconds = 12)) print(time3.humanize())
10 seconds ago 5 years ago in 2 days
The advantage of this module over the previous one is in exible display settings. For this, a special argument granularity is used. Let's take the time2 variable from the previous example and humanize it with different granularity settings.
print(time2.humanize(granularity=["year", "month", "day", "hour", "minute"])) print(time2.humanize(granularity=["year", "hour", "minute"])) print(time2.humanize(granularity=["minute"]))
5 years 8 months 13 days 2 hours and 24 minutes ago 5 years 6170 hours and 24 minutes ago 3000024 minutes ago
We have considered several options for humanizing the date and time objects in Python.
Each of the options has its own pros and cons. The most exible but also most time consuming option is to write the function yourself.
If you need localization, you should use humanize module.If you need exibility in display and are satis ed with the necessity for conversion, then you can use arrow module.