Come trovo la differenza di tempo tra due oggetti datetime in Python?


Risposte:


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

Sottraendo la volta successiva dalla prima volta si difference = later_time - first_timecrea un oggetto datetime che contiene solo la differenza. Nell'esempio sopra sono 0 minuti, 8 secondi e 562000 microsecondi.


2
Riferimento: docs.python.org/library/datetime.html#datetime-objects . Leggi "operazioni supportate".
S.Lott

@SilentGhost, Come arrivare con ore, minuti, secondi
Mulagala

1
@markcial: deloreantravisamenti datetime, pytzapproccio ad esempio, l'esempio di codice iniziale potrebbe essere scritto come d = datetime.now(timezone(EST))(una riga leggibile anziché cinque).
jfs,

1
nota: prestare attenzione quando si eseguono aritmetiche di data / ora su oggetti datetime ingenui che rappresentano l'ora locale. Potrebbe non funzionare ad es. Attorno alle transizioni dell'ora legale. Vedi il link con maggiori dettagli nella mia risposta
jfs

Come si usa c per trovare la differenza in termini di giorni, min, sec?
Zeeshan Mahmood,

152

Una novità di Python 2.7 è il timedeltametodo di istanza .total_seconds(). Dai documenti di Python, questo equivale a (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6.

Riferimento: 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


107

Utilizzando l'esempio datetime

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

Durata in anni

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

Durata in giorni

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

Durata in ore

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

Durata in minuti

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

Durata in secondi

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

Durata in microsecondi

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

Durata totale tra le due date

>>> 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 semplicemente:

>>> print(now - then)

Modifica 2019 Dato che questa risposta ha guadagnato trazione, aggiungerò una funzione, che potrebbe semplificarne l'utilizzo per alcuni

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

7
Non so perché nessuno ti abbia ringraziato. Grazie mille per una risposta così precisa. @Attaque
Amandeep Singh Sawhney,

Ho un errore TypeError: 'float' object is not subscriptablequando uso per: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 il

1
Questo perché non riesco a contare il numero di secondi in un anno :) 365 * 24 * 60 * 60 = 31536000 e non 31556926. Ho aggiornato la risposta e le funzioni e ora dovrebbe funzionare.
Attaque,

1
Questa dovrebbe essere la risposta accettata.
saran3h

28

Sottrarre l'uno dall'altro. Ottieni un timedeltaoggetto con la differenza.

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

È possibile convertire dd.days, dd.secondsed dd.microsecondsa pochi minuti.


Quali sono questi parametri? I commenti sarebbero belli
TheRealChx101

22

Se a, bsono oggetti datetime, allora per trovare la differenza di tempo tra loro in Python 3:

from datetime import timedelta

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

Nelle versioni precedenti di Python:

time_difference_in_minutes = time_difference.total_seconds() / 60

Se a, bsono oggetti datetime naive come quella restituita dalla datetime.now()allora il risultato può essere sbagliato se gli oggetti rappresentano ora locale con diverse UTC offset ad esempio, le transizioni in tutto o DST per le date / future passate. Maggiori dettagli: Scopri se sono trascorse 24 ore tra un periodo di tempo e l'altro - Python .

Per ottenere risultati affidabili, utilizzare l'ora UTC o gli oggetti datetime sensibili al fuso orario.


17

Usa 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)

1
Questo dovrebbe essere inserito nel modulo datetime. Non riesco proprio a capire perché abbia usato solo giorni, secondi e millis ...
paulochf,

Questo non risponde alla domanda relativa agli oggetti datetime.
elec3647,

10

Ecco come ottengo il numero di ore trascorse tra due oggetti datetime.datetime:

before = datetime.datetime.now()
after  = datetime.datetime.now()
hours  = math.floor(((after - before).seconds) / 3600)

9
Non funzionerà del tutto: timedelta.secondsfornisce solo il numero di secondi memorizzati in modo esplicito , che la garanzia della documentazione avrà in totale meno di un giorno. Volete (after - before).total_seconds(), che fornisce il numero di secondi che coprono l' intero delta.
PVC

1
(after - before).total_seconds() // 3600(Python 2.7) o (after - before) // timedelta(seconds=3600)(Python 3)
jfs

@lvc Il mio vecchio codice è stato effettivamente scritto in quel modo, e pensavo di essere intelligente e di "sistemarlo". Grazie per la correzione.
Tony,

@JFSebastian Grazie per questo, mi sono dimenticato dell'operatore //. E mi piace la sintassi py3 meglio, ma sto usando 2.7.
Tony,

9

Per trovare solo il numero di giorni: timedelta ha un attributo 'giorni'. Puoi semplicemente interrogarlo.

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

5

Ho pensato che potesse essere utile menzionare anche la formattazione per quanto riguarda timedelta. strptime () analizza una stringa che rappresenta un'ora in base a 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)

Questo produrrà: 0: 05: 00.518000


3

Uso qualcosa del genere:

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

2
ottieni dei dati perfettamente validi, perché li copi? il 75% del tuo codice può essere espresso dareturn t1-t2
Patrick Artner,

2

questo per trovare la differenza tra l'ora corrente e le 9.30

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

1

Questo è il mio approccio 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

mktime()si aspetta l'ora locale come input. L'ora locale mktime()potrebbe essere ambigua e potrebbe restituire una risposta errata in questo caso. Utilizzare a - binvece (a, b - oggetti datetime) . mktime()non è necessario e talvolta è sbagliato. Non usarlo in questo caso.
jfs,

@AnneTheAgile, risolto, colpa mia sull'importazione. Testato su Python 2.7.12
Eduardo il

1

In altri modi per ottenere la differenza tra la data;

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)

Quindi ottieni output in Min.

Grazie


1

Ho usato le differenze di tempo per i test di integrazione continua per verificare e migliorare le mie funzioni. Ecco un semplice codice se qualcuno ne ha bisogno

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()

usando:

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')

e ho qualcosa del genere nell'output del registro

2019-12-20 17:19:23.635297 tl -----------> 0.00007
2019-12-20 17:19:28.147656 tl -----------> 4.51234   Tests finished

0

Sulla base della grande risposta di @Attaque , propongo una versione semplificata più breve del calcolatore della differenza di data e ora:

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]

L'ho modificato per evitare di dichiarare funzioni ripetitive, rimosso l'intervallo predefinito di stampa piuttosto e aggiunto il supporto per millisecondi, settimane e mesi ISO (i mesi nudi sono solo approssimativi, in base al presupposto che ogni mese è uguale a 365/12).

Che 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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.