Converter um intervalo de tempo em dias, horas e minutos

242

Eu tenho um cronograma. Quero os dias, horas e minutos a partir disso - seja como tupla ou como dicionário ... não estou preocupado.

Eu devo ter feito isso uma dúzia de vezes em uma dúzia de idiomas ao longo dos anos, mas o Python geralmente tem uma resposta simples para tudo, então pensei em perguntar aqui antes de rebentar algumas matemáticas nauseantes simples (ainda que detalhadas).

O Sr. Fooz levanta uma boa questão.

Estou lidando com "listagens" (um pouco como listagens do ebay), nas quais cada uma tem uma duração. Estou tentando encontrar o tempo restante fazendowhen_added + duration - now

Estou certo ao dizer que não seria responsável pelo horário de verão? Caso contrário, qual é a maneira mais simples de adicionar / subtrair uma hora?

Oli
fonte
Se for apenas para obtê-lo como uma sequência no formato HH: mm: ss, diga "0:19:37" do timedeltaobjeto "datetime.timedelta (segundos = 1177)" : use str ()
Peter Mortensen

Respostas:

343

Se você tem um datetime.timedeltavalor td, td.daysjá fornece os "dias" que deseja. timedeltaos valores mantêm a fração do dia como segundos (não diretamente horas ou minutos), portanto você terá que executar "matemática simples nauseante simples", por exemplo:

def days_hours_minutes(td):
    return td.days, td.seconds//3600, (td.seconds//60)%60
Alex Martelli
fonte
1
Tenha em mente que se tdé negativo, -1 // 3600é -1.
JCRS
4
porque // ? em vez de /
Mohammed Shareef C
10
//é usado em vez de /obter um número inteiro, não um número flutuante. //é um operador de divisão de piso: "divisão que resulta em um número inteiro ajustado à esquerda na linha de números", veja aqui .
Eerik Sven Puudist
1
O @EerikSvenPuudist, como jcrsapontado, -1//3600é -1, então por que não usar int(td.seconds/3600)para transformar o -1segundo em 0horas em vez de 1horas para trás?
simpleuser 5/09/19
que tal adicionar os segundos restantes também? days, hours, minutes = x.days, x.seconds // 3600, x.seconds %3600//60e então seconds = x.seconds - hours*3600 - minutes*60
raphael
73

Isso é um pouco mais compacto, você obtém as horas, minutos e segundos em duas linhas.

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
mberacochea
fonte
7
está incorreto se td.daysfor diferente de zero. Você precisa hours += td.days*24. Se você deseja levar em consideração frações de segundo (OP não); seconds += td.microseconds / 1e6poderia ser usado.
JFS
30
days, hours, minutes = td.days, td.seconds // 3600, td.seconds // 60 % 60

Quanto ao horário de verão, acho que a melhor coisa é converter os dois datetimeobjetos em segundos. Dessa forma, o sistema calcula o horário de verão para você.

>>> 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
Jason Orendorff
fonte
1
mktime()pode falhar se o fuso horário local puder ter um deslocamento de utc diferente em momentos diferentes (muitos têm) - você pode usar o pytzmódulo para obter acesso ao banco de dados tz de uma maneira portadora de uma característica não-portátil. Além disso, a hora local pode ser ambígua (50% de chances de erro) - você precisa de algumas informações adicionais para desambiguar, por exemplo, muitas vezes (nem sempre) as datas em um arquivo de log são monótonas . Consulte Como posso subtrair um dia de uma data python? que pode ter que lidar com problemas semelhantes.
JFS
7

Eu não entendo

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

que tal agora

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

Você recebe minutos e segundos de um minuto como um flutuador.

Campbell
fonte
0

Eu usei o seguinte:

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

timedeltas tem um atributo dayse seconds.. você pode convertê-los com facilidade.

Jochen Ritzel
fonte