Esta é a melhor maneira, IMHO, pois você pode usar aritmética na timedelta e em qualquer objeto de data e hora.
Matthew Schinckel
13
Isso funciona por vários dias: str(datetime.timedelta(seconds=60*60*24+1))='1 day, 0:00:01'
hyprnick
3
str(datetime.timedelta(seconds=round(666666.55)))processa corretamente dias; suprime os segundos decimais.
CPBL 27/11
1
timedeltanão é seguro contra transbordamento e não pode executar operações matemáticas corretamente, por exemplo, str(timedelta(hours=8) - timedelta(hours=10))o resultado é '-1 day, 22:00:00'e a solução baseada em números inteiros é exatamente para as situações em que você precisa '-02:00:00'.
CPRN
1
+1. Esta resposta pode ser modificada com muita facilidade. Por exemplo, se você quiser omitir um campo ao imprimir, use o seguinte: stackoverflow.com/questions/7999935/…
eric_kernfeld 10/10
616
Usando a divmod()função, que faz apenas uma única divisão para produzir o quociente e o restante, é possível obter o resultado muito rapidamente com apenas duas operações matemáticas:
m, s = divmod(seconds,60)
h, m = divmod(m,60)
E, em seguida, use a formatação de string para converter o resultado na saída desejada:
print('{:d}:{:02d}:{:02d}'.format(h, m, s))# Python 3print(f'{h:d}:{m:02d}:{s:02d}')# Python 3.6+
Se você preferir operadores sobre funções, use o módulo; por exemplo (apenas minutos / segundos):'%d:%02dmn' % (seconds / 60, seconds % 60)
bufh 20/05
18
E você pode estendê-lo para dias: d, h = divmod(h, 24).
Mark Ransom
14
@ MarkRansom: e depois para meses m, d = divmod(m, 31). Oooops, não, você não pode. Pior, seu código estará errado se segundos de pulo entrarem no jogo. Para encurtar a história: use timedeltae não mexa no calendário, ele vai te morder.
4
@Tibo timedeltalida com segundos bissextos? Eu suspeito que não. Existem muitas aplicações em que essa matemática simples é mais que suficiente.
Mark Ransom
1
@MarkRansom str(timedelta(hours=8) - timedelta(hours=10))o resultado é '-1 dia, 22:00:00', então ... idk se funcionar com segundos bissextos, mas não funcionar com números negativos.
Cprn
70
Eu dificilmente posso nomear isso de uma maneira fácil (pelo menos não me lembro da sintaxe), mas é possível usar time.strftime , que oferece mais controle sobre a formatação:
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'
O gmtime é usado para converter segundos em um formato especial de tupla que strftime()requer.
Infelizmente, esse método começa a medir dias a partir de 1, para que não seja projetado para representar um delta de tempo e, portanto, é um acidente esperando para acontecer. Por exemplo, com time.strftime('%d %H:%M:%S', time.gmtime(1))=> '1 dia, 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
falhará se o delta for menor que um segundo:"{:0>8}".format(timedelta(milliseconds=66)) '0:00:00.066000'
jfs
1
Para todos os outros: O without ':0>8':exemplo está faltando um {:0>8}zero inicial à esquerda e 8 zeros à esquerda.
TankorSmash 24/07
2
No python 3.5.2, recebo um TypeError. Estou formatando uma time.time()-startvariável. Alguma visão? TypeError: non-empty format string passed to object.__format__
precisa saber é o seguinte
Tentei usar em datetime.now()vez de time.time()gerar meu objeto timedelta e recebo o mesmo erro.
medley56
@ medley56 Ao usar Python3, você precisa usar str()se você estiver indo usar um formato como 0>8: "{:0>8}".format(str(datetime.timedelta(seconds=666777))). Verifique esta resposta para mais informações.
Berriel
22
Este é o meu truque rápido:
from humanfriendly import format_timespan
secondsPassed =1302
format_timespan(secondsPassed)# '21 minutes and 42 seconds'
Em vez de 1você pode usar qualquer número maior que 0. Aqui usamos o fato de que datetime.fromordinalsempre retornará datetimeobjeto com o timecomponente sendo 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.relativedeltaé conveniente se você também precisar acessar horas, minutos e segundos enquanto flutua. datetime.timedeltanão fornece uma interface semelhante.
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)))
Estou tendo uma saída diferente da sua, o que me faz pensar que você tem um erro de digitação. Você provavelmente quis usar em seconds=5440vez de seconds=5540. Eu gosto da sua resposta!
JL
2
horas (h) calculadas pela divisão do piso (por //) de segundos em 3600 (60 min / h * 60 seg / min)
minutos (m) calculados pela divisão do piso dos segundos restantes (restante do cálculo da hora, em%) por 60 (60 s / min)
da mesma forma, segundos (s) pelo restante do cálculo de horas e minutos.
O resto é apenas formatação de string!
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
Embora esse código possa fornecer uma solução para a pergunta do OP, é melhor adicionar contexto sobre o porquê / como ele funciona. Isso pode ajudar os usuários futuros a aprender e aplicar esse conhecimento ao seu próprio código. Também é provável que você tenha um feedback positivo dos usuários na forma de upvotes, quando o código for explicado.
borchvm 10/02
2
Acabei de fazer, Obrigado @borchvm por apontar!
Sam
-2
Você pode dividir segundos por 60 para obter os minutos
import time
seconds = time.time()
minutes = seconds /60print(minutes)
Ao dividi-lo por 60 novamente, você receberá as horas
Respostas:
Você pode usar a
datetime.timedelta
função:fonte
str(datetime.timedelta(seconds=60*60*24+1))
='1 day, 0:00:01'
str(datetime.timedelta(seconds=round(666666.55)))
processa corretamente dias; suprime os segundos decimais.timedelta
não é seguro contra transbordamento e não pode executar operações matemáticas corretamente, por exemplo,str(timedelta(hours=8) - timedelta(hours=10))
o resultado é'-1 day, 22:00:00'
e a solução baseada em números inteiros é exatamente para as situações em que você precisa'-02:00:00'
.Usando a
divmod()
função, que faz apenas uma única divisão para produzir o quociente e o restante, é possível obter o resultado muito rapidamente com apenas duas operações matemáticas:E, em seguida, use a formatação de string para converter o resultado na saída desejada:
fonte
'%d:%02dmn' % (seconds / 60, seconds % 60)
d, h = divmod(h, 24)
.m, d = divmod(m, 31)
. Oooops, não, você não pode. Pior, seu código estará errado se segundos de pulo entrarem no jogo. Para encurtar a história: usetimedelta
e não mexa no calendário, ele vai te morder.timedelta
lida com segundos bissextos? Eu suspeito que não. Existem muitas aplicações em que essa matemática simples é mais que suficiente.str(timedelta(hours=8) - timedelta(hours=10))
o resultado é '-1 dia, 22:00:00', então ... idk se funcionar com segundos bissextos, mas não funcionar com números negativos.Eu dificilmente posso nomear isso de uma maneira fácil (pelo menos não me lembro da sintaxe), mas é possível usar time.strftime , que oferece mais controle sobre a formatação:
O gmtime é usado para converter segundos em um formato especial de tupla que
strftime()
requer.fonte
time.strftime('%d %H:%M:%S', time.gmtime(1))
=> '1 dia, 0:00:01'.Usando
datetime
:Com o
':0>8'
formato:Sem o
':0>8'
formato:Usando
time
:fonte
"{:0>8}".format(timedelta(milliseconds=66)) '0:00:00.066000'
without ':0>8':
exemplo está faltando um{:0>8}
zero inicial à esquerda e 8 zeros à esquerda.time.time()-start
variável. Alguma visão?TypeError: non-empty format string passed to object.__format__
datetime.now()
vez detime.time()
gerar meu objeto timedelta e recebo o mesmo erro.str()
se você estiver indo usar um formato como0>8
:"{:0>8}".format(str(datetime.timedelta(seconds=666777)))
. Verifique esta resposta para mais informações.Este é o meu truque rápido:
Para mais informações, visite: https://humanfriendly.readthedocs.io/en/latest/#humanfriendly.format_timespan
fonte
Se você precisar obter
datetime.time
valor, poderá usar este truque:Você não pode adicionar
timedelta
atime
, mas pode adicioná-lo adatetime
.UPD : Ainda outra variação da mesma técnica:
Em vez de
1
você pode usar qualquer número maior que 0. Aqui usamos o fato de quedatetime.fromordinal
sempre retornarádatetime
objeto com otime
componente sendo zero.fonte
É assim que eu entendi.
Alguns exemplos:
fonte
str(datetime.timedelta(seconds=666))
666.0
e666.1
valores.O seguinte conjunto funcionou para mim.
fonte
dateutil.relativedelta
é conveniente se você também precisar acessar horas, minutos e segundos enquanto flutua.datetime.timedelta
não fornece uma interface semelhante.Impressões
fonte
seconds=5440
vez deseconds=5540
. Eu gosto da sua resposta!horas (h) calculadas pela divisão do piso (por //) de segundos em 3600 (60 min / h * 60 seg / min)
minutos (m) calculados pela divisão do piso dos segundos restantes (restante do cálculo da hora, em%) por 60 (60 s / min)
da mesma forma, segundos (s) pelo restante do cálculo de horas e minutos.
O resto é apenas formatação de string!
fonte
Você pode dividir segundos por 60 para obter os minutos
Ao dividi-lo por 60 novamente, você receberá as horas
fonte
PS Meu código não é profissional
fonte