timedeltanie jest bezpieczny przed przepełnieniem i nie może poprawnie wykonywać operacji matematycznych, np str(timedelta(hours=8) - timedelta(hours=10)). wynik jest, '-1 day, 22:00:00'a rozwiązanie oparte na liczbach całkowitych jest dokładnie w tych sytuacjach, w których potrzebujesz '-02:00:00'.
cprn
1
+1. Ta odpowiedź może być bardzo łatwo zmodyfikowana. Na przykład, jeśli chcesz pominąć pole podczas drukowania, użyj tego: stackoverflow.com/questions/7999935/…
eric_kernfeld 10.10.2018
614
Używając divmod()funkcji, która wykonuje tylko jeden podział w celu wygenerowania zarówno ilorazu, jak i reszty, możesz bardzo szybko uzyskać wynik za pomocą tylko dwóch operacji matematycznych:
m, s = divmod(seconds,60)
h, m = divmod(m,60)
A następnie użyj formatowania ciągów, aby przekonwertować wynik na pożądany wynik:
print('{:d}:{:02d}:{:02d}'.format(h, m, s))# Python 3print(f'{h:d}:{m:02d}:{s:02d}')# Python 3.6+
Jeśli wolisz operatory niż funkcje, użyj modulo; na przykład (tylko minuty / sekundy):'%d:%02dmn' % (seconds / 60, seconds % 60)
bufh
18
I można go przedłużyć do dni: d, h = divmod(h, 24).
Mark Ransom
14
@MarkRansom: a następnie do miesięcy m, d = divmod(m, 31). Ups, nie, nie możesz. Co gorsza, twój kod będzie nieprawidłowy, jeśli w grze pojawią się sekundy przestępne. Krótko mówiąc: używaj timedeltai nie zadzieraj z kalendarzem, to cię ugryzie.
4
@ Tibo timedeltazajmuje się sekundami przestępnymi? Nie podejrzewam Istnieje wiele aplikacji, w których ta prosta matematyka jest więcej niż wystarczająca.
Mark Ransom
1
@ MarkRansom str(timedelta(hours=8) - timedelta(hours=10))wynikiem jest „-1 dzień, 22:00:00”, więc ... idk, jeśli działa z sekundami przestępnymi, ale nie działa z liczbami ujemnymi.
cprn
69
Trudno nazwać to łatwym sposobem (przynajmniej nie pamiętam składni), ale można użyć time.strftime , który daje większą kontrolę nad formatowaniem:
from time import strftime
from time import gmtime
strftime("%H:%M:%S", gmtime(666))'00:11:06'
strftime("%H:%M:%S", gmtime(60*60*24))'00:00:00'
gmtime służy do konwertowania sekund na specjalny strftime()wymagany krotek .
Niestety ta metoda zaczyna mierzyć dni od 1, więc nie jest zaprojektowana do reprezentowania delty czasowej, a więc jest to wypadek, który czeka. Na przykład z time.strftime('%d %H:%M:%S', time.gmtime(1))=> „1 dzień, 0:00:01”.
from time import gmtime
from time import strftime
# NOTE: The following resets if it goes over 23:59:59!
strftime("%H:%M:%S", gmtime(125))# Result: '00:02:05'
strftime("%H:%M:%S", gmtime(60*60*24-1))# Result: '23:59:59'
strftime("%H:%M:%S", gmtime(60*60*24))# Result: '00:00:00'
strftime("%H:%M:%S", gmtime(666777))# Result: '17:12:57'# Wrong
kończy się niepowodzeniem, jeśli delta jest mniejsza niż sekunda:"{:0>8}".format(timedelta(milliseconds=66)) '0:00:00.066000'
jfs
1
Do wszystkich innych: w without ':0>8':przykładzie brakuje wiodących {:0>8}padów zerowych na lewe 8 zer.
TankorSmash
2
W python 3.5.2 dostaję błąd typu. Formatuję time.time()-startzmienną. Jakiś wgląd? TypeError: non-empty format string passed to object.__format__
medley56,
Próbowałem użyć datetime.now()zamiast time.time()wygenerować mój obiekt timedelta i otrzymuję ten sam błąd.
medley56,
@ medley56 Podczas korzystania Python3, trzeba użyć str(), jeśli masz zamiar użyć formatu takich jak 0>8: "{:0>8}".format(str(datetime.timedelta(seconds=666777))). Sprawdź tę odpowiedź, aby uzyskać więcej informacji.
Berriel,
21
Oto moja szybka sztuczka:
from humanfriendly import format_timespan
secondsPassed =1302
format_timespan(secondsPassed)# '21 minutes and 42 seconds'
Zamiast tego 1możesz użyć dowolnej liczby większej niż 0. W tym przypadku wykorzystujemy fakt, że datetime.fromordinalzawsze zwróci datetimeobiekt o timeskładniku równym zero.
def sec2time(sec, n_msec=3):''' Convert seconds to 'D days, HH:MM:SS.FFF' '''if hasattr(sec,'__len__'):return[sec2time(s)for s in sec]
m, s = divmod(sec,60)
h, m = divmod(m,60)
d, h = divmod(h,24)if n_msec >0:
pattern ='%%02d:%%02d:%%0%d.%df'%(n_msec+3, n_msec)else:
pattern = r'%02d:%02d:%02d'if d ==0:return pattern %(h, m, s)return('%d days, '+ pattern)%(d, h, m, s)
dateutil.relativedeltajest wygodny, jeśli chcesz mieć dostęp do godzin, minut i sekund jako pływaków. datetime.timedeltanie zapewnia podobnego interfejsu.
from dateutil.relativedelta import relativedelta
rt = relativedelta(seconds=5440)print(rt.seconds)print('{:02d}:{:02d}:{:02d}'.format(
int(rt.hours), int(rt.minutes), int(rt.seconds)))
Dostaję inne wyniki niż twoje, co sprawia, że myślę, że masz literówkę. Prawdopodobnie chciałeś użyć seconds=5440zamiast seconds=5540. Jednak podoba mi się twoja odpowiedź!
JL
2
godziny (h) obliczone przez podział podłogi (przez //) sekund na 3600 (60 min / godz. * 60 sek / min)
minuty (m) obliczone przez podział podłogowy pozostałych sekund (pozostała część z obliczenia godziny, w%) o 60 (60 sekund / min)
podobnie, sekundy (s) w pozostałej części obliczenia godziny i minuty.
Reszta to tylko formatowanie ciągów!
def hms(seconds):
h = seconds //3600
m = seconds %3600//60
s = seconds %3600%60return'{:02d}:{:02d}:{:02d}'.format(h, m, s)print(hms(7500))# Should print 02h05m00s
Chociaż ten kod może stanowić rozwiązanie pytania PO, lepiej jest dodać kontekst wyjaśniający, dlaczego / jak to działa. Może to pomóc przyszłym użytkownikom w nauce i zastosowaniu tej wiedzy do własnego kodu. Prawdopodobnie będziesz otrzymywać pozytywne opinie od użytkowników w postaci pozytywnych opinii, gdy kod zostanie wyjaśniony.
borchvm
2
Właśnie zrobiłem, dziękuję @borchvm za wskazanie!
Sam
-2
Możesz podzielić sekundy przez 60, aby uzyskać minuty
import time
seconds = time.time()
minutes = seconds /60print(minutes)
Kiedy ponownie podzielisz go przez 60, dostaniesz godziny
Odpowiedzi:
Możesz użyć
datetime.timedelta
funkcji:źródło
str(datetime.timedelta(seconds=60*60*24+1))
='1 day, 0:00:01'
str(datetime.timedelta(seconds=round(666666.55)))
poprawnie renderuje dni; pomija sekundy dziesiętne.timedelta
nie jest bezpieczny przed przepełnieniem i nie może poprawnie wykonywać operacji matematycznych, npstr(timedelta(hours=8) - timedelta(hours=10))
. wynik jest,'-1 day, 22:00:00'
a rozwiązanie oparte na liczbach całkowitych jest dokładnie w tych sytuacjach, w których potrzebujesz'-02:00:00'
.Używając
divmod()
funkcji, która wykonuje tylko jeden podział w celu wygenerowania zarówno ilorazu, jak i reszty, możesz bardzo szybko uzyskać wynik za pomocą tylko dwóch operacji matematycznych:A następnie użyj formatowania ciągów, aby przekonwertować wynik na pożądany wynik:
źródło
'%d:%02dmn' % (seconds / 60, seconds % 60)
d, h = divmod(h, 24)
.m, d = divmod(m, 31)
. Ups, nie, nie możesz. Co gorsza, twój kod będzie nieprawidłowy, jeśli w grze pojawią się sekundy przestępne. Krótko mówiąc: używajtimedelta
i nie zadzieraj z kalendarzem, to cię ugryzie.timedelta
zajmuje się sekundami przestępnymi? Nie podejrzewam Istnieje wiele aplikacji, w których ta prosta matematyka jest więcej niż wystarczająca.str(timedelta(hours=8) - timedelta(hours=10))
wynikiem jest „-1 dzień, 22:00:00”, więc ... idk, jeśli działa z sekundami przestępnymi, ale nie działa z liczbami ujemnymi.Trudno nazwać to łatwym sposobem (przynajmniej nie pamiętam składni), ale można użyć time.strftime , który daje większą kontrolę nad formatowaniem:
gmtime służy do konwertowania sekund na specjalny
strftime()
wymagany krotek .źródło
time.strftime('%d %H:%M:%S', time.gmtime(1))
=> „1 dzień, 0:00:01”.Używanie
datetime
:W
':0>8'
formacie:Bez
':0>8'
formatu:Używanie
time
:źródło
"{:0>8}".format(timedelta(milliseconds=66)) '0:00:00.066000'
without ':0>8':
przykładzie brakuje wiodących{:0>8}
padów zerowych na lewe 8 zer.time.time()-start
zmienną. Jakiś wgląd?TypeError: non-empty format string passed to object.__format__
datetime.now()
zamiasttime.time()
wygenerować mój obiekt timedelta i otrzymuję ten sam błąd.str()
, jeśli masz zamiar użyć formatu takich jak0>8
:"{:0>8}".format(str(datetime.timedelta(seconds=666777)))
. Sprawdź tę odpowiedź, aby uzyskać więcej informacji.Oto moja szybka sztuczka:
Aby uzyskać więcej informacji Odwiedź: https://humanfriendly.readthedocs.io/en/latest/#humanfriendly.format_timespan
źródło
Jeśli chcesz uzyskać
datetime.time
wartość, możesz użyć tej sztuczki:Nie możesz dodawać
timedelta
dotime
, ale możesz dodać dodatetime
.UPD : Kolejna odmiana tej samej techniki:
Zamiast tego
1
możesz użyć dowolnej liczby większej niż 0. W tym przypadku wykorzystujemy fakt, żedatetime.fromordinal
zawsze zwrócidatetime
obiekt otime
składniku równym zero.źródło
Tak to dostałem.
Kilka przykładów:
źródło
str(datetime.timedelta(seconds=666))
666.0
i666.1
wartości.Poniższy zestaw działał dla mnie.
źródło
dateutil.relativedelta
jest wygodny, jeśli chcesz mieć dostęp do godzin, minut i sekund jako pływaków.datetime.timedelta
nie zapewnia podobnego interfejsu.Wydruki
źródło
seconds=5440
zamiastseconds=5540
. Jednak podoba mi się twoja odpowiedź!godziny (h) obliczone przez podział podłogi (przez //) sekund na 3600 (60 min / godz. * 60 sek / min)
minuty (m) obliczone przez podział podłogowy pozostałych sekund (pozostała część z obliczenia godziny, w%) o 60 (60 sekund / min)
podobnie, sekundy (s) w pozostałej części obliczenia godziny i minuty.
Reszta to tylko formatowanie ciągów!
źródło
Możesz podzielić sekundy przez 60, aby uzyskać minuty
Kiedy ponownie podzielisz go przez 60, dostaniesz godziny
źródło
PS Mój kod jest nieprofesjonalny
źródło