Skip to content

Instantly share code, notes, and snippets.

@jonlabelle
Forked from zhangsen/relative_time.py
Last active November 23, 2019 17:45
Show Gist options
  • Save jonlabelle/7d306575cbbd34b154f87b1853d532cc to your computer and use it in GitHub Desktop.
Save jonlabelle/7d306575cbbd34b154f87b1853d532cc to your computer and use it in GitHub Desktop.
python-relative-time
from datetime import datetime, timedelta
def relative_time(date):
"""Take a datetime and return its "age" as a string.
The age can be in second, minute, hour, day, month or year. Only the
biggest unit is considered, e.g. if it's 2 days and 3 hours, "2 days" will
be returned.
Make sure date is not in the future, or else it won't work.
Original Gist by 'zhangsen' @ https://gist.github.com/zhangsen/1199964
"""
def formatn(n, s):
"""Add "s" if it's plural"""
if n == 1:
return "1 %s" % s
elif n > 1:
return "%d %ss" % (n, s)
def qnr(a, b):
"""Return quotient and remaining"""
return a / b, a % b
class FormatDelta:
def __init__(self, dt):
now = datetime.now()
delta = now - dt
self.day = delta.days
self.second = delta.seconds
self.year, self.day = qnr(self.day, 365)
self.month, self.day = qnr(self.day, 30)
self.hour, self.second = qnr(self.second, 3600)
self.minute, self.second = qnr(self.second, 60)
def format(self):
for period in ['year', 'month', 'day', 'hour', 'minute', 'second']:
n = getattr(self, period)
if n >= 1:
return '{0} ago'.format(formatn(n, period))
return "just now"
return FormatDelta(date).format()
#
# EXAMPLES
#
just_now = relative_time(datetime.now()) # >>> just now
ten_years_ago = relative_time(datetime(2008, 9, 1)) # >>> 11 years ago
six_years_ago = relative_time(datetime.now() - timedelta(days=6)) # >>> 6 days ago
twenty_minutes = relative_time(datetime.now() - timedelta(minutes=20)) # >>> 20 minutes ago
print('')
print('just now............: {0}'.format(just_now))
print('ten years ago.......: {0}'.format(ten_years_ago))
print('six years ago.......: {0}'.format(six_years_ago))
print('twenty minutes ago..: {0}'.format(twenty_minutes))
@spencerpogo
Copy link

This code is good except on line 44 I found that n can be a decimal, making n > 0 pass but formatn() still not return anything, making certain strings show up as None ago.
Line 44 should be if n >= 1 to fix this problem. Also, you might want to put an else in formatn() on line 23 that raises an error so as to not silently return None.

@jonlabelle
Copy link
Author

Gist updated... thanks @Scoder12!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment