pdvm_datetime.py - Teil 1
Aus Gründen der Größe der Seiten werden hier alle internen Funktionalitäten der pdvm_datetime dargestellt und beschreiben. Die Pfeile nach Oben gehen auf den Beginn der Originalseite. Von dort sind alle Abschnitte erreichbar. Die Pfeile nach links gehen auf die Basisseite der pdvm_datetime.
__pdvmdatime()
Beschreibung
# --------------------------------------------------------------------
# __pdvmdatime(jahr,monat,tag,stunde,minute,sekunde,microsekunde)
# Eigenschaften der Klasse werden gesetzt, bzw. berechnet
# --------------------------------------------------------------------
def __pdvmdatime(self,year=0,month=0,day=0,hour=0,minute=0,second=0,microsecond=0):
self.year = year # Jahr
self.month = month # Monat
self.day = day # Tag im Monat
self.hour = hour # Stunde im Tag
self.minute = minute # Minute in der Stunde
self.second = second # Sekunde in der Minute
self.microsecond = microsecond # Microsekunde
self.pdvmdatetime = self.__convertToPdvmDateTime(year,month,day,hour,minute,second,microsecond)
self.pdvmtime = float(str(self.pdvmdatetime)[str(self.pdvmdatetime).find("."):])
self.__svalue()
return self.pdvmdatetime
__pdvmdatime - Beschreibung
Source
Über die Eingabewerte von Jahr, Monat, Tag, Stunde, Minute, Sekunde, Microsekunde werden die Eigenschaften im Objekt gesetzt. Werden nicht alle Werte mitgegeben, so werden die fehlenden Werte mit 0 angenommen.
Ablauf
- die Eigenschaften für die einzelnen Datum- und Zeitwerte werden gesetzt.
- über __convertToTdvmDateTime wird die Eigenschaft pdvmdatetime gesetzt
- Die Eigenschaft pdvmtime wird einfach durch das Abtrennen des Datums gesetzt
- interne Eigenschaften werden über __value() gesetzt. eigene Funktion, da diese zwei mal verwendet wird.
- pdvmdatetime wird zurückgegeben
Es ist die grundlegende Funktion zum Setzen eines Timestamp im Objekt.
__pdvmDateInDateSplit()
Beschreibung
# --------------------------------------------------------------------
# PdvmdateTime zerlegen
# --------------------------------------------------------------------
def __pdvmDateInDateSplit(self):
ret = self.__splitPdvmDate(self.pdvmdatetime)
self.year = ret[0]
self.month = ret[1]
self.day = ret[2]
self.pdvmtime = float(str(self.pdvmdatetime)[str(self.pdvmdatetime).find("."):])
cfntmsec = int(self.pdvmtime * self._tag) # Microsekunden des Tages
xistd = round(cfntmsec / self._stunde,4) # Stunden mit Rest
self.hour = int(xistd) # Stunden des Tages
reststd = cfntmsec % self._stunde # Rest Microsekunden
ximin = round(reststd / self._minute,4) # Minuten mit Rest
self.minute = int(ximin) # Minuten der Stunde
restmin = reststd % self._minute # Rest Microsekunden
xisec = round(restmin / self._sekunde,4)# Sekunden mit Rest
self.second = int(xisec) # Sekunden der Minute
if self.second==60: # Korrektur Ungenauigkeit
self.second = 0 # bei Ursprungswert 0
restsec = restmin % self._sekunde # Rest Microsekunden
self.microsecond = int(restsec) # Microsekunden der Sekunde
if self.microsecond > 999000: # Korrektur Ungenauigkeit
self.microsecond = 0 # bei Ursprungswert 0
self.__svalue()
return self.dtt
__pdvmDateInDateSplit() - Beschreibung
Source
Mit dieser Funktionalität wird die Eigenschaft pdvmdatetime in die Einzelteile des Datums und der Zeit zerlegt.
Ablauf
- Mit __splitPdvmDate() wird das Datum in die Variable ret zerlegt.
- die Eigenschaften year, month und day werden über ret gesetzt.
- die Eigenschaft pdvmtime wird über den Nachkommateil von pdvmdatetime gesetzt.
- die Microsekunden (für den Tag) aus pdvmtime werden errechnet (cfntmsec)
- die Stunden (mit Rest - gerundet auf 4 Nachkommastellen) werden errechnet (xistd)
- die Eigenschaft hour wird mit dem Integer aus xistd gesetzt.
- der Rest Microsekunden (ohne Stunden) wird errechnet (reststd)
- die Minuten (mit Rest - gerundet auf 4 Nachkommastellen) werden errechnet (ximin)
- die Eigenschaft minute wird mit dem Integer aus ximin gesetzt.
- der Rest Microsekunden (ohne Stunden, Minuten ) wird errechnet (restmin)
- die Sekunden (mit Rest - gerundet auf 4 Nachkommastellen) werden errechnet (xisec)
- die Eigenschaft second wird mit dem Integer aus xisec gesetzt.
- Wegen der Ungenauigkeit bei float und vielen Nachkommastellen werden 60 Sekunden auf 0 gesetzt
- der Rest Microsekunden (ohne Stunden, Minuten, Sekunden ) wird errechnet (restsec)
- die Eigenschaft microsecond wird mit dem Integer aus restsec gesetzt.
- Wegen der Ungenauigkeit bei float und vielen Nachkommastellen werden mehr als 999000 Microsekunden auf 0 gesetzt.
- über __svalue() werden die restlichen Eigenschaften gesetzt
- die Eigenschaft dtt (Tuple mit Jahr, Monat, Tag, Stunden, Minuten, Sekunden, Microsekunden) wird zurückgegeben.
Es ist die grundlegende Funktion zum Setzen der Eigenschaften im Objekt aus einem pdvmdatetime
__svalue()
Beschreibung
# --------------------------------------------------------------------
# Objektwerte
# --------------------------------------------------------------------
def __svalue(self):
# Tuple Datum / Zeiten setzen
ret = []
ret.append(self.year)
ret.append(self.month)
ret.append(self.day)
self.dd = tuple(ret)
ret1 = []
ret1.append(self.hour)
ret1.append(self.minute)
ret1.append(self.second)
ret1.append(self.microsecond)
self.dt = tuple(ret1)
self.dtt = tuple(ret)+tuple(ret1)
self.period = (self.year * 100) + self.month
return True
__svalue() - Beschreibung
Source
Die Tuple für Date (Eigenschaft dd), Time (Eigenschaft dt) und DateTime (Eigenschaft dtt) werden gesetzt. Dazu die Eigenschaft period.
Am Ende wird True zurückgegeben.
__lYearFYear()
Beschreibung
# --------------------------------------------------------------------
# Schaltjahr ermitteln
# --------------------------------------------------------------------
def __lYearFYear(self,year):
s = 0
if year != 0: # 0 % x immer 0
r = year % 4 # jedes 4 Jahr --> Schaltjahr
if r==0:
r = year % 100 # alle 100 Jahre --> keine Schaltjahr
if r==0:
r = year % 400 # alle 400 Jahre wieder --> Schaltjahr
if r==0:
s = 1 # Schaltjahr
else:
s = 0 # kein Schaltjahr
else:
s = 1 # Schaltjahr
else:
s = 0 # kein Schaltjahr
return s # Rückgabe Ergebnis
__lYearFYear() - Beschreibung
Source
Mit dieser Funktionalität wird ermittelt ob ein Jahr ein Schaltjahr ist oder nicht. Die Entscheidungen hier werden getroffen indem man den Rest aus einer Division ermittelt. Hierbei sind folgende Regeln zu beachten:
- Jede Jahreszahl die sich durch 4 teilen lässt ist grundsätzlich ein Scchaltjahr
- dieses trifft jedoch dann nicht zu, wenn sich die Jahrszahl durch 100 teilen lässt.
- die Ausnahme von der Ausnahme ist dann gegeben, wenn sich die Jahreszahl druch 400 teilen lässt.
Das typische Beispiel aus neuer Zeit ist das Jahr 2000.
- 2000 ist durch 4 teilbar --> Schaltjahr
- 2000 ist durch 100 teilbar --> doch kein Schaltjahr
- 2000 ist durch 400 teilbar --> also Ausnahme von der Ausnahme 2000 ist ein Schaltjahr.
Der Rückgabewert der Funktionalität ist 0 --> kein Schaltjahr und 1 --> Schaltjahr
__checkDate()
Beschreibung
# -------------------------------------------------------------------------------------
# Datum prüfen
# ---------------------------------------------------------------------------------
# Hinweis: Alle Jahre, auch die vor Chr. (negatives Datum) werden nach den Regeln des
# -------- gregorianischen Kalenders verarbeitet. Daher macht eine Prüfung auf das
# Jahr keinen Sinn und wurde weggelassen.
# ---------------------------------------------------------------------------------
# -------------------------------------------------------------------------------------
def __checkDate(self,year,month,day):
ok = False
# Check Month
if int(month) > 0 and int(month) < 13:
ok = True
else:
printMessage("error",pdvmObjekt,"PDT_010",["def: __checkDate","Monat: " + str(month)], self.language)
# Check Day
# Der Tag wird genau geprüft, dies bedeutet, dass beim Februar das Schaltjahr
# geprüft werden muss.
if ok:
md = monthdays[int(month)+1][int(self.__lYearFYear(int(year)))]-monthdays[int(month)][int(self.__lYearFYear(int(year)))]
if int(day)>0 and int(day)<md+1:
ok = True
else:
ok = False
printMessage("error",pdvmObjekt,"PDT_011",["def: __checkDate", "Tag: " + str(day),"Monat: " + str(month),"Jahr: " + str(year)], self.language)
return ok
__checkDate - Beschreibung
Source
Mit dieser Funktionalität werden die Tage und Monate zum angegebenen Jahr geprüft. Da wir hier alle Jahre nach den Regeln des gregorianischen Kalenders verarbeiten sind alle Jahre zugelassen. Eine Prüfung des Jahres findet hier daher nicht statt.
Ablauf
- Der Monat muss größer 0 und kleiner 13 sein. Ist dieses nicht der Fall wird die Fehlermeldung PTD_010 ausgegeben.
- Beim Tag wird mit Hilfe des Inhalts von monthdays (Initalisierung vor der Klasse) die maximal zulässige Tageszahl zum Monat ermittelt. Der Tag muss kleiner/gleich dieser Tageszahl sein und mindestens die Größe von 1. Anderenfalls wird die Fehlermeldung PTD_011 ausgegeben.
Zurückgegeben wird hier True und False.
Beschreibung
# --------------------------------------------------------------------
# Date (ohne Trenner) nach Spezifikation in Jahr / Monat / Tag konvertieren
# --------------------------------------------------------------------
def __calcDateToForm(self, datein, dlen):
year = 0
month = 0
day = 0
# Jahr ermitteln
ayear2 = self.GetAYear2
ajh2 = self.GetAYearH2
if dlen == 8:
year = datein[posYear[dlen][self.dateYearPos][0]:posYear[dlen][self.dateYearPos][1]]
elif dlen == 6:
year = datein[posYear[dlen][self.dateYearPos][0]:posYear[dlen][self.dateYearPos][1]]
if (int(ayear2)+5) < int(year):
year = str(((int(ajh2) - 1)*100)+int(year))
else:
year = str((int(ajh2)*100)+int(year))
elif dlen == 4:
year = self.GetAYear
else:
# darf hier nie ankommen / Sicherheit
printMessage("error",pdvmObjekt,"PDT_012",["def: __calcDateToForm","Länge: " + str(dlen)], self.language)
# Monat ermitteln
month = datein[posMonth[dlen][self.dateMonthPos][0]:posMonth[dlen][self.dateMonthPos][1]]
# Tag ermitteln
day = datein[posDay[dlen][self.dateMonthPos][0]:posDay[dlen][self.dateMonthPos][1]]
return year, month, day
Source
Hier wird ein Datumstring aus der Eingabe bzw. Analyse übergeben, dazu aus Gründen der Sicherheit auch die Länge mit der gearbeitet wird. Der String darf auch keine Trennzeichen enthalten.
Ablauf:
- Die Ausgabevariablen year, month, day werden initalisiert.
- Das aktuelle Jahr(2 Stellen) und Jahrhundert(2 Stellen) werden ermittelt.
- Mit Hilfe von posYear und self.dateYearPos wird das Jahr(year) aus dem String ermittelt.
- Hat das Jahr nur zwei Stellen wird für die nächsten 5 Jahre, das aktuelle Jahrundert und sonst das vorherige Jahrhundert hinzugefügt.
- Mit Hilfe von posMonth und self.dateMonthPos wird der Monat(month) aus dem String ermittelt.
- Mit Hilfe von posDay und self.dateDayPos wird der Tag(day) aus dem String ermittelt.
Rückgabe: (Jahr, Monat, Tag)
__upDown()
Beschreibung
# --------------------------------------------------------------------
# __upDown --- Para 1 --> auf Max // Para 2 --> Überlauf // Max
# --------------------------------------------------------------------
def __upDown(self,s,z,m):
while s > m:
s -= m
z += 1
while s < 1:
s += m
z -= 1
return (s,z)
__upDown() - Beschreibung
Source
Hiermit wird ein Überlauf bestimmt. Als Parameter werden übergeben (Zahl, Eingabewert, Maximal). Zurück gegeben werden die korrigierte Zahl und Eingabewert.
Beispiel bei Überlauf von Monaten:
__upDown(2019, 16, 12) --> also der Monat 16 im Jahr 2019 (ein Jahr hat aber max. 12 Monate.
Rüclgabe (2020,4)
umgekehrt:
__upDown(2019, -2, 12) -- also der Monat -2 im Jahr 2019
Rückgabe (2018,10)
__splitPdvmDate()
Beschreibung
# --------------------------------------------------------------------
# __splitPdvmDate PdvmDate wird in year,month,day zerlegt
# --------------------------------------------------------------------
def __splitPdvmDate(self,pdvmdate):
if pdvmdate > 1000:
yday = int(pdvmdate % 1000) # Tage im Jahr
year = int((pdvmdate - yday) / 1000) # Jahr
s = self.__lYearFYear(year) # Schaltjahr
ret = 0
for i in range(13,-1,-1):
if int(yday) < monthdays[i][s]+1:
pass
else:
if ret==0:
ret = i
mfndays_e = monthdays[i][s]
break
month = ret # Monat
day = int(yday - mfndays_e) # Tag
else:
year = 0
month = 0
day = 0
return (year,month,day)
__splitPdvmDate - Beschreibung
Source
Das PdvmDate wird in Jahr, Monat, Tag zerlegt.
Ablauf:
- Der Rest aus dem Teiler von 1000 ergeben die Tage im Jahr
- Datum - den Tagen geteilt durch 1000 ergibt das Jahr
- aus dem Jahr wird das Schaltjahr bestimmt
- über monthdays wird in einer Schleife der Monat ermittelt
- Damit kann auch der Tag des Monats errechnet werden
Rückgabe: (Jahr, Monat, Tag)
__splitPdvmDateTime()
Beschreibung
# --------------------------------------------------------------------
# __splitPdvmDateTime PdvmdateTime (Differenz) wird in alle Teile zerlegen
# --------------------------------------------------------------------
def __splitPdvmDateTime(self, pdvmdatetime):
ret = self.__splitPdvmDate(pdvmdatetime)
year = ret[0]
month = ret[1]
day = ret[2]
pdvmtime = float(str(pdvmdatetime)[str(pdvmdatetime).find("."):])
cfntmsec = int(pdvmtime * self._tag) # Microsekunden des Tages
xistd = round(cfntmsec / self._stunde,4) # Stunden mit Rest
hour = int(xistd) # Stunden des Tages
reststd = cfntmsec % self._stunde # Rest Microsekunden
ximin = round(reststd / self._minute,4) # Minuten mit Rest
minute = int(ximin) # Minuten der Stunde
restmin = reststd % self._minute # Rest Microsekunden
xisec = round(restmin / self._sekunde,4) # Sekunden mit Rest
second = int(xisec) # Sekunden der Minute
if self.second==60: # Korrektur Ungenauigkeit
self.second = 0 # bei Ursprungswert 0
restsec = restmin % self._sekunde # Rest Microsekunden
microsecond = int(restsec) # Microsekunden der Sekunde
if microsecond > 999000: # Korrektur Ungenauigkeit
microsecond = 0 # bei Ursprungswert 0
return (year,month,day,hour,minute,second)
__splitPdvmDateTime() - Beschreibung
Source
Diese Funktionalität ist fast identisch mit "__pdvmDateInDateSplit()" mit dem einen Unterschied, dass hier nicht die Werte im Objekt gesetzt werden sondern eine Rückgabe in der Form von (year,month,day,hour,minute,second) erfolgt. Die Werte des Objekts werden damit nicht verändert. Erforderlich ist diese, da ich Differenzen innerhalb des Objekts bestimme, also den Differenzwert separat splitte. Ein eigenes Objekt dafür ging natürlich auch. Ich habe es halt mal so gelöst.
Ablauf
- Mit __splitPdvmDate() wird das Datum in die Variable ret zerlegt.
- die Eigenschaften year, month und day werden über ret gesetzt.
- die Eigenschaft pdvmtime wird über den Nachkommateil von pdvmdatetime gesetzt.
- die Microsekunden (für den Tag) aus pdvmtime werden errechnet (cfntmsec)
- die Stunden (mit Rest - gerundet auf 4 Nachkommastellen) werden errechnet (xistd)
- die Eigenschaft hour wird mit dem Integer aus xistd gesetzt.
- der Rest Microsekunden (ohne Stunden) wird errechnet (reststd)
- die Minuten (mit Rest - gerundet auf 4 Nachkommastellen) werden errechnet (ximin)
- die Eigenschaft minute wird mit dem Integer aus ximin gesetzt.
- der Rest Microsekunden (ohne Stunden, Minuten ) wird errechnet (restmin)
- die Sekunden (mit Rest - gerundet auf 4 Nachkommastellen) werden errechnet (xisec)
- die Eigenschaft second wird mit dem Integer aus xisec gesetzt.
- Wegen der Ungenauigkeit bei float und vielen Nachkommastellen werden 60 Sekunden auf 0 gesetzt
- der Rest Microsekunden (ohne Stunden, Minuten, Sekunden ) wird errechnet (restsec)
- die Eigenschaft microsecond wird mit dem Integer aus restsec gesetzt.
- Wegen der Ungenauigkeit bei float und vielen Nachkommastellen werden mehr als 999000 Microsekunden auf 0 gesetzt.
- über __svalue() werden die restlichen Eigenschaften gesetzt
- die Eigenschaft dtt (Tuple mit Jahr, Monat, Tag, Stunden, Minuten, Sekunden, Microsekunden) wird zurückgegeben.
Rückgabe: (Jahr, Monat, Tag, Stunde, Minute, Sekunde)
__convertToPdvmDateTime()
Beschreibung
# --------------------------------------------------------------------
# __convertToPdvmDateTime --- Einzelzeiten geben PdvmDateTime zurück
# --------------------------------------------------------------------
def __convertToPdvmDateTime(self,year,month,day,hour,minute,second,microsecond):
# calc Tag im Jahr
self.yday = self.__calcToDayInYear(year, month, day)
# PdvmDate setzen
self.pdvmdate = (year * 1000) + self.yday
# PdvmDateTime setzen
# gesamter Zeitwert als Microsekunde
zeitwert = ((hour * self._stunde) + (minute * self._minute) +
(second * self._sekunde) + microsecond)
# Microsekundenwert auf Tage
timevalue = zeitwert / self._tag
pdvmdatetime = timevalue + self.pdvmdate
return pdvmdatetime
__convertToPdvmDateTime - Beschreibung
Source
Aus den Einzelwerte wie Jahr, Monat, Tag, Stunde, Minute, Sekunde, Microsekunden wird hier ein PdvmDateTime gebildet. Dieses ist dann auch der Rückgabewert.
Ablauf:
- aus Jahr, Monat und Tag wird mit __calcToDayInYear() der Tag im Jahr errechnet
- mit Jahr und Tag im Jahr wird dann das pdvmdate gebildet
- über die fixen Faktoren für Stunden, Minuten, Sekunden und dazu den Mikrosekunden wird der Zeitwert gebildet.
- der Zeitwert wird durch den Faktor für den Tag geteit (die angegebenen Größen können ja das vielfache eines Tages sein)
- Jahreswechsel?? -- derzeit noch ein Bug, wenn zuviele Tage entstehen... Logik muss geändert werden.
- Zeitwert + Datum ergeben den PdvmDateTime
Rückgabe: PdvmDateTime