Konwertuj timedelta na dni, godziny i minuty


243

Mam timedelta. Chcę dni, godziny i minuty od tego - albo jako krotka albo słownik ... Nie jestem zdenerwowany.

Przez lata musiałem to robić kilkanaście razy w kilkunastu językach, ale Python zazwyczaj ma prostą odpowiedź na wszystko, więc pomyślałem, że zapytam tutaj, zanim wypiszę mdłą, prostą (ale pełną słów) matematykę.

Pan Fooz podnosi dobrą rację.

Mam do czynienia z „aukcjami” (trochę jak aukcje w serwisie eBay), w których każdy ma czas trwania. Staram się znaleźć pozostały czaswhen_added + duration - now

Czy mam rację mówiąc, że to nie wyjaśnia DST? Jeśli nie, jaki jest najprostszy sposób dodawania / odejmowania godziny?


Jeśli ma to być tylko ciąg znaków w formacie GG: mm: ss, powiedz „0:19:37” z timedeltaobiektu „datetime.timedelta (sekundy = 1177)” : po prostu użyj str ()
Peter Mortensen

Odpowiedzi:


344

Jeśli masz datetime.timedeltawartość td, td.daysjuż daje ci „dni”, które chcesz. timedeltawartości zachowują ułamek dnia w sekundach (nie bezpośrednio w godzinach lub minutach), więc rzeczywiście będziesz musiał wykonać „mdląco prostą matematykę”, np .:

def days_hours_minutes(td):
    return td.days, td.seconds//3600, (td.seconds//60)%60

1
Należy pamiętać, że jeśli tdjest ujemne, -1 // 3600jest -1.
jcrs

4
czemu // ? zamiast /
Mohammed Shareef C

10
//jest używany zamiast /do uzyskania liczby całkowitej, a nie liczby zmiennoprzecinkowej. //jest operatorem podziału podłogi: „podział, który daje wynik w postaci liczby całkowitej dostosowanej do lewej strony w linii liczbowej”, patrz tutaj .
Eerik Sven Puudist

1
@EerikSvenPuudist, jak jcrswskazano, -1//3600jest -1, więc dlaczego nie użyć int(td.seconds/3600)zamiast tego, aby zmienić -1sekundę w 0godziny zamiast 1godziny wstecz?
simpleuser

co powiesz na dodanie pozostałych sekund? days, hours, minutes = x.days, x.seconds // 3600, x.seconds %3600//60a następnie seconds = x.seconds - hours*3600 - minutes*60
raphael

73

Jest to nieco bardziej kompaktowe, godziny, minuty i sekundy są wyświetlane w dwóch wierszach.

days = td.days
hours, remainder = divmod(td.seconds, 3600)
minutes, seconds = divmod(remainder, 60)
# If you want to take into account fractions of a second
seconds += td.microseconds / 1e6

7
jest niepoprawny, jeśli td.daysjest niezerowy. Trzeba hours += td.days*24. Jeśli chcesz wziąć pod uwagę ułamki sekundy (OP nie); seconds += td.microseconds / 1e6może być użyty.
jfs

30
days, hours, minutes = td.days, td.seconds // 3600, td.seconds // 60 % 60

Jeśli chodzi o czas letni, myślę, że najlepszą rzeczą jest konwersja obu datetimeobiektów na sekundy. W ten sposób system oblicza dla Ciebie czas letni.

>>> m13 = datetime(2010, 3, 13, 8, 0, 0)  # 2010 March 13 8:00 AM
>>> m14 = datetime(2010, 3, 14, 8, 0, 0)  # DST starts on this day, in my time zone
>>> mktime(m14.timetuple()) - mktime(m13.timetuple())     # difference in seconds
82800.0
>>> _/3600                                                # convert to hours
23.0

1
mktime()może się nie powieść, jeśli lokalna strefa czasowa może mieć różne przesunięcie utc w różnym czasie (wielu tak robi) - możesz użyć pytzmodułu, aby uzyskać dostęp do bazy danych tz w przenośny, determinacyjny sposób. Czas lokalny może być również niejednoznaczny (50% szans na błąd) - potrzebujesz dodatkowych informacji, aby ujednoznacznić, np. Często (nie zawsze) daty w pliku dziennika są monotonne . Zobacz Jak mogę odjąć dzień od daty pytona? które mogą mieć do czynienia z podobnymi problemami.
jfs

7

Nie rozumiem

days, hours, minutes = td.days, td.seconds // 3600, td.seconds // 60 % 60

co powiesz na to

days, hours, minutes = td.days, td.seconds // 3600, td.seconds % 3600 / 60.0

Dostajesz minuty i sekundy minuty jako liczba zmiennoprzecinkowa.


0

Użyłem następujących:

delta = timedelta()
totalMinute, second = divmod(delta.seconds, 60)
hour, minute = divmod(totalMinute, 60)
print(f"{hour}h{minute:02}m{second:02}s")

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.