Formatieren Sie timedelta zu string

275

Ich habe Probleme beim Formatieren eines datetime.timedeltaObjekts.

Folgendes versuche ich zu tun: Ich habe eine Liste von Objekten und eines der Mitglieder der Klasse des Objekts ist ein Zeitdelta-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 tun, und ich habe Schwierigkeiten. Mein aktueller Ansatz besteht darin, der Klasse Methoden für meine Objekte hinzuzufügen, die Stunden und Minuten zurückgeben. Ich kann die Stunden erhalten, indem ich das timedelta.seconds durch 3600 dividiere und runde. Ich habe Probleme, die restlichen Sekunden zu bekommen und diese in Minuten umzuwandeln.

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

mawcs
quelle
44
Wäre schön, wenn timedelta ein Äquivalent der strftime () -Methode hätte.
JS.
@JS. Nun, Sie können etwas, wenn Sie verwenden datetime.utcfromtimestamp(). Siehe meine Antwort unten.
sjngm
@JS. - 100% stimmen zu. Dann ist __str__von timedeltaganz anständig im Gegensatz zu __repr__(das heißt - für Menschen!). Zum Beispiel: datetime.timedelta(minutes=6, seconds=41) * 2618 / 48gibt datetime.timedelta(seconds=21871, microseconds=208333), aber str(datetime.timedelta(minutes=6, seconds=41) * 2618 / 48)gibt '6:04:31.208333'die ziemlich in Ordnung ist zu lesen.
Tomasz Gandor

Antworten:

213

Sie können das Zeitdelta einfach mit str () in einen String konvertieren. Hier ist ein Beispiel:

import datetime
start = datetime.datetime(2009,2,10,14,00)
end   = datetime.datetime(2009,2,10,16,00)
delta = end-start
print(str(delta))
# prints 2:00:00
Parand
quelle
13
Eher wie das Aufrufen der str () -Methode mit timedelta als Argument.
Joeforker
12
Sie brauchen den str-Aufruf dort nicht, er wird automatisch per Druck ausgeführt.
Zitrax
5
@Zitrax, aber es ist notwendig, wenn Sie das Delta mit einer anderen Zeichenfolge verketten möchten. Zum Beispielprint 'some thing ' + str(delta)
Plinio.Santos
12
Und wenn der Datentyp als 'datetime.timedelta' definiert ist und Sie ihn ConvertDuration=datetime.timedelta(milliseconds=int(254459))so verwenden, verwenden Sie einfach split, um die Mikrosekunden außer Spiel zu setzen. Von 0: 03: 43.765000 kann ich 0:03:43 erhalten, indem ich einfach TotalDuration=str(ConvertDuration).split('.', 2)[0]
laufe
16
Dies druckt das Delta möglicherweise als Zeichenfolge, formatiert es jedoch nicht wie angefordert.
Dannid
187

Wie Sie wissen, können Sie die total_seconds von einem timedelta-Objekt abrufen, indem Sie auf das .secondsAttribut zugreifen .

Python bietet die integrierte Funktion, divmod()die Folgendes ermöglicht:

s = 13420
hours, remainder = divmod(s, 3600)
minutes, seconds = divmod(remainder, 60)
print '{:02}:{:02}:{:02}'.format(int(hours), int(minutes), int(seconds))
# result: 03:43:40

oder Sie können in Stunden und Rest umrechnen, indem Sie eine Kombination aus Modulo und Subtraktion verwenden:

# arbitrary number of seconds
s = 13420
# hours
hours = s // 3600 
# remaining seconds
s = s - (hours * 3600)
# minutes
minutes = s // 60
# remaining seconds
seconds = s - (minutes * 60)
# total time
print '{:02}:{:02}:{:02}'.format(int(hours), int(minutes), int(seconds))
# result: 03:43:40
John Fouhy
quelle
5
Bei negativen Zeitangaben sollten Sie zuerst das Vorzeichen auswerten und dann tun abs(s).
Mbarkhau
27
Beachten Sie, dass Sie möglicherweise tatsächlich '%d:%02d:%02d'führende Nullen in der Ausgabezeichenfolge verwenden möchten .
ShinNoNoir
12
Für Python 2.7 und höher verwenden Sie die Methode .total_seconds ()
sk8asd123
27
Nicht verwenden, .secondswenn der Unterschied negativ oder länger als 24 Stunden sein kann ( .secondsAttribut ignoriert .days). Verwenden Sie .total_seconds()stattdessen oder sein Analog.
JFS
Für positive Unterschiede implementiere ich dies von Zeit zu Zeit neu. Vielen Dank, dass Sie diesmal nur suchen müssen :)
Wolf
59
>>> str(datetime.timedelta(hours=10.56))
10:33:36

>>> td = datetime.timedelta(hours=10.505) # any timedelta object
>>> ':'.join(str(td).split(':')[:2])
10:30

Wenn Sie das timedeltaObjekt an die str()Funktion übergeben, wird derselbe Formatierungscode aufgerufen, der bei einfacher Eingabe verwendet wird print td. Da Sie die Sekunden nicht möchten, können wir die Zeichenfolge durch Doppelpunkte (3 Teile) teilen und sie nur mit den ersten 2 Teilen wieder zusammensetzen.

Joeforker
quelle
Danke für deine Antwort, Joeforker, aber ich bin mir nicht sicher, ob ich deine Antwort verstehe. Ich erhalte ein Zeitdelta über datetime - datetime. Ich kenne die Stunden nicht. Außerdem sieht es so aus, als ob Ihr Beispiel Sekunden enthält. Wie würde ich das entfernen?
Mawcs
1
Es spielt keine Rolle, woher Sie das timedelta-Objekt beziehen, es wird das gleiche Format haben.
Joeforker
9
Wenn es länger als ein Tag ist, wird es nach der Split / Join-Verarbeitung als "4 Tage, 8:00" formatiert.
Joeforker
4
str(my_timedelta)funktioniert schlecht für negative Zahlen
Catskul
2
Zeigt auch Tage an, wenn> 24 Stunden, z. B. '4 Tage, 18: 48: 22.330000'. Viele hier empfohlene Methoden tun dies nicht.
Alexei Martianov
47
def td_format(td_object):
    seconds = int(td_object.total_seconds())
    periods = [
        ('year',        60*60*24*365),
        ('month',       60*60*24*30),
        ('day',         60*60*24),
        ('hour',        60*60),
        ('minute',      60),
        ('second',      1)
    ]

    strings=[]
    for period_name, period_seconds in periods:
        if seconds > period_seconds:
            period_value , seconds = divmod(seconds, period_seconds)
            has_s = 's' if period_value > 1 else ''
            strings.append("%s %s%s" % (period_value, period_name, has_s))

    return ", ".join(strings)
Adam Jacob Muller
quelle
3
Wirklich schön, ich würde vorschlagen , Wechsel if seconds > period_seconds:zu if seconds >= period_seconds:jedoch.
CBenni
1
Dies gibt leere Zeichenfolgen für negative Zeitleisten zurück. Sie sind sich nicht sicher, ob dies beabsichtigt ist?
Dirk
31

Ich persönlich benutze die humanizeBibliothek dafür:

>>> import datetime
>>> humanize.naturalday(datetime.datetime.now())
'today'
>>> humanize.naturalday(datetime.datetime.now() - datetime.timedelta(days=1))
'yesterday'
>>> humanize.naturalday(datetime.date(2007, 6, 5))
'Jun 05'
>>> humanize.naturaldate(datetime.date(2007, 6, 5))
'Jun 05 2007'
>>> humanize.naturaltime(datetime.datetime.now() - datetime.timedelta(seconds=1))
'a second ago'
>>> humanize.naturaltime(datetime.datetime.now() - datetime.timedelta(seconds=3600))
'an hour ago'

Natürlich gibt es Ihnen nicht genau die Antwort, nach der Sie gesucht haben (was in der Tat der Fall ist, str(timeA - timeB)aber ich habe festgestellt, dass das Display nach mehr als ein paar Stunden schnell unlesbar wird. humanizeEs unterstützt viel größere Werte für Menschen lesbar und auch gut lokalisiert.

Es ist contrib.humanizeanscheinend von Djangos Modul inspiriert. Da Sie also Django verwenden, sollten Sie es wahrscheinlich verwenden.

anarcat
quelle
2
Schön, + 1 Obwohl: humanize.naturaldelta (pd.Timedelta ('- 10sec')) -> '10 Sekunden ': S ...
ntg
2
Nun, es ist ein 10-Sekunden- Delta . :) Wenn du die Zeit willst , naturaltimeist das , was du nutzen willst.
Anarcat
28

Er hat bereits ein timedelta-Objekt. Warum also nicht die integrierte Methode total_seconds () verwenden, um es in Sekunden zu konvertieren, und dann divmod () verwenden, um Stunden und Minuten abzurufen?

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.

Bill Kidd
quelle
23

Hier ist eine Allzweckfunktion zum Konvertieren eines timedeltaObjekts oder einer regulären Zahl (in Form von Sekunden oder Minuten usw.) in eine schön formatierte Zeichenfolge. Ich habe die fantastische Antwort von mpounsett auf eine doppelte Frage genommen, sie etwas flexibler gestaltet, die Lesbarkeit verbessert und die Dokumentation hinzugefügt.

Sie werden feststellen, dass dies hier die bisher flexibelste Antwort ist, da Sie damit Folgendes tun können:

  1. Passen Sie das Zeichenfolgenformat im laufenden Betrieb an, anstatt es fest zu codieren.
  2. Lassen Sie bestimmte Zeitintervalle problemlos aus (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
MarredCheese
quelle
Sehr schöner, sauberer Code! Ich frage mich, wie dieser Code erweitert werden kann, um die letzten Sekundenbruchteile im Formatierer zu verarbeiten ...
kfmfe04
17

Ich weiß, dass dies eine alte beantwortete Frage ist, aber ich benutze sie datetime.utcfromtimestamp()dafür. Es dauert die Anzahl der Sekunden und gibt eine zurück datetime, die wie jede andere formatiert werden kann datetime.

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

Solange Sie für die Zeitabschnitte, die funktionieren sollten, im gesetzlichen Bereich bleiben, dh 1234: 35 nicht zurückgeben, da die Stunden <= 23 sind.

sjngm
quelle
2
Sie sollten print timedelta(seconds=end - begin)stattdessen verwenden.
JFS
@JFSebastian Dann müssten Sie die Stunden manuell mit führenden Nullen auffüllen.
sjngm
Ich sehe nichts über Polsterung in der Frage. Verwenden .zfill(8)Sie, wenn Sie es brauchen.
JFS
1
Benötigt einen Aufruf von .total_seconds (): >>> datetime.utcfromtimestamp ((t2-t1) .total_seconds ()). Strftime ("% H:% M:% S") <<< >>> '00: 00: 05 '
Cagney
2
Ich bevorzuge diese Lösung sehr, sie ermöglicht es Ihnen, die Formatierung zu steuern. Beachten Sie, dass Sie den str-Formatierer auch direkt wie folgt verwenden können: "{0:% H}: {0:% M}". Format (Dauer)
Zehen
15

Der Fragesteller möchte ein schöneres Format als das typische:

  >>> import datetime
  >>> datetime.timedelta(seconds=41000)
  datetime.timedelta(0, 41000)
  >>> str(datetime.timedelta(seconds=41000))
  '11:23:20'
  >>> str(datetime.timedelta(seconds=4102.33))
  '1:08:22.330000'
  >>> str(datetime.timedelta(seconds=413302.33))
  '4 days, 18:48:22.330000'

Es gibt also zwei Formate, eines, bei dem Tage 0 sind und weggelassen werden, und eines, bei dem der Text "n Tage, h: m: s" angezeigt wird. Die Sekunden können jedoch Brüche enthalten, und die Ausdrucke enthalten keine führenden Nullen, sodass die Spalten unübersichtlich sind.

Hier ist meine Routine, wenn es Ihnen gefällt:

def printNiceTimeDelta(stime, etime):
    delay = datetime.timedelta(seconds=(etime - stime))
    if (delay.days > 0):
        out = str(delay).replace(" days, ", ":")
    else:
        out = "0:" + str(delay)
    outAr = out.split(':')
    outAr = ["%02d" % (int(float(x))) for x in outAr]
    out   = ":".join(outAr)
    return out

Dies gibt die Ausgabe im Format dd: hh: mm: ss zurück:

00:00:00:15
00:00:00:19
02:01:31:40
02:01:32:22

Ich habe darüber nachgedacht, Jahre hinzuzufügen, aber dies bleibt als Übung für den Leser, da die Ausgabe bei über 1 Jahr sicher ist:

>>> str(datetime.timedelta(seconds=99999999))
'1157 days, 9:46:39'
Kevin J. Rice
quelle
15

Ich würde hier ernsthaft über den Occam's Razor-Ansatz nachdenken:

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

Dies gibt eine Zeichenfolge ohne 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))

2 Jahre später liebe ich diese Sprache!

Pyrotherm
quelle
5
Dies gilt nicht für Tage
Waschbaer
13

Meine datetime.timedeltaObjekte waren länger als ein Tag. Hier ist also ein weiteres Problem. Alle obigen Diskussionen gehen von weniger als einem Tag aus. A timedeltaist eigentlich ein Tupel von Tagen, Sekunden und Mikrosekunden. Die obige Diskussion sollte td.secondswie Joe verwendet werden, aber wenn Sie Tage haben, ist sie NICHT im Sekundenwert enthalten.

Ich erhalte eine Zeitspanne zwischen 2 Datumsangaben und Drucktagen und -stunden.

span = currentdt - previousdt
print '%d,%d\n' % (span.days,span.seconds/3600)
Alex L.
quelle
Dies ist die zukunftssichere Lösung.
Jibin
11

Ich habe die humanfriendlyPython-Bibliothek verwendet, 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/

Dhiraj Gupta
quelle
7

In Anlehnung an Joes obigen Beispielwert würde ich den Modularithmetikoperator verwenden, also:

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

Beachten Sie, dass die Ganzzahldivision in Python standardmäßig abgerundet wird. Wenn Sie expliziter sein möchten, verwenden Sie je nach Bedarf math.floor () oder math.ceil ().

UltraNurd
quelle
timedelta weiß bereits, wie man sich selbst formatiert, wie in 'print some_timedelta'.
Joeforker
Ja, aber es kann keine Zeichenfolge mit beliebigem Format akzeptieren, was Michael gefragt hat. Obwohl jetzt, wo ich darüber nachdenke, 3600 Division Mod die Stunden-Sekunden-Annahme macht, die Probleme bei Schaltsekunden verursacht.
UltraNurd
Ja, aber er möchte keine Zeichenfolge mit beliebigem Format, er möchte fast genau das Standardverhalten.
Joeforker
2
Vergessen Sie nicht // zum Abschneiden der Teilung in Python 3000
Joeforker
3
+1, aber warum bearbeitest du die Antwort nicht, um // zu verwenden? Ich würde auch vorschlagen, td.total_seconds()anstatt .secondszu verwenden, damit es für Intervalle> 1 Tag funktioniert.
Antony Hatchkins
4
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
Veselin Penev
quelle
Hast du das geschrieben? Wie viel hast du getestet?
Thomas Ahle
Ich verwende diesen Code in meinem Projekt namens datahaven.net . Es funktioniert ziemlich gut. Hast du irgendwelche Fehler gesehen?
Veselin Penev
Es ist immer schön, wenn Sie mit einer solchen codelastigen Antwort ein paar Informationen liefern können :) Wie ein Beispiel dafür, wie es funktioniert, mögliche Stärken und Schwächen.
Thomas Ahle
1
Oh. Sicher!. Ein Beispiel für Sie hinzugefügt. :-)
Veselin Penev
Super :) Beachten Sie auch , dass das timedeltaObjekt die Felder hat days, secondsund microsecondsdurch die Dokumentation.
Thomas Ahle
4

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

Zeitdelta zu HH: MM String:

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'
Nealtz
quelle
4
import datetime
hours = datetime.timedelta(hours=16, minutes=30)
print((datetime.datetime(1,1,1) + hours).strftime('%H:%M'))
SleX
quelle
2
in 3.7 bekomme ich AttributeError: 'datetime.timedelta' Objekt hat kein Attribut 'strftime'
qubodup
4

Ein einfacher Vorlagenfilter für dieses Problem. Die eingebaute Funktion int () rundet niemals auf. F-Strings (dh 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
Patrick
quelle
3
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 produzieren:

>>> from datetime import timedelta
>>> localize_timedelta(timedelta(days=3660, minutes=500))
'10 years 10 days 8 hours 20 minutes'
Artem Vasilev
quelle
Am besten meiner Meinung nach, in Bezug auf die Länge und was es abdeckt
Dici
1

Bitte überprüfen Sie diese Funktion - sie konvertiert das Timedelta-Objekt in die Zeichenfolge 'HH: MM: SS'.

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)
MobilePro.pl
quelle
1

Einzeiler. Da timedeltas keine strftime von datetime anbieten, bringen Sie das timedelta wieder auf datetime und verwenden Sie stftime.

Dies kann nicht nur das vom OP angeforderte Format Stunden: Minuten erreichen, sondern Sie können jetzt die volle Formatierungsleistung der Zeit von datetime nutzen, falls sich Ihre Anforderungen in eine andere 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 den Ärger, dass Zeitdelas in Zeichenfolgen als H: MM: SS und nicht als HH: MM: SS formatiert werden, was mich zu diesem Problem und der von mir geteilten Lösung führt.

Bill Gale
quelle
0

Wenn Sie bereits ein Timedelta-Objekt haben, konvertieren Sie dieses Objekt einfach in einen String. Entfernen Sie die letzten 3 Zeichen der Zeichenfolge und drucken Sie. Dadurch wird der Sekundenabschnitt abgeschnitten und der Rest im Format Stunden: Minuten gedruckt.

t = str(timedeltaobj) 

print t[:-3]
Sima
quelle
Die -3 funktioniert nicht, besser nutzenprint t.split('.')[0]
EvgenyKolyakov
0

Wenn Sie zufällig IPythonin Ihren Paketen haben (sollten Sie), hat es (jedenfalls bis jetzt) ​​einen sehr schönen Formatierer für die Dauer (in Float-Sekunden). Das wird an verschiedenen Orten verwendet, zum Beispiel von der %%timeZellmagie. Ich mag das Format, das es für kurze Zeit erzeugt:

>>> from IPython.core.magics.execution import _format_time
>>> 
>>> for v in range(-9, 10, 2):
...     dt = 1.25 * 10**v
...     print(_format_time(dt))

1.25 ns
125 ns
12.5 µs
1.25 ms
125 ms
12.5 s
20min 50s
1d 10h 43min 20s
144d 16h 13min 20s
14467d 14h 13min 20s
Pierre D.
quelle
-3
t1 = datetime.datetime.strptime(StartTime, "%H:%M:%S %d-%m-%y")

t2 = datetime.datetime.strptime(EndTime, "%H:%M:%S %d-%m-%y")

return str(t2-t1)

So für:

StartTime = '15:28:53 21-07-13'
EndTime = '15:32:40 21-07-13'

kehrt zurück:

'0:03:47'
Aviad
quelle
-10

Vielen Dank an alle für Ihre Hilfe. Ich habe viele Ihrer Ideen aufgenommen und zusammengestellt. Lassen Sie mich wissen, was Sie denken.

Ich habe der Klasse zwei Methoden hinzugefügt:

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

In meinem Django habe ich dies verwendet (Summe ist das Objekt und es befindet sich in einem Wörterbuch):

<td>{{ sum.0 }}</td>    
<td>{{ sum.1.hours|stringformat:"d" }}:{{ sum.1.minutes|stringformat:"#02.0d" }}</td>
mawcs
quelle
Es ist ein bisschen lang. Ich würde vorschlagen: def hhmm (self): return ':'. Join (str (td) .split (':') [: 2]) <td> {{sum.1.hhmm}} </ td>
Joeforker
1
Verwenden Sie einfach divmod (), wie im Beispiel "Unterschied zweier Daten" unter docs.python.org/release/2.5.2/lib/datetime-timedelta.html gezeigt
Tom