from datetime import datetime from django.utils import timezone from django.utils.translation import ungettext, ugettext as _ def pluralize_year(n): return ungettext( _('{num:.1f} year{ago}'), _('{num:.1f} years{ago}'), n) def pluralize_month(n): return ungettext( _('{num:.1f} month{ago}'), _('{num:.1f} months{ago}'), n) def pluralize_week(n): return ungettext( _('{num:.1f} week{ago}'), _('{num:.1f} weeks {ago}'), n) def pluralize_day(n): return ungettext( _('{num:.1f} day{ago}'), _('{num:.1f} days{ago}'), n) OLDER_CHUNKS = ( (365.0, pluralize_year), (30.0, pluralize_month), (7.0, pluralize_week), ) def _un(singular__plural, n=None): singular, plural = singular__plural return ungettext(singular, plural, n) def naturaldatetime(date, include_seconds=False): """Convert datetime into a human natural date string.""" if not date: return '' right_now = timezone.now() today = datetime(right_now.year, right_now.month, right_now.day, tzinfo=right_now.tzinfo) delta = right_now - date delta_midnight = today - date days = delta.days hours = int(round(delta.seconds / 3600, 0)) minutes = delta.seconds / 60 seconds = delta.seconds ago = ' ago' if days < 0: ago = '' days = abs(days) if days == 0: if hours == 0: if minutes > 0: minutes += float(seconds)/60 return ungettext( _('{minutes:.1f} minute{ago}'), _('{minutes:.1f} minutes{ago}'), minutes ).format(minutes=minutes, ago=ago) else: if include_seconds and seconds: return ungettext( _('{seconds} second{ago}'), _('{seconds} seconds{ago}'), seconds ).format(seconds=seconds, ago=ago) return _('just now') else: hours += float(minutes)/60 return ungettext( _('{hours:.1f} hour{ago}'), _('{hours:.1f} hours{ago}'), hours ).format(hours=hours, ago=ago) if delta_midnight.days == 0: return _('yesterday at {time}').format(time=date.strftime('%H:%M')) count = 0 for chunk, pluralizefun in OLDER_CHUNKS: if days < 7.0: count = days + float(hours)/24 fmt = pluralize_day(count) return fmt.format(num=count, ago=ago) if days >= chunk: count = (delta_midnight.days + 1) / chunk count = abs(count) fmt = pluralizefun(count) return fmt.format(num=count, ago=ago) def naturaldate(date): if not date: return '' today = timezone.now().date() delta = today - date days = delta.days if days == 0: return _('today') elif days == 1: return _('yesterday') ago = ' ago' if days < 0: ago = '' days = abs(days) delta_midnight = today - date count = 0 for chunk, pluralizefun in OLDER_CHUNKS: if days < 7.0: count = days fmt = pluralize_day(count) return fmt.format(num=count, ago=ago) if days >= chunk: count = (delta_midnight.days + 1) / chunk count = abs(count) fmt = pluralizefun(count) return fmt.format(num=count, ago=ago)