Comment puis-je trouver la différence de temps entre deux objets datetime en python?


Réponses:


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

La soustraction de la dernière heure de la première fois difference = later_time - first_timecrée un objet datetime qui ne conserve que la différence. Dans l'exemple ci-dessus, il s'agit de 0 minute, 8 secondes et 562 000 microsecondes.


2
Référence: docs.python.org/library/datetime.html#datetime-objects . Lisez "opérations prises en charge".
S.Lott

@SilentGhost, Comment obtenir des heures, des minuits, des secondes
Mulagala

1
@markcial: deloreandénaturation datetime, pytzapproche par exemple, l'exemple de code de démarrage pourrait être écrit comme d = datetime.now(timezone(EST))(une ligne lisible au lieu de cinq).
jfs

1
Remarque: vous devez être prudent lorsque vous effectuez des calculs de date / heure sur des objets datetime naïfs qui représentent l'heure locale. Il peut échouer, par exemple, autour des transitions DST. Voir le lien avec plus de détails dans ma réponse
jfs

Comment c est-il utilisé pour trouver la différence en termes de jours, min, sec?
Zeeshan Mahmood

152

Nouveau dans Python 2.7 est la timedeltaméthode d'instance .total_seconds(). D'après les documents Python, cela équivaut à (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6.

Référence: 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

Utilisation de l'exemple 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

Durée en années

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

Durée en jours

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

Durée en heures

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

Durée en minutes

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

Durée en secondes

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

Durée en microsecondes

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

Durée totale entre les deux dates

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

ou simplement:

>>> print(now - then)

Edit 2019 Puisque cette réponse a gagné du terrain, je vais ajouter une fonction, ce qui pourrait simplifier l'utilisation pour certains

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
Je ne sais pas pourquoi personne ne vous a remercié. Merci beaucoup pour une réponse aussi précise. @Attaque
Amandeep Singh Sawhney

J'ai une erreur TypeError: 'float' object is not subscriptablelors de l'utilisation pour: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
C'est parce que je ne peux pas compter le nombre de secondes dans une année :) 365 * 24 * 60 * 60 = 31536000 et non 31556926. J'ai mis à jour la réponse et les fonctions et cela devrait fonctionner maintenant.
Attaque

1
Ce devrait être la réponse acceptée.
saran3h

28

Il suffit de soustraire l'un de l'autre. Vous obtenez un timedeltaobjet avec la différence.

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

Vous pouvez convertir dd.days, dd.secondset dd.microsecondsen minutes.


Quels sont ces paramètres? Les commentaires seraient bien
TheRealChx101

22

Si a, bsont des objets datetime alors pour trouver la différence de temps entre eux en Python 3:

from datetime import timedelta

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

Sur les versions antérieures de Python:

time_difference_in_minutes = time_difference.total_seconds() / 60

Si a, bsont des objets datetime naïfs tels que retournés par datetime.now()alors le résultat peut être faux si les objets représentent l'heure locale avec différents décalages UTC, par exemple, autour des transitions DST ou pour des dates passées / futures. Plus de détails: recherchez si 24 heures se sont écoulées entre les heures - Python .

Pour obtenir des résultats fiables, utilisez des objets temps UTC ou datetime sensibles au fuseau horaire.


17

Utilisez 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
Cela devrait être mis dans le module datetime. Je n'arrive pas à comprendre pourquoi il n'utilisait que des jours, des secondes et des millis ...
paulochf

Cela ne répond pas à la question concernant les objets datetime.
elec3647

10

Voici comment j'obtiens le nombre d'heures qui se sont écoulées entre deux objets datetime.datetime:

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

9
Cela ne fonctionnera pas tout à fait: timedelta.secondsne donne que le nombre de secondes stockées explicitement - ce que la documentation garantit totalisera moins d'une journée. Vous voulez (after - before).total_seconds(), ce qui donne le nombre de secondes qui s'étendent sur tout le delta.
lvc

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

@lvc Mon ancien code a en fait été écrit de cette façon, et je pensais être intelligent et le "réparer". Merci pour la correction.
Tony

@JFSebastian Merci pour cela, j'ai oublié l'opérateur //. Et j'aime mieux la syntaxe py3, mais j'utilise 2.7.
Tony

9

Pour trouver simplement le nombre de jours: timedelta a un attribut «jours». Vous pouvez simplement l'interroger.

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

J'ai pensé qu'il pourrait être utile de mentionner également le formatage en ce qui concerne timedelta. strptime () analyse une chaîne représentant une heure selon un format.

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)

Cela produira: 0: 05: 00.518000


3

J'utilise quelque chose comme ça:

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
vous obtenez des horaires parfaitement corrects, pourquoi les recopiez-vous? c'est 75% de votre code qui peut être exprimé parreturn t1-t2
Patrick Artner

2

c'est pour trouver la différence entre l'heure actuelle et 9h30

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

1

C'est mon approche en utilisant 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()attend l'heure locale comme entrée. L'heure locale peut être ambiguë et mktime()peut renvoyer une mauvaise réponse dans ce cas. Utilisez à la a - bplace (a, b - objets datetime) . mktime()est inutile et c'est parfois faux. Ne l'utilisez pas dans ce cas.
jfs

@AnneTheAgile, corrigé, ma faute à l'importation. Testé sur Python 2.7.12
Eduardo

1

De différentes manières pour obtenir la différence entre la date;

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)

Obtenez donc la sortie en min.

Merci


1

J'ai utilisé les différences de temps pour les tests d'intégration continue pour vérifier et améliorer mes fonctions. Voici un code simple si quelqu'un en a besoin

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

En utilisant:

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

et j'ai quelque chose comme ça dans la sortie du journal

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

0

Sur la base d'une excellente réponse @Attaque , je propose une version simplifiée plus courte du calculateur de différence datetime:

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]

Je l'ai changé pour éviter de déclarer des fonctions répétitives, supprimé le joli intervalle d'impression par défaut et ajouté la prise en charge des millisecondes, des semaines et des mois ISO (à l'esprit, les mois sont juste approximatifs, en supposant que chaque mois est égal à 365/12).

Ce qui produit:

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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.