Planteamiento del problema
Parece que hay un error en el módulo de datetime de Python, el siguiente fragmento de código debería explicarse por sí mismo:
import datetime dep = datetime.datetime(2021, 9, 11, 7, 25) arr = datetime.datetime(2021, 9, 11, 12, 35) print(f"expected: -5h10m, real: {dep - arr}") print(f"expected: 5h10m, real: {arr - dep}")Lo que obtengo con python 3.10:
expected: -5h10m, real: -1 day, 18:50:00 expected: 5h10m, real: 5:10:00Pregunta
¿Es un error o una característica? Si es un error, ¿qué puedo hacer para solucionarlo?
Yo llamaría a este efecto
expected: -5h10m, real: -1 day, 18:50:00 expected: 5h10m, real: 5:10:00glitch , ya que se limita únicamente a mirar, mientras que ambos deltas tienen la misma cantidad de segundos y son iguales a su opuesto, lo que se puede verificar de la siguiente manera
import datetime dep = datetime.datetime(2021, 9, 11, 7, 25) arr = datetime.datetime(2021, 9, 11, 12, 35) delta1 = dep - arr delta2 = arr - dep print(delta1.total_seconds()) # -18600.0 print(delta2.total_seconds()) # 18600.0 print(delta1 == -delta2) # True print(delta2 == -delta1) # True print(delta1 + delta2) # 0:00:00Es una característica: la resta de datetime de datetime da como resultado un objeto timedelta , que se normaliza para que solo el valor negativo pueda ser days . Ese comportamiento está documentado, por ejemplo. aquí: https://pl.python.org/docs/lib/datetime-timedelta.html
puede ver la implementación de restar en objetos de fecha y hora, pero esencialmente hace lo mismo que el código a continuación.
import datetime dep = datetime.datetime(2021, 9, 11, 7, 25) arr = datetime.datetime(2021, 9, 11, 12, 35) dep_days = dep.toordinal() arr_days = dep.toordinal() dep_secs = dep.second + dep.minute * 60 + dep.hour * 3600 arr_secs = arr.second + arr.minute * 60 + arr.hour * 3600 day_diff = dep_days - arr_days sec_diff = dep_secs - arr_secs micro_diff = dep.microsecond - arr.microsecond base = datetime.timedelta(day_diff,sec_diff,micro_diff) print(base)el timedelta te dice que retrocedes un día en el tiempo y luego avanzas 18 horas y 50 minutos, lo que realmente significa retroceder 24 horas + 18 horas 50 = 5 horas 10 minutos
si solo está interesado en esto desde el punto de vista de la presentación de cadenas, puede envolver esto en una función simple que le dará una representación de cadena relativa de la diferencia horaria
import datetime def relative_time_str(delta: datetime.timedelta): neutral = datetime.timedelta() if delta < neutral: return f"-{neutral - delta}" return f"{delta}" dep = datetime.datetime(2021, 9, 11, 7, 25) arr = datetime.datetime(2021, 9, 11, 12, 35) print(f"expected: -5h10m, real: {relative_time_str(dep - arr)}") print(f"expected: 5h10m, real: {relative_time_str(arr - dep)}")PRODUCCIÓN
expected: -5h10m, real: -5:10:00 expected: 5h10m, real: 5:10:00