18๐
No, I donโt think there is any built in filter to format a timedelta
, it should be fairly easy to write one yourself though.
Here is a basic example:
from django import template
register = template.Library()
@register.filter
def duration(td):
total_seconds = int(td.total_seconds())
hours = total_seconds // 3600
minutes = (total_seconds % 3600) // 60
return '{} hours {} min'.format(hours, minutes)
4๐
Contribution for Aumo answer:
from django import template
register = template.Library()
@register.filter
def duration(td):
total_seconds = int(td.total_seconds())
days = total_seconds // 86400
remaining_hours = total_seconds % 86400
remaining_minutes = remaining_hours % 3600
hours = remaining_hours // 3600
minutes = remaining_minutes // 60
seconds = remaining_minutes % 60
days_str = f'{days}d ' if days else ''
hours_str = f'{hours}h ' if hours else ''
minutes_str = f'{minutes}m ' if minutes else ''
seconds_str = f'{seconds}s' if seconds and not hours_str else ''
return f'{days_str}{hours_str}{minutes_str}{seconds_str}'
- How to serialize an 'object list' in Django REST Framework
- Django vs. Pylons
- How to convert request.user into a proxy auth.User class?
1๐
This is the one I use, it rounds minutes and display only the information needed :
@register.filter
def duration(timedelta):
"""
Format a duration field
"2h and 30 min" or only "45 min" for example
:rtype: str
"""
total_seconds = int(timedelta.total_seconds())
hours = total_seconds // 3600
minutes = round((total_seconds % 3600) / 60)
if minutes == 60:
hours += 1
minutes = 0
if hours and minutes:
# Display both
return f'{hours}h and {minutes} min'
elif hours:
# Display only hours
return f'{hours}h'
# Display only minutes
return f'{minutes} min'
- Error loading sample django-bootstrap3 template
- DataTables: Custom Response Handling
- Django.core.exceptions.ImproperlyConfigured: Set the SECRET_KEY environment variable
0๐
In order to make this as readable as possible for crawlers and screen readers, so as to improve your SEO rating, the best practice is to use the html time
tag, with the datetime
attribute.
https://developer.mozilla.org/en-US/docs/Web/HTML/Element/time
https://www.w3.org/TR/2014/REC-html5-20141028/infrastructure.html#valid-duration-string
I have written a template tag to accomplish the formatting of the duration, both in machine and human-readable forms. This displays days, hours, minutes, seconds, and microseconds, using the largest increments possible and hiding any values that are 0. It also handles pluralizing the labels and adding commas and spaces as necessary.
datetime.py (templatetag file)
import datetime
from django import template
register = template.Library()
from django.template.defaultfilters import pluralize
@register.filter
def duration(value, mode=""):
assert mode in ["machine", "phrase", "clock"]
remainder = value
response = ""
days = 0
hours = 0
minutes = 0
seconds = 0
microseconds = 0
if remainder.days > 0:
days = remainder.days
remainder -= datetime.timedelta(days=remainder.days)
if round(remainder.seconds/3600) > 1:
hours = round(remainder.seconds/3600)
remainder -= datetime.timedelta(hours=hours)
if round(remainder.seconds/60) > 1:
minutes = round(remainder.seconds/60)
remainder -= datetime.timedelta(minutes=minutes)
if remainder.seconds > 0:
seconds = remainder.seconds
remainder -= datetime.timedelta(seconds=seconds)
if remainder.microseconds > 0:
microseconds = remainder.microseconds
remainder -= datetime.timedelta(microseconds=microseconds)
if mode == "machine":
response = "P{days}DT{hours}H{minutes}M{seconds}.{microseconds}S".format(
days=days,
hours=hours,
minutes=minutes,
seconds=seconds,
microseconds=str(microseconds).zfill(6),
)
elif mode == "phrase":
response = []
if days:
response.append(
"{days} day{plural_suffix}".format(
days=days,
plural_suffix=pluralize(days),
)
)
if hours:
response.append(
"{hours} hour{plural_suffix}".format(
hours=hours,
plural_suffix=pluralize(hours),
)
)
if minutes:
response.append(
"{minutes} minute{plural_suffix}".format(
minutes=minutes,
plural_suffix=pluralize(minutes),
)
)
if seconds:
response.append(
"{seconds} second{plural_suffix}".format(
seconds=seconds,
plural_suffix=pluralize(seconds),
)
)
if microseconds:
response.append(
"{microseconds} microsecond{plural_suffix}".format(
microseconds=microseconds,
plural_suffix=pluralize(microseconds),
)
)
response = ", ".join(response)
elif mode == "clock":
response = []
if days:
response.append(
"{days} day{plural_suffix}".format(
days=days,
plural_suffix=pluralize(days),
)
)
if hours or minutes or seconds or microseconds:
time_string = "{hours}:{minutes}".format(
hours = str(hours).zfill(2),
minutes = str(minutes).zfill(2),
)
if seconds or microseconds:
time_string += ":{seconds}".format(
seconds = str(seconds).zfill(2),
)
if microseconds:
time_string += ".{microseconds}".format(
microseconds = str(microseconds).zfill(6),
)
response.append(time_string)
response = ", ".join(response)
return response
template.html (template file)
{% load datetime %}
<!-- phrase format -->
<time datetime="{{ event.duration|duration:'machine' }}">
{{ event.duration|duration:'phrase' }}
</time>
<!-- clock format -->
<time datetime="{{ event.duration|duration:'machine' }}">
{{ event.duration|duration:'clock' }}
</time>
Example Output
<!-- phrase format -->
<time datetime="P2DT1H0M0.000000S">2 days, 1 hour</time>
<!-- clock format -->
<time datetime="P2DT1H0M0.000000S">2 days, 01:00</time>
- Django: model object "has no attribute '_meta'" in class based view
- FastCGI application behind NGINX is unable to detect that HTTPS secure connection is used