django-orchestra/orchestra/utils/humanize.py

152 lines
4.3 KiB
Python
Raw Normal View History

2014-07-22 21:47:01 +00:00
from datetime import datetime
from django.utils import timezone
from django.utils.translation import ungettext, ugettext as _
2016-04-06 19:00:16 +00:00
def verbose_time(n, units, ago='ago'):
2015-10-07 11:44:30 +00:00
if n >= 5:
2016-04-06 19:00:16 +00:00
return _("{n} {units} {ago}").format(n=int(n), units=units, ago=ago)
2014-09-03 13:56:02 +00:00
return ungettext(
2016-04-06 19:00:16 +00:00
_("{n:.1f} {s_units} {ago}"),
_("{n:.1f} {units} {ago}"), n
).format(n=n, units=units, s_units=units[:-1], ago=ago)
2014-07-22 21:47:01 +00:00
OLDER_CHUNKS = (
2015-10-07 11:44:30 +00:00
(365.0, 'years'),
(30.0, 'months'),
(7.0, 'weeks'),
2014-07-22 21:47:01 +00:00
)
def _un(singular__plural, n=None):
singular, plural = singular__plural
return ungettext(singular, plural, n)
def naturaldatetime(date, show_seconds=False):
2014-07-22 21:47:01 +00:00
"""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
2015-10-07 11:44:30 +00:00
hours = float(delta.seconds) / 3600
minutes = float(delta.seconds) / 60
2014-07-22 21:47:01 +00:00
seconds = delta.seconds
2014-09-03 13:56:02 +00:00
days = abs(days)
2016-04-06 19:00:16 +00:00
ago = ''
if right_now > date:
ago = 'ago'
2014-07-22 21:47:01 +00:00
if days == 0:
2015-10-07 11:44:30 +00:00
if int(hours) == 0:
if minutes >= 1 or not show_seconds:
2016-04-06 19:00:16 +00:00
return verbose_time(minutes, 'minutes', ago=ago)
2014-07-22 21:47:01 +00:00
else:
2016-04-06 19:00:16 +00:00
return verbose_time(seconds, 'seconds', ago=ago)
2014-07-22 21:47:01 +00:00
else:
2016-04-06 19:00:16 +00:00
return verbose_time(hours, 'hours', ago=ago)
2014-07-22 21:47:01 +00:00
if delta_midnight.days == 0:
2015-10-03 13:08:41 +00:00
date = timezone.localtime(date)
return _("yesterday at {time}").format(time=date.strftime('%H:%M'))
2014-07-22 21:47:01 +00:00
count = 0
2015-10-07 11:44:30 +00:00
for chunk, units in OLDER_CHUNKS:
2014-07-22 21:47:01 +00:00
if days < 7.0:
count = days + float(hours)/24
2016-04-06 19:00:16 +00:00
return verbose_time(count, 'days', ago=ago)
2014-07-22 21:47:01 +00:00
if days >= chunk:
count = (delta_midnight.days + 1) / chunk
2014-09-03 13:56:02 +00:00
count = abs(count)
2016-04-06 19:00:16 +00:00
return verbose_time(count, units, ago=ago)
2014-09-17 10:32:29 +00:00
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')
2014-09-26 15:05:20 +00:00
ago = ' ago'
2016-04-06 19:00:16 +00:00
if days < 0 or today < date:
2014-09-26 15:05:20 +00:00
ago = ''
days = abs(days)
delta_midnight = today - date
2014-09-17 10:32:29 +00:00
count = 0
2015-10-07 13:15:16 +00:00
for chunk, units in OLDER_CHUNKS:
2014-09-17 10:32:29 +00:00
if days < 7.0:
2014-09-26 15:05:20 +00:00
count = days
2016-04-06 19:00:16 +00:00
fmt = verbose_time(count, 'days', ago=ago)
2014-09-17 10:32:29 +00:00
return fmt.format(num=count, ago=ago)
if days >= chunk:
count = (delta_midnight.days + 1) / chunk
count = abs(count)
2016-04-06 19:00:16 +00:00
fmt = verbose_time(count, units, ago=ago)
2014-09-17 10:32:29 +00:00
return fmt.format(num=count, ago=ago)
2014-10-24 10:16:46 +00:00
def text2int(textnum, numwords={}):
if not numwords:
units = (
'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight',
'nine', 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen',
'sixteen', 'seventeen', 'eighteen', 'nineteen',
)
tens = ('', '', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety')
scales = ['hundred', 'thousand', 'million', 'billion', 'trillion']
numwords['and'] = (1, 0)
for idx, word in enumerate(units):
numwords[word] = (1, idx)
for idx, word in enumerate(tens):
numwords[word] = (1, idx * 10)
for idx, word in enumerate(scales):
numwords[word] = (10 ** (idx * 3 or 2), 0)
current = result = 0
for word in textnum.split():
word = word.lower()
if word not in numwords:
raise Exception("Illegal word: " + word)
scale, increment = numwords[word]
current = current * scale + increment
if scale > 100:
result += current
current = 0
return result + current
UNITS_CONVERSIONS = {
1024**4: ['TB', 'TiB', 'TERABYTES'],
1024**3: ['GB', 'GiB', 'GYGABYTES'],
1024**2: ['MB', 'MiB', 'MEGABYTES'],
1024: ['KB', 'KiB', 'KYLOBYTES'],
1: ['B', 'BYTES'],
}
def unit_to_bytes(unit):
2015-04-02 16:14:55 +00:00
for bytes, units in UNITS_CONVERSIONS.items():
if unit in units:
return bytes
raise KeyError("%s is not a valid unit." % unit)