In dem Artikel /Blog/2012/03/Wertebereich-von-Datentypen-der-Datenbank bin ich auf die verschiedenen Datentypen der Datenstruktur eingegangen und habe Ihnen deren Wertebereich erläutert. In CONZEPT 16 existieren allerdings nicht nur allgemeine sondern auch spezielle Variablentypen. Einer von diesen speziellen Variablentypen ist der CalTime-Datentyp. Im folgenden Artikel möchte ich Ihnen diesen Datentyp näher bringen.
Der CalTime-Datentyp enthält in erster Linie Informationen zum Datum und der Uhrzeit. Eine Variable diesen Types verfügt allerdings über mehrere Eigenschaften und Methoden. Der Wertebereich diesen Datentyps geht vom 01.01.1601 bis zum 31.12.30000. Die Definition dieser Variable erfolgt nach dem selben Prinzip wie bei allen anderen Definitionen in CONZEPT 16.
Eigenschaften der Variablen vom Typ CalTime
Die Eigenschaften der Variablen werden immer mit dem Operator "->" angesprochen. Generell lassen sich die Eigenschaften in zwei Kategorien unterteilen. Die erste Kategorie beinhaltet die Eigenschaften, welche gesetzt oder auch abgefragt werden können. In der zweiten Kategorie befinden sich die Eigenschaften welche ausschließlich ausgelesen werden können.
Eigenschaften, welche gelesen und gesetzt werden können:
vpYear : int
– Jahreszahl
In dieser Eigenschaft kann das Jahr gesetzt / abgefragt werden.vpMonth : int
– Monat
Hier kann der Monat gesetzt oder abgefragt werden.vpDay : int
– Tag
In dieser Eigenschaft kann der Tag des Datums abgefragt oder geändert werden.vpHours : int
– Stunden
Über diese Eigenschaft können die Stunden der Uhrzeit gesetzt / abgefragt werden.vpMinutes : int
– Minuten
Mit dieser Eigenschaft können die Minuten eines Zeitwertes gesetzt / abgefragt werden.vpSeconds : int
– Sekunden
Hier können die Sekunden eines Zeitwertes gesetzt / abgefragt werden.vpMilliseconds : int
– Millisekunden
In dieser Eigenschaft können die Millisekunden einer Uhrzeit gesetzt oder abgefragt werden.vpDate : date
– Datumswert
Hier kann das Datum abgefragt oder gesetzt werden.vpTime : time
– Zeitwert
Über die Eigenschaft kann die Uhrzeit abgefragt bzw. gesetzt werden.vpBiasMinutes : int
– Zeitzonenabweichung
In dieser Eigenschaft steht die Abweichung der Zeit auf Grund der Zeitzone von der UTC. Diese Eigenschaft kann jederzeit abgefragt werden, allerdings erhält sie den Wert0
wenn sie vorher nicht übervmSystemTime()
odervmServerTime()
gesetzt wurde.
Nach der Deklaration sind die Variablen mit dem Wert NULL
initialisiert. Somit haben alle Eigenschaften den Wert 0
bzw. 0.0.0
und 00:00:00.0
Eigenschaften, welche nur gelesen werden können:
vpLeapYear : logic
– Schaltjahr
Die Eigenschaft hat den Wert TRUE, wenn das angegebene Datum ein Schaltjahr ist.vpWeek : int
– Kalenderwoche
In der Eigenschaft steht die Kalenderwoche des gesetzten Datums.vpWeekYear : int
– Jahr der Kalenderwoche
In der Eigenschaft steht das Jahr der Kalenderwoche des gesetzten Datums.vpDayOfWeek : int
– Wochentag
Diese Eigenschaft liefert die Nummer des Wochentages zurück.
Methoden des CalTime-Datentyps
Die Methoden der Variablen des Types CalTime können ebenso wie die Eigenschaften mit dem Operator "->" angesprochen werden
vmSystemTime()
Mit dieser Methode kann das aktuelle Datum und / oder die aktuelle Uhrzeit ermittelt werden.vmServerTime()
Mit dieser Methode kann das aktuelle Datum und / oder die aktuelle Uhrzeit des CONZEPT 16-Datenbankservers ermittelt werden.vmEasterDate()
Diese Methode liefert den Ostersonntag für das angegebene Jahr zurück.vmMonthModify()
Mit dieser Methode kann der Monat eines Datumswertes verändert werden.vmDayModify()
Mit Hilfe dieser Methode kann der Tag eines Datumswertes verändert werden.vmSecondsModify()
Mit dieser Methode kann ein Zeitwert verändert werden.
Update: Um Informationen des CalTime
-Datentyps in eine Datenbank zu speichern, wird der Datentyp in BigInt
konvertiert (CnvBC()
). Somit ergibt sich außerdem die Möglichkeit anhand diesen Wertes Berechnungen durchzuführen. Zum Beispiel um die Dauer einer Selektion zu berechnen. Wird nun der ursprüngliche Wert benötigt, konvertiert man den BigInt
Datentyp wieder zurück in den CalTime
-Datentyp (CnvCB()
).
8 Antworten
@Kilian
Die Methode vmSystemTime() ist ja nicht nur für caltime, sondern auch für die Typen date, time und int64 verwendbar. Daher gibt es auch keinen Rückgabewert. Alternativ wäre auch eine zusätzliche SysCaltime() und SysTimestamp() etc. möglich gewesen. Anstatt der einen Methode vmServerTime() wären aber in diesem Fall 4 Funktionen notwendig gewesen.
Das Hauptproblem von SysDate() und SysTime() besteht in der Rückgabe der lokalen Zeit (kein UTC), der geringen Auflösung von 1/100-Sekunden, und der Speicherung des Zeitpunkts in zwei Variablen. Die Verwendung von int64 und caltime vereinfacht da doch einiges.
@Klaus
Mit einem unvollständigen Datum sind keine Berechnungen möglich. Wird beispielsweise der Tag nicht benötigt, setzt man ihn eben immer auf 1.
@Florian
Das Argument, man könne sich ja eine eigene Funktion schreiben, ist zwar zutreffend, gilt aber genauso in die Gegenrichtung: Wozu die vm-Methoden einführen, wir haben ja SysDate() und jeder der was anderes will, kann sich ja eine entspr. Funktion schreiben.
Daneben löst Ihr Vorschlag das Problem der aufeinander folgenden Methodenaufrufe nicht: "SystemTime()->vmMonthModify(-12)->vmEasterDate()". Dies ist in C16 aus zwei Gründen derzeit nicht möglich, a) weil die vm-Methoden nichts Sinnvolles zurückliefern und b) weil der C16-Compiler aufeinander folgende quasi objektorientierte Konstrukte wie "hA->getB()->getC()" ohnehin nicht versteht.
Daher ja mein Eindruck, dass im Falle der vm-Methoden Konstrukte geschaffen worden sind, die nicht so recht in das System passen und mein Vorschlag wäre entweder a) objektorientiertes Programmieren in C16 möglich zu machen oder b) niemals pragmatische Methoden wie GetMeSomethingUseful() durch umständliche Konstrukte Obj->changeUnderlyingObjectButDontReturnAnything() zu ersetzen. Am Liebsten natürlich a).
Anm. zum Problem unvollständiger Daten:
Derartige unvollständige CalTimes sind nur noch sehr eingeschränkt verwendbar, wenn man unter Verwendung des 2. Beispiels von Florian:
tCalTime->vmDayModify(-2) ausführt und danach tCalTime->vpDay abfragt bekommt man 1 zurück, statt 31.
@Klaus
Das können Sie realisieren, indem Sie bei einer leeren Caltime-Variable die einzelnen Datumselemente über ihre Eigenschaften setzen.
Datum ohne Tag:
tCaltime # NULL;
tCaltime->vpYear # 2012;
tCaltime->vpMonth # 4;
Datum ohne Jahr:
tCaltime # NULL;
tCaltime->vpMonth # 4;
tCaltime->vpDay # 1;
Dabei ist allerdings zu beachten, dass die vpDate-Eigenschaft nicht mehr abgefragt werden kann, da sie kein gültiges Datum liefert.
@Th.Eichele
Das Abfragen der Systemzeit vom Betriebssystem ist ohnehin eine Operation die u.U. einen Augenblick an Zeit kostet, da sollte der Aufruf der Funktion kaum ins Gewicht fallen.
Bei einer längeren Verarbeitung können Sie sich die aktuelle Zeit aber auch in einer Variable speichern und diese anstelle des Funktionsaufrufs übergeben:
tTime->vmSystemTime();
for …
loop …
while (…)
DoAnything(tTime, …);
Der vorgeschlagene Workaround fördert aber sicher nicht die Laufzeit
Gibt es auch eine Möglichkeit unvollständige Datumsangaben zu handhaben? Konkret haben wir folgende Fälle :
Das Prüfdatum an einem technischen Gerät (wie z.B. TÜV beim PKW) ist an keinen bestimmten Tag gebunden, sondern lediglich Monat und Jahr stehen fest. Wenn hier Datumsangaben mit dem Tageswert 0 aber den richtigen Monats- und Jahreswerten zulässig wären, könnten die vorhandenen Möglichkeiten der Datumsberechnung genutzt werden ohne eigene Routinen, die mit zwei Variablen (Monat und Jahr) arbeiten, nutzen zu müssen.Auch könnte bei geplanten Daten, bei denen der Tag noch nicht endgültig feststeht, dieser im Nachhinein ergänzt werden und jedem wäre gleich ersichtlich, dass der Termin noch nicht taggenau festliegt.
Der zweite Fall sind Daten ohne Jahresangabe (bzw. 0000), z.B. Geburtsdatum ohne Kenntnis des Geburtsjahres.
Wenn es nur darum geht, die Systemzeit als Rückgabewert an eine Funktion übergeben zu können, können Sie sich natürlich auch einfach eine kleine Hilfsfunktion schreiben:
sub Sys.TimeGet
()
: caltime;
local
{
tTime : caltime;
}
{
tTime->vmSystemTime();
return(tTime);
}
Diese Funktion können Sie dann anstelle der Funktionen SysDate() und SysTime() verwenden.
Laut Hilfe sollen die vm-Methoden statt der Funktionen SysDate(), SysTime() verwendet werden. Ich frage mich, warum diese Änderung vorgenommen wurde, denn ich halte sie für unpraktisch.
Die vm-Methoden haben den Nachteil, dass sie keinen Wert zurückliefern, sondern einen gegebenen CalTime/Date-Wert verändern, damit ist eine Verwendung ähnlich wie in: "DoAnything(SysDate(), …)" nicht möglich, sondern man muss erst eine Variable deklarieren, dann die Methode darauf aufrufen und kann dann erst die DoAnything-Funktion mit der Systemzeit aufrufen: "… local { SystemTime : CalTime } … SystemTime->vmSystemTime(); DoAnything(SystemTime, …)"
Das finde ich recht umständlich.
Sinnvoll sind solche Mehtoden sicherlich, aber da C16 nicht objektorientiert ist, bringt’s relativ wenig. Damit diese Konstrukte die Produktivität fördern statt hemmen, müsste man Aufrufe wie "SystemTime()->vmYearModify(1)->vmEasterDate()" machen können. Dann könnte man z.B. auch "DoAnything(SystemTime()->vmDayModify(-1),…)" durchführen und die SysDate() und SysTime() Funtkionen wären tatsächlich entbehrlich.