Convierta un timedelta a días, horas y minutos

242

Tengo un timedelta. Quiero los días, horas y minutos de eso, ya sea como una tupla o un diccionario ... No estoy preocupado.

Debo haber hecho esto una docena de veces en una docena de idiomas a lo largo de los años, pero Python generalmente tiene una respuesta simple a todo, así que pensé en preguntar aquí antes de revelar algunas matemáticas nauseabundamente simples (pero detalladas).

El Sr. Fooz plantea un buen punto.

Estoy tratando con "listados" (un poco como los listados de eBay) donde cada uno tiene una duración. Estoy tratando de encontrar el tiempo que queda haciendowhen_added + duration - now

¿Tengo razón al decir que eso no representaría el horario de verano? Si no, ¿cuál es la forma más simple de sumar / restar una hora?

Oli
fuente
Si es solo para obtenerlo como una cadena en formato HH: mm: ss, diga "0:19:37" del timedeltaobjeto "datetime.timedelta (segundos = 1177)" : simplemente use str ()
Peter Mortensen

Respuestas:

343

Si tiene un datetime.timedeltavalor td, td.daysya le da los "días" que desea. timedeltalos valores mantienen la fracción del día como segundos (no directamente horas o minutos), por lo que, de hecho, tendrá que realizar "matemáticas nauseabundamente simples", por ejemplo:

def days_hours_minutes(td):
    return td.days, td.seconds//3600, (td.seconds//60)%60
Alex Martelli
fuente
1
Tenga en cuenta que si tdes negativo, -1 // 3600es -1.
jcrs
44
por qué // ? en lugar de /
Mohammed Shareef C
10
//se usa en lugar de /obtener un número entero, no un flotante. //es un operador de división de piso: "división que resulta en un número entero ajustado a la izquierda en la línea numérica", vea aquí .
Eerik Sven Puudista el
1
@EerikSvenPuudist como jcrsfuera de punta, -1//3600está -1, ¿por qué no usar int(td.seconds/3600)en lugar de convertir -1segundos en 0horas en lugar de 1hacia atrás por hora?
simpleuser
¿qué tal agregar los segundos restantes también? days, hours, minutes = x.days, x.seconds // 3600, x.seconds %3600//60y luego seconds = x.seconds - hours*3600 - minutes*60
raphael
73

Esto es un poco más compacto, obtienes las horas, minutos y segundos en dos líneas.

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
fuente
77
es incorrecto si td.daysno es cero. Es necesario hours += td.days*24. Si desea tener en cuenta fracciones de segundo (OP no); seconds += td.microseconds / 1e6puede ser usado.
jfs
30
days, hours, minutes = td.days, td.seconds // 3600, td.seconds // 60 % 60

En cuanto a DST, creo que lo mejor es convertir ambos datetimeobjetos en segundos. De esta manera, el sistema calcula el horario de verano por usted.

>>> 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
fuente
1
mktime()puede fallar si la zona horaria local puede tener un desplazamiento utc diferente en diferentes momentos (muchos lo hacen); podría usar el pytzmódulo para obtener acceso a la base de datos tz de una manera deteminista portátil. Además, la hora local puede ser ambigua (50% de posibilidades de error): necesita información adicional para desambiguar, por ejemplo, a menudo (no siempre) las fechas en un archivo de registro son monótonas . Consulte ¿Cómo puedo restar un día de una fecha de Python? eso puede tener que lidiar con problemas similares.
jfs
7

No entiendo

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

Qué tal esto

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

Tienes minutos y segundos de un minuto como flotador.

Campbell
fuente
0

Usé lo siguiente:

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
fuente
-2

los timedeltas tienen un atributo daysy seconds... puedes convertirlos tú mismo con facilidad.

Jochen Ritzel
fuente