Refactored naturaltime to use a class-based formatter
This commit is contained in:
parent
e0d0fc0b14
commit
56611a96df
|
@ -9,7 +9,8 @@ from django.utils.formats import number_format
|
|||
from django.utils.safestring import mark_safe
|
||||
from django.utils.timezone import is_aware, utc
|
||||
from django.utils.translation import (
|
||||
gettext as _, ngettext, npgettext_lazy, pgettext,
|
||||
gettext as _, gettext_lazy, ngettext, ngettext_lazy, npgettext_lazy,
|
||||
pgettext,
|
||||
)
|
||||
|
||||
register = template.Library()
|
||||
|
@ -214,79 +215,89 @@ def naturaltime(value):
|
|||
For date and time values show how many seconds, minutes, or hours ago
|
||||
compared to current timestamp return representing string.
|
||||
"""
|
||||
if not isinstance(value, date): # datetime is a subclass of date
|
||||
return value
|
||||
return NaturalTimeFormatter.string_for(value)
|
||||
|
||||
now = datetime.now(utc if is_aware(value) else None)
|
||||
if value < now:
|
||||
delta = now - value
|
||||
if delta.days != 0:
|
||||
# Translators: delta will contain a string like '2 months' or '1 month, 2 weeks'
|
||||
return _('%(delta)s ago') % {'delta': defaultfilters.timesince(value, now, time_strings={
|
||||
# Translators: 'naturaltime-past' strings will be included in
|
||||
# '%(delta)s ago'
|
||||
'year': npgettext_lazy('naturaltime-past', '%d year', '%d years'),
|
||||
'month': npgettext_lazy('naturaltime-past', '%d month', '%d months'),
|
||||
'week': npgettext_lazy('naturaltime-past', '%d week', '%d weeks'),
|
||||
'day': npgettext_lazy('naturaltime-past', '%d day', '%d days'),
|
||||
'hour': npgettext_lazy('naturaltime-past', '%d hour', '%d hours'),
|
||||
'minute': npgettext_lazy('naturaltime-past', '%d minute', '%d minutes')
|
||||
})}
|
||||
elif delta.seconds == 0:
|
||||
return _('now')
|
||||
elif delta.seconds < 60:
|
||||
return ngettext(
|
||||
# Translators: please keep a non-breaking space (U+00A0)
|
||||
# between count and time unit.
|
||||
'a second ago', '%(count)s seconds ago', delta.seconds
|
||||
) % {'count': delta.seconds}
|
||||
elif delta.seconds // 60 < 60:
|
||||
count = delta.seconds // 60
|
||||
return ngettext(
|
||||
# Translators: please keep a non-breaking space (U+00A0)
|
||||
# between count and time unit.
|
||||
'a minute ago', '%(count)s minutes ago', count
|
||||
) % {'count': count}
|
||||
|
||||
class NaturalTimeFormatter:
|
||||
time_strings = {
|
||||
# Translators: delta will contain a string like '2 months' or '1 month, 2 weeks'
|
||||
'past-day': gettext_lazy('%(delta)s ago'),
|
||||
# Translators: please keep a non-breaking space (U+00A0) between count
|
||||
# and time unit.
|
||||
'past-hour': ngettext_lazy('an hour ago', '%(count)s hours ago', 'count'),
|
||||
# Translators: please keep a non-breaking space (U+00A0) between count
|
||||
# and time unit.
|
||||
'past-minute': ngettext_lazy('a minute ago', '%(count)s minutes ago', 'count'),
|
||||
# Translators: please keep a non-breaking space (U+00A0) between count
|
||||
# and time unit.
|
||||
'past-second': ngettext_lazy('a second ago', '%(count)s seconds ago', 'count'),
|
||||
'now': gettext_lazy('now'),
|
||||
# Translators: please keep a non-breaking space (U+00A0) between count
|
||||
# and time unit.
|
||||
'future-second': ngettext_lazy('a second from now', '%(count)s seconds from now', 'count'),
|
||||
# Translators: please keep a non-breaking space (U+00A0) between count
|
||||
# and time unit.
|
||||
'future-minute': ngettext_lazy('a minute from now', '%(count)s minutes from now', 'count'),
|
||||
# Translators: please keep a non-breaking space (U+00A0) between count
|
||||
# and time unit.
|
||||
'future-hour': ngettext_lazy('an hour from now', '%(count)s hours from now', 'count'),
|
||||
# Translators: delta will contain a string like '2 months' or '1 month, 2 weeks'
|
||||
'future-day': gettext_lazy('%(delta)s from now'),
|
||||
}
|
||||
past_substrings = {
|
||||
# Translators: 'naturaltime-past' strings will be included in '%(delta)s ago'
|
||||
'year': npgettext_lazy('naturaltime-past', '%d year', '%d years'),
|
||||
'month': npgettext_lazy('naturaltime-past', '%d month', '%d months'),
|
||||
'week': npgettext_lazy('naturaltime-past', '%d week', '%d weeks'),
|
||||
'day': npgettext_lazy('naturaltime-past', '%d day', '%d days'),
|
||||
'hour': npgettext_lazy('naturaltime-past', '%d hour', '%d hours'),
|
||||
'minute': npgettext_lazy('naturaltime-past', '%d minute', '%d minutes'),
|
||||
}
|
||||
future_substrings = {
|
||||
# Translators: 'naturaltime-future' strings will be included in '%(delta)s from now'
|
||||
'year': npgettext_lazy('naturaltime-future', '%d year', '%d years'),
|
||||
'month': npgettext_lazy('naturaltime-future', '%d month', '%d months'),
|
||||
'week': npgettext_lazy('naturaltime-future', '%d week', '%d weeks'),
|
||||
'day': npgettext_lazy('naturaltime-future', '%d day', '%d days'),
|
||||
'hour': npgettext_lazy('naturaltime-future', '%d hour', '%d hours'),
|
||||
'minute': npgettext_lazy('naturaltime-future', '%d minute', '%d minutes'),
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def string_for(cls, value):
|
||||
if not isinstance(value, date): # datetime is a subclass of date
|
||||
return value
|
||||
|
||||
now = datetime.now(utc if is_aware(value) else None)
|
||||
if value < now:
|
||||
delta = now - value
|
||||
if delta.days != 0:
|
||||
return cls.time_strings['past-day'] % {
|
||||
'delta': defaultfilters.timesince(value, now, time_strings=cls.past_substrings),
|
||||
}
|
||||
elif delta.seconds == 0:
|
||||
return cls.time_strings['now']
|
||||
elif delta.seconds < 60:
|
||||
return cls.time_strings['past-second'] % {'count': delta.seconds}
|
||||
elif delta.seconds // 60 < 60:
|
||||
count = delta.seconds // 60
|
||||
return cls.time_strings['past-minute'] % {'count': count}
|
||||
else:
|
||||
count = delta.seconds // 60 // 60
|
||||
return cls.time_strings['past-hour'] % {'count': count}
|
||||
else:
|
||||
count = delta.seconds // 60 // 60
|
||||
return ngettext(
|
||||
# Translators: please keep a non-breaking space (U+00A0)
|
||||
# between count and time unit.
|
||||
'an hour ago', '%(count)s hours ago', count
|
||||
) % {'count': count}
|
||||
else:
|
||||
delta = value - now
|
||||
if delta.days != 0:
|
||||
# Translators: delta will contain a string like '2 months' or '1 month, 2 weeks'
|
||||
return _('%(delta)s from now') % {'delta': defaultfilters.timeuntil(value, now, time_strings={
|
||||
# Translators: 'naturaltime-future' strings will be included in
|
||||
# '%(delta)s from now'
|
||||
'year': npgettext_lazy('naturaltime-future', '%d year', '%d years'),
|
||||
'month': npgettext_lazy('naturaltime-future', '%d month', '%d months'),
|
||||
'week': npgettext_lazy('naturaltime-future', '%d week', '%d weeks'),
|
||||
'day': npgettext_lazy('naturaltime-future', '%d day', '%d days'),
|
||||
'hour': npgettext_lazy('naturaltime-future', '%d hour', '%d hours'),
|
||||
'minute': npgettext_lazy('naturaltime-future', '%d minute', '%d minutes')
|
||||
})}
|
||||
elif delta.seconds == 0:
|
||||
return _('now')
|
||||
elif delta.seconds < 60:
|
||||
return ngettext(
|
||||
# Translators: please keep a non-breaking space (U+00A0)
|
||||
# between count and time unit.
|
||||
'a second from now', '%(count)s seconds from now', delta.seconds
|
||||
) % {'count': delta.seconds}
|
||||
elif delta.seconds // 60 < 60:
|
||||
count = delta.seconds // 60
|
||||
return ngettext(
|
||||
# Translators: please keep a non-breaking space (U+00A0)
|
||||
# between count and time unit.
|
||||
'a minute from now', '%(count)s minutes from now', count
|
||||
) % {'count': count}
|
||||
else:
|
||||
count = delta.seconds // 60 // 60
|
||||
return ngettext(
|
||||
# Translators: please keep a non-breaking space (U+00A0)
|
||||
# between count and time unit.
|
||||
'an hour from now', '%(count)s hours from now', count
|
||||
) % {'count': count}
|
||||
delta = value - now
|
||||
if delta.days != 0:
|
||||
return cls.time_strings['future-day'] % {
|
||||
'delta': defaultfilters.timeuntil(value, now, time_strings=cls.future_substrings),
|
||||
}
|
||||
elif delta.seconds == 0:
|
||||
return cls.time_strings['now']
|
||||
elif delta.seconds < 60:
|
||||
return cls.time_strings['future-second'] % {'count': delta.seconds}
|
||||
elif delta.seconds // 60 < 60:
|
||||
count = delta.seconds // 60
|
||||
return cls.time_strings['future-minute'] % {'count': count}
|
||||
else:
|
||||
count = delta.seconds // 60 // 60
|
||||
return cls.time_strings['future-hour'] % {'count': count}
|
||||
|
|
Loading…
Reference in New Issue