Wie finde ich den Zeitunterschied zwischen zwei Datums- / Uhrzeitobjekten in Python?

354

Wie erkenne ich den Zeitunterschied in Minuten zwischen zwei datetimeObjekten?

Hobhouse
quelle

Antworten:

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

Durch Subtrahieren der späteren Zeit vom ersten Mal difference = later_time - first_timewird ein Datum / Uhrzeit-Objekt erstellt, das nur die Differenz enthält. Im obigen Beispiel sind es 0 Minuten, 8 Sekunden und 562000 Mikrosekunden.

SilentGhost
quelle
2
Referenz: docs.python.org/library/datetime.html#datetime-objects . Lesen Sie "Unterstützte Operationen".
S.Lott
@ SilentGhost, wie man mit Stunden, Minuten, Sekunden kommt
Mulagala
1
@markcial: deloreanfalsch dargestellt datetime, pytzAnsatz z. B. könnte das Codebeispiel für den Einstieg als d = datetime.now(timezone(EST))(eine lesbare Zeile anstelle von fünf) geschrieben werden.
JFS
1
Hinweis: Sie sollten vorsichtig sein, wenn Sie Datums- / Uhrzeit-Arithmetik für naive Datums- / Uhrzeitobjekte durchführen, die die Ortszeit darstellen. Dies kann beispielsweise bei Sommerzeitübergängen fehlschlagen. Siehe den Link mit mehr Details in meiner Antwort
jfs
Wie wird c verwendet, um Unterschiede in Tagen, Minuten und Sekunden zu ermitteln?
Zeeshan Mahmood
152

Neu bei Python 2.7 ist die timedeltaInstanzmethode .total_seconds(). In den Python-Dokumenten entspricht dies (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6.

Referenz: 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
quelle
107

Verwenden Sie das Datum / Uhrzeit-Beispiel

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

Dauer in Jahren

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

Dauer in Tagen

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

Dauer in Stunden

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

Dauer in Minuten

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

Dauer in Sekunden

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

Dauer in Mikrosekunden

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

Gesamtdauer zwischen den beiden Daten

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

oder einfach:

>>> print(now - then)

Edit 2019 Da diese Antwort an Bedeutung gewonnen hat, werde ich eine Funktion hinzufügen, die die Verwendung für einige vereinfachen könnte

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
quelle
7
Ich weiß nicht, warum sich niemand bei Ihnen bedankt hat. Vielen Dank für eine so präzise Antwort. @Attaque
Amandeep Singh Sawhney
Ich habe Fehler TypeError: 'float' object is not subscriptablebei der Verwendung für: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
Das liegt daran, dass ich die Anzahl der Sekunden in einem Jahr nicht zählen kann :) 365 * 24 * 60 * 60 = 31536000 und nicht 31556926. Ich habe die Antwort und die Funktionen aktualisiert und es sollte jetzt funktionieren.
Attaque
1
Dies sollte die akzeptierte Antwort sein.
Saran3h
28

Subtrahieren Sie einfach voneinander. Sie erhalten ein timedeltaObjekt mit dem Unterschied.

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

Sie können konvertieren dd.days, dd.secondsund dd.microsecondszu Minuten.

Vinay Sajip
quelle
Was sind diese Parameter? Kommentare wären nett
TheRealChx101
22

Wenn a, bsind Datum / Uhrzeit-Objekte, um den Zeitunterschied zwischen ihnen in Python 3 zu ermitteln:

from datetime import timedelta

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

Bei früheren Python-Versionen:

time_difference_in_minutes = time_difference.total_seconds() / 60

Wenn a, bsind naiv Datetime - Objekte wie durch zurück datetime.now()dann das Ergebnis falsch sein kann , wenn die Objekte Ortszeit mit unterschiedlichen UTC Offsets zB um DST Übergänge oder für vergangene / zukünftige Termine vertreten. Weitere Details: Finden Sie heraus, ob zwischen den Daten 24 Stunden vergangen sind - Python .

Verwenden Sie UTC-Zeit- oder zeitzonenbezogene Datums- / Uhrzeitobjekte, um zuverlässige Ergebnisse zu erhalten.

jfs
quelle
17

Verwenden Sie 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)
Abfall
quelle
1
Dies sollte in das Datum / Uhrzeit-Modul gestellt werden. Ich kann einfach nicht verstehen, warum es nur Tage, Sekunden und Millis verwendet hat ...
Paulochf
Dies beantwortet nicht die Frage zu Datetime-Objekten.
elec3647
10

So erhalte ich die Anzahl der Stunden, die zwischen zwei datetime.datetime-Objekten vergangen sind:

before = datetime.datetime.now()
after  = datetime.datetime.now()
hours  = math.floor(((after - before).seconds) / 3600)
Tony
quelle
9
Dies wird nicht ganz funktionieren: timedelta.secondsGibt nur die Anzahl der explizit gespeicherten Sekunden an - die Dokumentation garantiert weniger als einen Tag. Sie möchten (after - before).total_seconds(), was die Anzahl der Sekunden angibt, die das gesamte Delta umfassen.
lvc
1
(after - before).total_seconds() // 3600(Python 2.7) oder (after - before) // timedelta(seconds=3600)(Python 3)
jfs
@lvc Mein alter Code wurde tatsächlich so geschrieben, und ich dachte, ich wäre schlau und "repariere" ihn. Danke für die Korrektur.
Tony
@JFSebastian Danke dafür, ich habe den Operator // vergessen. Und ich mag die py3-Syntax besser, benutze aber 2.7.
Tony
9

Um nur die Anzahl der Tage zu ermitteln: timedelta hat das Attribut 'Tage'. Sie können das einfach abfragen.

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

Ich dachte nur, es könnte nützlich sein, die Formatierung auch in Bezug auf das Zeitdelta zu erwähnen. strptime () analysiert eine Zeichenfolge, die eine Zeit gemäß einem Format darstellt.

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)

Dies gibt Folgendes aus: 0: 05: 00.518000

Spatz
quelle
3

Ich benutze so etwas:

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
quelle
2
Sie erhalten vollkommen gute Datenzeiten. Warum kopieren Sie sie? Das sind 75% Ihres Codes können vonreturn t1-t2
Patrick Artner
2

Hiermit wird der Unterschied zwischen der aktuellen Zeit und 9.30 Uhr ermittelt

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

Dies ist mein Ansatz mit 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
quelle
mktime()erwartet Ortszeit als Eingabe. Die Ortszeit ist möglicherweise nicht eindeutig und gibt mktime()in diesem Fall möglicherweise eine falsche Antwort zurück. Verwenden Sie a - bstattdessen (a, b - datetime-Objekte) . mktime()ist unnötig und es ist manchmal falsch. Verwenden Sie es in diesem Fall nicht.
JFS
@AnneTheAgile, behoben, mein Fehler beim Import. Getestet auf Python 2.7.12
Eduardo
1

Auf andere Weise, um einen Unterschied zwischen dem Datum zu erhalten;

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)

Also Ausgabe in min.

Vielen Dank

Anurag Pandey
quelle
1

Ich habe Zeitunterschiede für kontinuierliche Integrationstests verwendet, um meine Funktionen zu überprüfen und zu verbessern. Hier ist einfacher Code, wenn jemand ihn braucht

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

Verwenden von:

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

und ich habe so etwas in der Protokollausgabe

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

Basierend auf der großartigen Antwort von @Attaque schlage ich eine kürzere vereinfachte Version des Datums- / Zeitdifferenzrechners vor:

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]

Ich habe es geändert, um zu vermeiden, dass sich wiederholende Funktionen deklariert werden, das hübsche Standardintervall für den Druck entfernt und die Unterstützung für Millisekunden, Wochen und ISO-Monate hinzugefügt (die Monate sind nur ungefähr, basierend auf der Annahme, dass jeder Monat gleich ist 365/12).

Welches produziert:

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
quelle