Datumsrechner

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
ASCII158
User
Beiträge: 80
Registriert: Samstag 28. September 2002, 15:40
Wohnort: München

Hallo Leute,

ich suche nach einer Funktion, die mir nach Eingabe zweier Daten (z.B. 4.5.2002 17:45 und 2.6.2003 19:07) Die Differenz ausgibt (in diesem Fall
29.0.1. 1:22) Gibt es da was fertiges oder hat einer von euch schonmal sowas gemacht?

Wenn nicht muss ich das wohl selber machen... ;-)
mfg,

10011110
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

hmm... Frage: ist es sinnvoll eine Datumsdifferenz mit Monaten anzugeben? Eher doch mit Tagen und Jahren. Das ließe sich dann auch relativ leicht selber machen. Zuerst die Differenz der Tage ausrechnen, dann die Zeitdifferenz (hh:mm:ss). Wenn die Negativ ist, ziehst du einfach nen tag ab und rechnest die negative in normale Zeit um (lässt sich ja leicht machen, wenn man vor dem ausrechnen der Differenz in sekunden umrechnet). Das mit dem Differenzen der Tage rechnest du dann einfach grob in Monate und Jahre auf, oder lässt es.

Nen Codeschnippel für die Tagedifferenzen hab ich noch, als wir vor einiger Zeit in der Schule der Gregorianischen Kalendar hatten... ist ein wenig lang, funktioniert aber ;)

Code: Alles auswählen

def schaltjahr (jahr):
    if (jahr % 400 == 0) or ((jahr % 4 == 0) and (jahr % 100 != 0)) :
        return 1
    else:
        return 0
def tagemonat(jahr,monat):
    if monat == 2:
        return schaltjahr(jahr) + 28
    elif (monat == 4) or (monat == 6) or (monat == 9) or (monat == 11):
        return 30
    else:
        return 31
def davor (j1,m1,t1,j2,m2,t2):
    if j1 < j2:
        return 1
    elif j1 > j2:
        return 0
    elif m1 < m2:
        return 1
    elif m1 > m2:
        return 0
    elif t1 < t2:
        return 1
    else:
        return 0
def nachfolger(jahr,monat,tag):
    j = jahr; m = monat; t = tag
    t = t + 1
    if (t > tagemonat(jahr,monat)):
        t = 1
        m = m + 1
    if (m > 12):
        m = 1
        j = j + 1
    return j,m,t

def tagedifferenz(j1,m1,t1,j2,m2,t2):
    if not davor(j1,m1,t1,j2,m2,t2):
        (j1,m1,t1,j2,m2,t2)=(j2,m2,t2,j1,m1,t1)
    diff=0L
    while davor(j1,m1,t1,j2,m2,t2):
        (j1,m1,t1)=nachfolger(j1,m1,t1)
        diff=diff+1L
    return diff

print tagedifferenz(2003,5,31,2003,6,2)
rAiNm4n

wieso benutzt du nicht einfach das Modul time?
konkret würde das dann ungefähr so aussehen:

Code: Alles auswählen

import time
date1 = time.mktime((2002, 5, 4, 17, 45, 0, 0, 0, 0))
date2 = time.mktime((2003, 6, 2, 19, 7, 0, 0, 0, 0))
erg = time.strftime("%d.%m.%Y %H:%M", time.gmtime(date2 - date1))
>>> print erg
'30.01.1971 01:22' (Die Jahreszahl ist hier eher uninterressant...)

Ich hoffe ich konnte dir helfen...
cu

Chris
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

weil die Monats- und Tageszahl wohl in den seltensten Fällen stimmen dürfte. schließlich wird immer von 1.1.1970 ausgegangen. wenn du eine Differenz bildest, wird angenommen, du würdest einen Zeitpunkt beschreiben, der damals war. Auch dürften die Schaltjahre, die eventuell dazwischen zu beachten sind, rausfallen. Probiers einfach mal mit meinen Angaben ;)

und: man füttert mktime nur mit localtimes und für das zurückrechnen nimmt man dann auch localtime... hab ich Erfahrungen mit gemacht und mich gewundert, warum ich 2 Studen Zeitunterschied hatte...
rAiNm4n

Die Tagesdifferenz, die dein Skript liefert, kannst du aber trotzdem mit dem time-Modul rausbekommen:

Code: Alles auswählen

import time
secs1 = time.mktime((2002, 5, 4, 17, 45, 0, 0, 0, 0))
secs2 = time.mktime((2003, 6, 2, 19, 7, 0, 0, 0, 0))
diff = secs2 - secs1
days = diff / 86400    # diff / 60 / 60 / 24
>>> print days
394.05694444444447
Liefert das selbe Ergebnis, wie dein Skript.

cu
Chris
ASCII158
User
Beiträge: 80
Registriert: Samstag 28. September 2002, 15:40
Wohnort: München

Ich hab mir selber nochn paar Gedanken gemacht:

Code: Alles auswählen

def zeitdifferenz(eins, zwei):
	import calendar
	jahr1, monat1, tag1, stunde1, minute1= eins
	jahr2, monat2, tag2, stunde2, minute2= zwei
	
	for jahr in range(jahr1):
		minute1+=525600+1440*calendar.isleap(jahr)
	
	for monat in range(1,monat1):
		gesamt=calendar.monthcalendar(jahr1, monat)
		tagzahl=0
		for woche in gesamt:
			for tag in woche:
				if tag != 0: tagzahl+=1
		
		minute1+=tagzahl*1440
		
	for tag in range(tag1):
		minute1+=1440
		
	for stunde in range(stunde1):
		minute1+=60
	
	for jahr in range(jahr2):
		minute2+=525600+1440*calendar.isleap(jahr)
	
	for monat in range(1,monat2):
		gesamt=calendar.monthcalendar(jahr2, monat)
		tagzahl=0
		for woche in gesamt:
			for tag in woche:
				if tag != 0: tagzahl+=1
		
		minute2+=tagzahl*1440
		
	for tag in range(tag2):
		minute2+=1440
		
	for stunde in range(stunde2):
		minute2+=60
		
	diff= abs(minute1 - minute2)
	
	jahrn=diff//525600
  	diff -= jahrn*525600
	monatn=diff//43200
	diff -= monatn*43200
	tagn=diff//1440
	diff -= tagn*1440
	stunden=diff//60
	diff -= stunden*60
	minuten=diff
		
	
	return (jahrn, monatn, tagn, stunden, minuten)
	
if __name__=='__main__':
	import time
	print (1986,1,22,16,30)
	print time.gmtime()[:5]
	print zeitdifferenz((1986,1,22,16,30),time.localtime()[:5])
Gibt korrekt:
(1986, 1, 22, 16, 3
(2003, 6, 4, 16, 49
(0, 7, 21, 21, 41)
[/quote][/code]
mfg,

10011110
rAiNm4n
User
Beiträge: 19
Registriert: Mittwoch 4. Juni 2003, 11:30
Wohnort: Berlin

Eine Frage:
Wieso beträgt bei deinem Beispiel die Zeitdifferenz zwischen 22.1.1986 16:30 und 4.6.2003 16:49 nur 7 Monate, 21 Tage, 21 Stunden und 21 Minuten? Also entweder hast du nen Fehler gemacht oder ich blick da nich durch... :roll:
cu

Chris
ASCII158
User
Beiträge: 80
Registriert: Samstag 28. September 2002, 15:40
Wohnort: München

Äh, das weiss ich jatzt auch nicht wie mir das passiert ist, die Ausgabe ist:
(1986, 1, 22, 16, 30)
(2003, 6, 5, 12, 32)
(17, 4, 17, 22, 2)
mfg,

10011110
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

ASCII158 hat geschrieben:
(1986, 1, 22, 16, 30)
(2003, 6, 5, 12, 32)
(17, 4, 17, 22, 2)
Ich komme händisch auf (17, 4, 13, 20, 2)

Code: Alles auswählen

30 + 2             -> 32      kein Übertrag
16Uhr + 20 Std     -> 12Uhr   nächster Tag   Übertrag!
22. Jan  + 13 Tage -> 6. eines folgenden Monats            
Die 13 setzt sich zusammen aus:
       22. Jan (ausschließlich) bis 31 Jan. sind   9 Tage
       1. Juni bis 5. Juni sind                    5 Tage
       wegen Start am Nachmittag und Ende Mittags -1 Tage
       Summe                                      13 Tage
Jan
Voges
User
Beiträge: 564
Registriert: Dienstag 6. August 2002, 14:52
Wohnort: Region Hannover

Hallo nochmal!
Ich werf' mal mein Skript in die Runde

Code: Alles auswählen

from calendar import monthrange

def datediff(von,bis):
    (jVon,mVon,tVon,stdVon,minVon) = [int(i) for i in von.split()]
    (jBis,mBis,tBis,stdBis,minBis) = [int(i) for i in bis.split()]

    minVon += stdVon*60
    minBis += stdBis*60

    anzMin = minBis - minVon
    if minVon > minBis:
        anzMin += 1440
        tBis -= 1

    anzStd = anzMin // 60
    anzMin = anzMin % 60

    if tVon > tBis:
        anzTage = monthrange(jVon,mVon)[1] - tVon
        anzTage += tBis
    else:
        anzTage = (tBis - tVon)
    
    anzMonate = 0
    if tVon > tBis:
        anzMonate -= 1
    
    anzJahre = jBis - jVon
    if mVon > mBis+anzMonate:
        anzJahre -= 1
        anzMonate += 12 - mVon + mBis
    else:
        anzMonate += mBis - mVon

    return "%d %d %d  %d %d" % (anzJahre,anzMonate,anzTage,anzStd,anzMin)

print datediff("2002 1 5    0 00","2003 1 4   0 00")
print datediff("2002 2 5    0 00","2003 2 4   0 00")
print datediff("2002 12 31 23 00","2003 1 1   1 00")
print datediff("2004 4 4    4 44","2005 4 4   4 43")
print datediff("1986 1 22  16 30","2003 6 5  12 32")
Ausgabe:
0 11 30 0 0
0 11 27 0 0
0 0 0 2 0
0 11 29 23 59
17 4 13 20 2

Sehr sinnvoll erscheint mir die gleichzeitige Angabe von Monaten und Tagen als Differenzen aber wirklich nicht (siehe die ersten beiden Beispiele).
Jan
QuatschVirus
User
Beiträge: 1
Registriert: Montag 8. Februar 2021, 08:59

rAiNm4n hat geschrieben: Mittwoch 4. Juni 2003, 11:26 Die Tagesdifferenz, die dein Skript liefert, kannst du aber trotzdem mit dem time-Modul rausbekommen:

Code: Alles auswählen

import time
secs1 = time.mktime((2002, 5, 4, 17, 45, 0, 0, 0, 0))
secs2 = time.mktime((2003, 6, 2, 19, 7, 0, 0, 0, 0))
diff = secs2 - secs1
days = diff / 86400    # diff / 60 / 60 / 24
>>> print days
394.05694444444447
Liefert das selbe Ergebnis, wie dein Skript.

cu
Chris
Sorry, das ich das wieder aufgreife, aber dieses Skribt gibt bei mir einen Tag zu viel aus. Vielleicht übersehe ich auch etwas...

Code: Alles auswählen

import time
secs1 = time.mktime((2020, 2, 8, 9, 10, 0, 0, 0, 0))
secs2 = time.mktime((2021, 2, 8, 9, 10, 0, 0, 0, 0))
diff = secs2 - secs1
days = diff / 86400
print(days)
366.0        #Da kein Schaltjahr war, müsste hier 365.0 rauskommen
Weiß jemand, warum das passieren könnte?

Danke,
QuatschVirus
Benutzeravatar
sparrow
User
Beiträge: 4164
Registriert: Freitag 17. April 2009, 10:28

Schaltjahre haben 366 Tage - wie du bereits richtig festgestellt hast.

Und ich würde datetime verwenden. Vielleicht gab es das 2003 noch nicht.

Code: Alles auswählen

from datetime import datetime as DateTime

start = DateTime(2020, 2, 8, 9, 10)
stop = DateTime(2021, 2, 8, 9, 10)

print(stop-start)
Benutzeravatar
DeaD_EyE
User
Beiträge: 1012
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

rAiNm4n hat geschrieben: Mittwoch 4. Juni 2003, 19:51 Wieso beträgt bei deinem Beispiel die Zeitdifferenz zwischen 22.1.1986 16:30 und 4.6.2003 16:49 nur 7 Monate, 21 Tage, 21 Stunden und 21 Minuten? Also entweder hast du nen Fehler gemacht oder ich blick da nich durch... :roll:
Mir stellt sich da eine ganz andere Frage.

Wie soll man Jahre und Monate einer Zeitdifferenz berücksichtigen? 30 Tage pro Monat, 360 Tage pro Jahr?

Ich verwende oft timedelta, um Zeitdifferenzen in kleine Einheiten zu unterteilen (Tage, Stunden, Minuten, Sekunden).


Beispiel mit dem Code von Sparrow:

Code: Alles auswählen

from datetime import datetime as DateTime
from datetime import timedelta as TimeDelta

start = DateTime(2020, 2, 8, 9, 10)
stop = DateTime(2021, 2, 8, 9, 10)

zeitdifferenz = stop - start

stunden = zeitdifferenz  / TimeDelta(hours=1)
print("Stunden:", stunden)


# Jahre, Monate, Tage, Stunden, Minuten, Sekunden
# zeitdifferenz in Tage

tage = zeitdifferenz  / TimeDelta(days=1)
jahre, tage = divmod(tage, 360) # 360 Tage pro Jahr
monate, tage = divmod(tage, 30) # 30 Tage pro Monat
stunden, tage = divmod(tage, 24)
minuten, stunden = divmod(stunden, 60)
sekunden, minuten = divmod(minuten, 60)

jahre = int(jahre)
monate = int(monate)
tage = int(tage)
stunden = int(stunden)
minuten = int(minuten)

print(f"{jahre} Jahr(e) {monate} Monat(e) {tage} Tage {stunden} Stunden {minuten} Minuten {sekunden} Sekunden")
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Sirius3
User
Beiträge: 17711
Registriert: Sonntag 21. Oktober 2012, 17:20

TimeDelta hat drei Attribute, days, seconds und microseconds. Das sind jeweils Integers. Ansonsten würde man auch die Tage gleich in ein int umwandeln und spart sich die ganzen int-Aufrufe im Nachgang. Der Code für minuten, sekunden und stunden funktioniert eh nicht.
Damit vereinfacht sich der Code zu

Code: Alles auswählen

# Jahre, Monate, Tage, Stunden, Minuten, Sekunden
# zeitdifferenz in Tage

tage = zeitdifferenz.days
jahre, tage = divmod(tage, 360) # 360 Tage pro Jahr
monate, tage = divmod(tage, 30) # 30 Tage pro Monat

sekunden = zeitdifferenz.seconds
minuten, sekunden = divmod(sekunden, 60)
stunden, minuten = divmod(minuten, 60)
Benutzeravatar
DeaD_EyE
User
Beiträge: 1012
Registriert: Sonntag 19. September 2010, 13:45
Wohnort: Hagen
Kontaktdaten:

So gehts natürlich einfacher.
sourceserver.info - sourceserver.info/wiki/ - ausgestorbener Support für HL2-Server
Antworten