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.

41voto

MarredCheese Punkte 13018

Hier ist eine allgemeine Funktion zur Konvertierung von entweder einer timedelta Objekt oder eine normale Zahl (in Form von Sekunden oder Minuten usw.) in eine schön formatierte Zeichenkette umwandeln. Ich nahm mpounsett's fantastische Antwort auf eine doppelte Frage, machte sie ein wenig flexibler, verbesserte die Lesbarkeit und fügte Dokumentation hinzu.

Sie werden feststellen, dass dies die bisher flexibelste Antwort ist, da sie Ihnen die Möglichkeit gibt:

  1. Passen Sie das Format der Zeichenkette im laufenden Betrieb an, anstatt es hart zu kodieren.
  2. Bestimmte Zeitintervalle können problemlos ausgelassen werden (siehe Beispiele unten).

Funktion:

from string import Formatter
from datetime import timedelta

def strfdelta(tdelta, fmt='{D:02}d {H:02}h {M:02}m {S:02}s', inputtype='timedelta'):
    """Convert a datetime.timedelta object or a regular number to a custom-
    formatted string, just like the stftime() method does for datetime.datetime
    objects.

    The fmt argument allows custom formatting to be specified.  Fields can 
    include seconds, minutes, hours, days, and weeks.  Each field is optional.

    Some examples:
        '{D:02}d {H:02}h {M:02}m {S:02}s' --> '05d 08h 04m 02s' (default)
        '{W}w {D}d {H}:{M:02}:{S:02}'     --> '4w 5d 8:04:02'
        '{D:2}d {H:2}:{M:02}:{S:02}'      --> ' 5d  8:04:02'
        '{H}h {S}s'                       --> '72h 800s'

    The inputtype argument allows tdelta to be a regular number instead of the  
    default, which is a datetime.timedelta object.  Valid inputtype strings: 
        's', 'seconds', 
        'm', 'minutes', 
        'h', 'hours', 
        'd', 'days', 
        'w', 'weeks'
    """

    # Convert tdelta to integer seconds.
    if inputtype == 'timedelta':
        remainder = int(tdelta.total_seconds())
    elif inputtype in ['s', 'seconds']:
        remainder = int(tdelta)
    elif inputtype in ['m', 'minutes']:
        remainder = int(tdelta)*60
    elif inputtype in ['h', 'hours']:
        remainder = int(tdelta)*3600
    elif inputtype in ['d', 'days']:
        remainder = int(tdelta)*86400
    elif inputtype in ['w', 'weeks']:
        remainder = int(tdelta)*604800

    f = Formatter()
    desired_fields = [field_tuple[1] for field_tuple in f.parse(fmt)]
    possible_fields = ('W', 'D', 'H', 'M', 'S')
    constants = {'W': 604800, 'D': 86400, 'H': 3600, 'M': 60, 'S': 1}
    values = {}
    for field in possible_fields:
        if field in desired_fields and field in constants:
            values[field], remainder = divmod(remainder, constants[field])
    return f.format(fmt, **values)

Demo:

>>> td = timedelta(days=2, hours=3, minutes=5, seconds=8, microseconds=340)

>>> print strfdelta(td)
02d 03h 05m 08s

>>> print strfdelta(td, '{D}d {H}:{M:02}:{S:02}')
2d 3:05:08

>>> print strfdelta(td, '{D:2}d {H:2}:{M:02}:{S:02}')
 2d  3:05:08

>>> print strfdelta(td, '{H}h {S}s')
51h 308s

>>> print strfdelta(12304, inputtype='s')
00d 03h 25m 04s

>>> print strfdelta(620, '{H}:{M:02}', 'm')
10:20

>>> print strfdelta(49, '{D}d {H}h', 'h')
2d 1h

36voto

Bill Kidd Punkte 1004

Er hat bereits ein timedelta-Objekt, warum also nicht dessen eingebaute Methode total_seconds() verwenden, um es in Sekunden umzuwandeln, und dann divmod() verwenden, um Stunden und Minuten zu erhalten?

hours, remainder = divmod(myTimeDelta.total_seconds(), 3600)
minutes, seconds = divmod(remainder, 60)

# Formatted only for hours and minutes as requested
print '%s:%s' % (hours, minutes)

Dies funktioniert unabhängig davon, ob das Zeitdelta gerade Tage oder Jahre hat.

30voto

sjngm Punkte 11845

Ich weiß, dass dies eine alte Frage ist, aber ich verwende datetime.utcfromtimestamp() dafür. Sie nimmt die Anzahl der Sekunden und gibt eine datetime die wie jede andere formatiert werden kann datetime .

duration = datetime.utcfromtimestamp(end - begin)
print duration.strftime('%H:%M')

Solange Sie innerhalb der zulässigen Zeitspannen bleiben, sollte dies funktionieren, d.h. es wird nicht 1234:35 zurückgegeben, da die Stunden <= 23 sind.

20voto

Pyrotherm Punkte 233

Ich würde hier ernsthaft den Ansatz von Occam's Razor in Betracht ziehen:

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

Dies gibt eine Zeichenkette ohne die Mikrosekunden zurück

Wenn Sie das Objekt datetime.timedelta neu generieren möchten, gehen Sie wie folgt vor:

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

Nach 2 Jahren liebe ich diese Sprache!

18voto

Dhiraj Gupta Punkte 8345

Ich habe die humanfriendly python-Bibliothek, um dies zu tun, es funktioniert sehr gut.

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

'5 minutes and 21 seconds'

Verfügbar unter https://pypi.org/project/humanfriendly/

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