Формат Python timedelta в строку - PullRequest
       117

Формат Python timedelta в строку

226 голосов
/ 11 февраля 2009

Я новичок в Python (2 недели), и у меня возникают проблемы с форматированием объекта datetime.timedelta.

Вот что я пытаюсь сделать: У меня есть список объектов, и один из членов класса объекта является объектом timedelta, который показывает продолжительность события. Я хотел бы отобразить эту продолжительность в формате часов: минут.

Я испробовал множество способов сделать это, и у меня возникли трудности. Мой текущий подход заключается в добавлении методов в класс для моих объектов, которые возвращают часы и минуты. Я могу получить часы, разделив timedelta.seconds на 3600 и округлив его. У меня проблемы с получением оставшихся секунд и преобразованием их в минуты.

Кстати, я использую Google AppEngine с Django Templates для презентации.

Если кто-то может помочь или знает лучший способ решить эту проблему, я был бы очень рад.

Спасибо

Ответы [ 21 ]

9 голосов
/ 26 февраля 2015

Я бы серьезно рассмотрел подход Бритвы Оккама здесь:

td = str(timedelta).split('.')[0]

Возвращает строку без микросекунд

Если вы хотите восстановить объект datetime.timedelta, просто сделайте это:

h,m,s = re.split(':', td)
new_delta = datetime.timedelta(hours=int(h),minutes=int(m),seconds=int(s))

2 года, я люблю этот язык!

7 голосов
/ 11 февраля 2009

Следуя приведенному выше примеру значения Джо, я бы использовал арифметический оператор модуля, таким образом:

td = datetime.timedelta(hours=10.56)
td_str = "%d:%d" % (td.seconds/3600, td.seconds%3600/60)

Обратите внимание, что целочисленное деление в Python округляется по умолчанию; если вы хотите быть более явным, используйте math.floor () или math.ceil () в зависимости от ситуации.

5 голосов
/ 21 июня 2018

Для этого я использовал библиотеку humanfriendly python, она работает очень хорошо.

import humanfriendly
from datetime import timedelta
delta = timedelta(seconds = 321)
humanfriendly.format_timespan(delta)

'5 minutes and 21 seconds'

Доступно на https://pypi.org/project/humanfriendly/

4 голосов
/ 29 сентября 2013
def seconds_to_time_left_string(total_seconds):
    s = int(total_seconds)
    years = s // 31104000
    if years > 1:
        return '%d years' % years
    s = s - (years * 31104000)
    months = s // 2592000
    if years == 1:
        r = 'one year'
        if months > 0:
            r += ' and %d months' % months
        return r
    if months > 1:
        return '%d months' % months
    s = s - (months * 2592000)
    days = s // 86400
    if months == 1:
        r = 'one month'
        if days > 0:
            r += ' and %d days' % days
        return r
    if days > 1:
        return '%d days' % days
    s = s - (days * 86400)
    hours = s // 3600
    if days == 1:
        r = 'one day'
        if hours > 0:
            r += ' and %d hours' % hours
        return r 
    s = s - (hours * 3600)
    minutes = s // 60
    seconds = s - (minutes * 60)
    if hours >= 6:
        return '%d hours' % hours
    if hours >= 1:
        r = '%d hours' % hours
        if hours == 1:
            r = 'one hour'
        if minutes > 0:
            r += ' and %d minutes' % minutes
        return r
    if minutes == 1:
        r = 'one minute'
        if seconds > 0:
            r += ' and %d seconds' % seconds
        return r
    if minutes == 0:
        return '%d seconds' % seconds
    if seconds == 0:
        return '%d minutes' % minutes
    return '%d minutes and %d seconds' % (minutes, seconds)

for i in range(10):
    print pow(8, i), seconds_to_time_left_string(pow(8, i))


Output:
1 1 seconds
8 8 seconds
64 one minute and 4 seconds
512 8 minutes and 32 seconds
4096 one hour and 8 minutes
32768 9 hours
262144 3 days
2097152 24 days
16777216 6 months
134217728 4 years
4 голосов
/ 10 мая 2014

У меня была похожая проблема с выводом расчета сверхурочных на работе. Значение всегда должно отображаться в формате ЧЧ: ММ, даже если оно больше одного дня, и значение может стать отрицательным. Я объединил некоторые из показанных решений, и, возможно, кто-то найдет это решение полезным. Я понял, что если значение timedelta является отрицательным, большинство показанных решений с помощью метода divmod не работают "из коробки":

def td2HHMMstr(td):
  '''Convert timedelta objects to a HH:MM string with (+/-) sign'''
  if td < datetime.timedelta(seconds=0):
    sign='-'
    td = -td
  else:
    sign = ''
  tdhours, rem = divmod(td.total_seconds(), 3600)
  tdminutes, rem = divmod(rem, 60)
  tdstr = '{}{:}:{:02d}'.format(sign, int(tdhours), int(tdminutes))
  return tdstr

timedelta to HH: MM строка:

td2HHMMstr(datetime.timedelta(hours=1, minutes=45))
'1:54'

td2HHMMstr(datetime.timedelta(days=2, hours=3, minutes=2))
'51:02'

td2HHMMstr(datetime.timedelta(hours=-3, minutes=-2))
'-3:02'

td2HHMMstr(datetime.timedelta(days=-35, hours=-3, minutes=-2))
'-843:02'
3 голосов
/ 11 мая 2018
import datetime
hours = datetime.timedelta(hours=16, minutes=30)
print((datetime.datetime(1,1,1) + hours).strftime('%H:%M'))
2 голосов
/ 26 сентября 2016
from django.utils.translation import ngettext

def localize_timedelta(delta):
    ret = []
    num_years = int(delta.days / 365)
    if num_years > 0:
        delta -= timedelta(days=num_years * 365)
        ret.append(ngettext('%d year', '%d years', num_years) % num_years)

    if delta.days > 0:
        ret.append(ngettext('%d day', '%d days', delta.days) % delta.days)

    num_hours = int(delta.seconds / 3600)
    if num_hours > 0:
        delta -= timedelta(hours=num_hours)
        ret.append(ngettext('%d hour', '%d hours', num_hours) % num_hours)

    num_minutes = int(delta.seconds / 60)
    if num_minutes > 0:
        ret.append(ngettext('%d minute', '%d minutes', num_minutes) % num_minutes)

    return ' '.join(ret)

Это даст:

>>> from datetime import timedelta
>>> localize_timedelta(timedelta(days=3660, minutes=500))
'10 years 10 days 8 hours 20 minutes'
1 голос
/ 03 марта 2016

Пожалуйста, проверьте эту функцию - она ​​преобразует объект timedelta в строку 'ЧЧ: ММ: СС'

def format_timedelta(td):
    hours, remainder = divmod(td.total_seconds(), 3600)
    minutes, seconds = divmod(remainder, 60)
    hours, minutes, seconds = int(hours), int(minutes), int(seconds)
    if hours < 10:
        hours = '0%s' % int(hours)
    if minutes < 10:
        minutes = '0%s' % minutes
    if seconds < 10:
        seconds = '0%s' % seconds
    return '%s:%s:%s' % (hours, minutes, seconds)
0 голосов
/ 21 ноября 2017

Если у вас уже есть timedelta obj, просто преобразуйте этот объект в строку. Удалите последние 3 символа строки и напечатайте. Это обрезает часть секунд и печатает оставшуюся часть в формате Часы: минуты.

t = str(timedeltaobj) 

print t[:-3]
0 голосов
/ 12 февраля 2009

Спасибо всем за вашу помощь. Я взял много твоих идей и соединил их, дай мне знать, что ты думаешь.

Я добавил в класс два метода:

def hours(self):
    retval = ""
    if self.totalTime:
        hoursfloat = self.totalTime.seconds / 3600
        retval = round(hoursfloat)
    return retval

def minutes(self):
    retval = ""
    if self.totalTime:
        minutesfloat = self.totalTime.seconds / 60
        hoursAsMinutes = self.hours() * 60
        retval = round(minutesfloat - hoursAsMinutes)
    return retval

В моем django я использовал это (сумма - объект, и это находится в словаре):

<td>{{ sum.0 }}</td>    
<td>{{ sum.1.hours|stringformat:"d" }}:{{ sum.1.minutes|stringformat:"#02.0d" }}</td>
...