¿Cómo encuentro la diferencia horaria entre dos objetos datetime en python?

Respuestas:

374
>>> import datetime
>>> first_time = datetime.datetime.now()
>>> later_time = datetime.datetime.now()
>>> difference = later_time - first_time
>>> seconds_in_day = 24 * 60 * 60
datetime.timedelta(0, 8, 562000)
>>> divmod(difference.days * seconds_in_day + difference.seconds, 60)
(0, 8)      # 0 minutes, 8 seconds

Restar el tiempo posterior de la primera vez difference = later_time - first_timecrea un objeto datetime que solo contiene la diferencia. En el ejemplo anterior, son 0 minutos, 8 segundos y 562000 microsegundos.

SilentGhost
fuente
2
Referencia: docs.python.org/library/datetime.html#datetime-objects . Lea "operaciones compatibles".
S.Lott
@SilentGhost, Cómo llegar con horas, minutos, segundos
Mulagala
1
@markcial: deloreantergiversaciones datetime, pytzenfoque , por ejemplo, el ejemplo de código de inicio podría escribirse como d = datetime.now(timezone(EST))(una línea legible en lugar de cinco).
jfs
1
nota: debe tener cuidado al realizar operaciones aritméticas de fecha / hora en objetos ingenuos de fecha y hora que representan la hora local. Puede fallar, por ejemplo, alrededor de las transiciones DST. Vea el enlace con más detalles en mi respuesta
jfs
¿Cómo se usa c para encontrar la diferencia en términos de días, min, seg?
Zeeshan Mahmood
152

Nuevo en Python 2.7 es el timedeltamétodo de instancia .total_seconds(). De los documentos de Python, esto es equivalente a (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6.

Referencia: http://docs.python.org/2/library/datetime.html#datetime.timedelta.total_seconds

>>> import datetime
>>> time1 = datetime.datetime.now()
>>> time2 = datetime.datetime.now() # waited a few minutes before pressing enter
>>> elapsedTime = time2 - time1
>>> elapsedTime
datetime.timedelta(0, 125, 749430)
>>> divmod(elapsedTime.total_seconds(), 60)
(2.0, 5.749430000000004) # divmod returns quotient and remainder
# 2 minutes, 5.74943 seconds
Ryan Stanley
fuente
107

Usando el ejemplo de fecha y hora

>>> from datetime import datetime
>>> then = datetime(2012, 3, 5, 23, 8, 15)        # Random date in the past
>>> now  = datetime.now()                         # Now
>>> duration = now - then                         # For build-in functions
>>> duration_in_s = duration.total_seconds()      # Total number of seconds between dates

Duración en años

>>> years = divmod(duration_in_s, 31536000)[0]    # Seconds in a year=365*24*60*60 = 31536000.

Duración en dias

>>> days  = duration.days                         # Build-in datetime function
>>> days  = divmod(duration_in_s, 86400)[0]       # Seconds in a day = 86400

Duración en horas

>>> hours = divmod(duration_in_s, 3600)[0]        # Seconds in an hour = 3600

Duración en minutos

>>> minutes = divmod(duration_in_s, 60)[0]        # Seconds in a minute = 60

Duración en segundos

>>> seconds = duration.seconds                    # Build-in datetime function
>>> seconds = duration_in_s

Duración en microsegundos

>>> microseconds = duration.microseconds          # Build-in datetime function  

Duración total entre las dos fechas.

>>> days    = divmod(duration_in_s, 86400)        # Get days (without [0]!)
>>> hours   = divmod(days[1], 3600)               # Use remainder of days to calc hours
>>> minutes = divmod(hours[1], 60)                # Use remainder of hours to calc minutes
>>> seconds = divmod(minutes[1], 1)               # Use remainder of minutes to calc seconds
>>> print("Time between dates: %d days, %d hours, %d minutes and %d seconds" % (days[0], hours[0], minutes[0], seconds[0]))

o simplemente:

>>> print(now - then)

Editar 2019 Dado que esta respuesta ha ganado popularidad, agregaré una función que podría simplificar el uso para algunos

from datetime import datetime

def getDuration(then, now = datetime.now(), interval = "default"):

    # Returns a duration as specified by variable interval
    # Functions, except totalDuration, returns [quotient, remainder]

    duration = now - then # For build-in functions
    duration_in_s = duration.total_seconds() 

    def years():
      return divmod(duration_in_s, 31536000) # Seconds in a year=31536000.

    def days(seconds = None):
      return divmod(seconds if seconds != None else duration_in_s, 86400) # Seconds in a day = 86400

    def hours(seconds = None):
      return divmod(seconds if seconds != None else duration_in_s, 3600) # Seconds in an hour = 3600

    def minutes(seconds = None):
      return divmod(seconds if seconds != None else duration_in_s, 60) # Seconds in a minute = 60

    def seconds(seconds = None):
      if seconds != None:
        return divmod(seconds, 1)   
      return duration_in_s

    def totalDuration():
        y = years()
        d = days(y[1]) # Use remainder to calculate next variable
        h = hours(d[1])
        m = minutes(h[1])
        s = seconds(m[1])

        return "Time between dates: {} years, {} days, {} hours, {} minutes and {} seconds".format(int(y[0]), int(d[0]), int(h[0]), int(m[0]), int(s[0]))

    return {
        'years': int(years()[0]),
        'days': int(days()[0]),
        'hours': int(hours()[0]),
        'minutes': int(minutes()[0]),
        'seconds': int(seconds()),
        'default': totalDuration()
    }[interval]

# Example usage
then = datetime(2012, 3, 5, 23, 8, 15)
now = datetime.now()

print(getDuration(then)) # E.g. Time between dates: 7 years, 208 days, 21 hours, 19 minutes and 15 seconds
print(getDuration(then, now, 'years'))      # Prints duration in years
print(getDuration(then, now, 'days'))       #                    days
print(getDuration(then, now, 'hours'))      #                    hours
print(getDuration(then, now, 'minutes'))    #                    minutes
print(getDuration(then, now, 'seconds'))    #                    seconds
Attaque
fuente
77
No sé por qué nadie te ha agradecido. Muchas gracias por una respuesta tan precisa. @Attaque
Amandeep Singh Sawhney
Tengo un error TypeError: 'float' object is not subscriptablecuando uso para:then = datetime(2017, 8, 11, 15, 58, tzinfo=pytz.UTC) now = datetime(2018, 8, 11, 15, 58, tzinfo=pytz.UTC) getDuration(then, now, 'years')
Piotr Wasilewicz
1
Eso es porque no puedo contar la cantidad de segundos en un año :) 365 * 24 * 60 * 60 = 31536000 y no 31556926. Actualicé la respuesta y las funciones y debería funcionar ahora.
Ataque el
1
Esta debería ser la respuesta aceptada.
saran3h
28

Solo resta uno del otro. Obtienes un timedeltaobjeto con la diferencia.

>>> import datetime
>>> d1 = datetime.datetime.now()
>>> d2 = datetime.datetime.now() # after a 5-second or so pause
>>> d2 - d1
datetime.timedelta(0, 5, 203000)

Puedes convertir dd.days, dd.secondsy dd.microsecondsa minutos.

Vinay Sajip
fuente
¿Cuáles son esos parámetros? Los comentarios estarían bien
TheRealChx101
22

Si a, bson objetos de fecha y hora, entonces para encontrar la diferencia horaria entre ellos en Python 3:

from datetime import timedelta

time_difference = a - b
time_difference_in_minutes = time_difference / timedelta(minutes=1)

En versiones anteriores de Python:

time_difference_in_minutes = time_difference.total_seconds() / 60

Si a, bson de fecha y hora ingenua objetos tales como devuelto por datetime.now()entonces el resultado puede ser errónea si los objetos representan el tiempo local con diferentes UTC compensaciones por ejemplo, alrededor de las transiciones de horario de verano o para fechas / futuras pasadas. Más detalles: Encuentre si han pasado 24 horas entre fechas y horas - Python .

Para obtener resultados confiables, use la hora UTC o los objetos datetime con reconocimiento de zona horaria.

jfs
fuente
17

Use divmod:

now = int(time.time()) # epoch seconds
then = now - 90000 # some time in the past

d = divmod(now-then,86400)  # days
h = divmod(d[1],3600)  # hours
m = divmod(h[1],60)  # minutes
s = m[1]  # seconds

print '%d days, %d hours, %d minutes, %d seconds' % (d[0],h[0],m[0],s)
tgwaste
fuente
1
Esto debe ponerse en el módulo de fecha y hora. Simplemente no puedo entender por qué usó solo días, segundos y milis ...
paulochf 05 de
Esto no responde la pregunta sobre los objetos de fecha y hora.
elec3647
10

Así es como obtengo la cantidad de horas que transcurrieron entre dos objetos datetime.datetime:

before = datetime.datetime.now()
after  = datetime.datetime.now()
hours  = math.floor(((after - before).seconds) / 3600)
Tony
fuente
99
Esto no funcionará: timedelta.secondssolo da el número de segundos almacenados explícitamente , que la documentación garantiza que sumarán menos de un día. Desea (after - before).total_seconds(), lo que da la cantidad de segundos que abarcan todo el delta.
lvc
1
(after - before).total_seconds() // 3600(Python 2.7) o (after - before) // timedelta(seconds=3600)(Python 3)
jfs
@lvc Mi antiguo código en realidad estaba escrito de esa manera, y pensé que estaba siendo inteligente y lo "arreglaba". Gracias por la corrección.
Tony
@JFSebastian Gracias por eso, me olvidé del operador //. Y sí, me gusta más la sintaxis de py3, pero estoy usando 2.7.
Tony
9

Para encontrar el número de días: timedelta tiene un atributo 'days'. Simplemente puede consultar eso.

>>>from datetime import datetime, timedelta
>>>d1 = datetime(2015, 9, 12, 13, 9, 45)
>>>d2 = datetime(2015, 8, 29, 21, 10, 12)
>>>d3 = d1- d2
>>>print d3
13 days, 15:59:33
>>>print d3.days
13
griknus17
fuente
5

Solo pensé que podría ser útil mencionar el formato también en lo que respecta a timedelta. strptime () analiza una cadena que representa un tiempo de acuerdo con un formato.

from datetime import datetime

datetimeFormat = '%Y/%m/%d %H:%M:%S.%f'    
time1 = '2016/03/16 10:01:28.585'
time2 = '2016/03/16 09:56:28.067'  
time_dif = datetime.strptime(time1, datetimeFormat) - datetime.strptime(time2,datetimeFormat)
print(time_dif)

Esto generará: 0: 05: 00.518000

gorrión
fuente
3

Yo uso algo así:

from datetime import datetime

def check_time_difference(t1: datetime, t2: datetime):
    t1_date = datetime(
        t1.year,
        t1.month,
        t1.day,
        t1.hour,
        t1.minute,
        t1.second)

    t2_date = datetime(
        t2.year,
        t2.month,
        t2.day,
        t2.hour,
        t2.minute,
        t2.second)

    t_elapsed = t1_date - t2_date

    return t_elapsed

# usage 
f = "%Y-%m-%d %H:%M:%S+01:00"
t1 = datetime.strptime("2018-03-07 22:56:57+01:00", f)
t2 = datetime.strptime("2018-03-07 22:48:05+01:00", f)
elapsed_time = check_time_difference(t1, t2)

print(elapsed_time)
#return : 0:08:52
Softmixt
fuente
2
obtienes citas perfectamente buenas, ¿por qué las copias? eso es 75% de su código puede ser expresado porreturn t1-t2
Patrick Artner
2

esto es para encontrar la diferencia entre la hora actual y las 9.30 a.m.

t=datetime.now()-datetime.now().replace(hour=9,minute=30)
nidheesh
fuente
1

Este es mi enfoque usando mktime .

from datetime import datetime, timedelta
from time import mktime

yesterday = datetime.now() - timedelta(days=1)
today = datetime.now()

difference_in_seconds = abs(mktime(yesterday.timetuple()) - mktime(today.timetuple()))
difference_in_minutes = difference_in_seconds / 60
Eduardo
fuente
mktime()espera la hora local como entrada. La hora local puede ser ambigua y mktime()puede devolver una respuesta incorrecta en este caso. Utilice en su a - blugar (a, b - objetos de fecha y hora) . mktime()es innecesario y a veces está mal. No lo uses en este caso.
jfs
@AnneTheAgile, arreglado, mi error en la importación. Probado en Python 2.7.12
Eduardo
1

En otras formas de obtener la diferencia entre la fecha;

import dateutil.parser
import datetime
last_sent_date = "" # date string
timeDifference = current_date - dateutil.parser.parse(last_sent_date)
time_difference_in_minutes = (int(timeDifference.days) * 24 * 60) + int((timeDifference.seconds) / 60)

Entonces obtenga salida en Min.

Gracias

Anurag Pandey
fuente
1

He utilizado las diferencias de tiempo para las pruebas de integración continua para verificar y mejorar mis funciones. Aquí hay un código simple si alguien lo necesita

from datetime import datetime

class TimeLogger:
    time_cursor = None

    def pin_time(self):
        global time_cursor
        time_cursor = datetime.now()

    def log(self, text=None) -> float:
        global time_cursor

        if not time_cursor:
            time_cursor = datetime.now()

        now = datetime.now()
        t_delta = now - time_cursor

        seconds = t_delta.total_seconds()

        result = str(now) + ' tl -----------> %.5f' % seconds
        if text:
            result += "   " + text
        print(result)

        self.pin_time()

        return seconds


time_logger = TimeLogger()

Utilizando:

from .tests_time_logger import time_logger
class Tests(TestCase):
    def test_workflow(self):
    time_logger.pin_time()

    ... my functions here ...

    time_logger.log()

    ... other function(s) ...

    time_logger.log(text='Tests finished')

y tengo algo así en la salida del registro

2019-12-20 17:19:23.635297 tl -----------> 0.00007
2019-12-20 17:19:28.147656 tl -----------> 4.51234   Tests finished
Serg Smyk
fuente
0

Basado en la excelente respuesta de @Attaque , propongo una versión simplificada más corta de la calculadora de diferencia de fecha y hora:

seconds_mapping = {
    'y': 31536000,
    'm': 2628002.88, # this is approximate, 365 / 12; use with caution
    'w': 604800,
    'd': 86400,
    'h': 3600,
    'min': 60,
    's': 1,
    'mil': 0.001,
}

def get_duration(d1, d2, interval, with_reminder=False):
    if with_reminder:
        return divmod((d2 - d1).total_seconds(), seconds_mapping[interval])
    else:
        return (d2 - d1).total_seconds() / seconds_mapping[interval]

Lo cambié para evitar declarar funciones repetitivas, eliminé el intervalo predeterminado de impresión bonita y agregué soporte para milisegundos, semanas y meses ISO (teniendo en cuenta que los meses son solo aproximados, en base a la suposición de que cada mes es igual a 365/12).

Que produce:

d1 = datetime(2011, 3, 1, 1, 1, 1, 1000)
d2 = datetime(2011, 4, 1, 1, 1, 1, 2500)

print(get_duration(d1, d2, 'y', True))      # => (0.0, 2678400.0015)
print(get_duration(d1, d2, 'm', True))      # => (1.0, 50397.12149999989)
print(get_duration(d1, d2, 'w', True))      # => (4.0, 259200.00149999978)
print(get_duration(d1, d2, 'd', True))      # => (31.0, 0.0014999997802078724)
print(get_duration(d1, d2, 'h', True))      # => (744.0, 0.0014999997802078724)
print(get_duration(d1, d2, 'min', True))    # => (44640.0, 0.0014999997802078724)
print(get_duration(d1, d2, 's', True))      # => (2678400.0, 0.0014999997802078724)
print(get_duration(d1, d2, 'mil', True))    # => (2678400001.0, 0.0004999997244524721)

print(get_duration(d1, d2, 'y', False))     # => 0.08493150689687975
print(get_duration(d1, d2, 'm', False))     # => 1.019176965856293
print(get_duration(d1, d2, 'w', False))     # => 4.428571431051587
print(get_duration(d1, d2, 'd', False))     # => 31.00000001736111
print(get_duration(d1, d2, 'h', False))     # => 744.0000004166666
print(get_duration(d1, d2, 'min', False))   # => 44640.000024999994
print(get_duration(d1, d2, 's', False))     # => 2678400.0015
print(get_duration(d1, d2, 'mil', False))   # => 2678400001.4999995
Voy
fuente