437 Stimmen

Zeitdelta in String formatieren

Ich habe Probleme bei der Formatierung einer datetime.timedelta Objekt.

Hier ist, was ich t Ich habe eine Liste von Objekten und eines der Mitglieder der Klasse des Objekts ist ein Timedelta-Objekt, das die Dauer eines Ereignisses anzeigt. Ich möchte diese Dauer im Format Stunden:Minuten anzeigen.

Ich habe verschiedene Methoden ausprobiert, um dies zu erreichen, aber ich habe Schwierigkeiten. Mein derzeitiger Ansatz besteht darin, der Klasse für meine Objekte Methoden hinzuzufügen, die Stunden und Minuten zurückgeben. Die Stunden erhalte ich, indem ich die timedelta.seconds durch 3600 teile und das Ergebnis runde. Ich habe Schwierigkeiten, die restlichen Sekunden zu ermitteln und in Minuten umzurechnen.

Übrigens, ich verwende Google AppEngine mit Django Templates für die Präsentation.

7voto

Bill Gale Punkte 1072

Nur eine Zeile. Da timedeltas nicht datetime's strftime bieten, bringen Sie das timedelta zurück zu einer datetime, und verwenden Sie stftime.

Damit können Sie nicht nur das vom Auftraggeber gewünschte Format Stunden:Minuten erreichen, sondern auch die volle Formatierungskraft von strftime von datetime nutzen, falls sich Ihre Anforderungen zu einer anderen Darstellung ändern.

import datetime
td = datetime.timedelta(hours=2, minutes=10, seconds=5)
print(td)
print(datetime.datetime.strftime(datetime.datetime.strptime(str(td), "%H:%M:%S"), "%H:%M"))

Output:
2:10:05
02:10

Dies löst auch das Ärgernis, dass Timedeltas in Strings als H:MM:SS und nicht als HH:MM:SS formatiert werden, was mich zu diesem Problem und der von mir mitgeteilten Lösung führte.

6voto

SleX Punkte 113
import datetime
hours = datetime.timedelta(hours=16, minutes=30)
print((datetime.datetime(1,1,1) + hours).strftime('%H:%M'))

4voto

Artem Vasilev Punkte 129
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)

Dies wird zu einem Ergebnis führen:

>>> from datetime import timedelta
>>> localize_timedelta(timedelta(days=3660, minutes=500))
'10 years 10 days 8 hours 20 minutes'

4voto

nealtz Punkte 321

Ich hatte ein ähnliches Problem mit der Ausgabe der Überstundenberechnung bei der Arbeit. Der Wert sollte immer in HH:MM angezeigt werden, auch wenn er größer als ein Tag ist und der Wert negativ werden kann. Ich habe einige der gezeigten Lösungen kombiniert, und vielleicht findet jemand anderes diese Lösung nützlich. Ich habe festgestellt, dass die meisten der gezeigten Lösungen mit der divmod-Methode nicht sofort funktionieren, wenn der Timedelta-Wert negativ ist:

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 in HH:MM-Zeichenfolge:

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'

4voto

Patrick Punkte 351

Ein unkomplizierter Vorlagenfilter für dieses Problem. Die eingebaute Funktion int() rundet nie auf. F-Strings (d.h. f'') erfordern Python 3.6.

@app_template_filter()
def diffTime(end, start):
    diff = (end - start).total_seconds()
    d = int(diff / 86400)
    h = int((diff - (d * 86400)) / 3600)
    m = int((diff - (d * 86400 + h * 3600)) / 60)
    s = int((diff - (d * 86400 + h * 3600 + m *60)))
    if d > 0:
        fdiff = f'{d}d {h}h {m}m {s}s'
    elif h > 0:
        fdiff = f'{h}h {m}m {s}s'
    elif m > 0:
        fdiff = f'{m}m {s}s'
    else:
        fdiff = f'{s}s'
    return fdiff

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X