Wenig Komfort bietet AutoLisp, was den Umgang mit Datum und
Zeit angeht - wobei wenig noch stark übertrieben ist: Es gibt
nichts! Die Systemvariablen DATE und CDATE können ausgelesen
werden, und das war's schon. Zum Handwerkszeug eines Programmierers
gehören aber Funktionen, mit denen man beispielsweise
-
Datum und/oder Zeit als String ausgeben kann
-
Mit Datum und Zeit rechnen kann
-
steuern und messen kann, z.B. Pausen oder die
Laufzeit von Programmen/Funktionen
-
Zufallszahlen erzeugen kann
Die ersten drei dieser Punkte werden in diesem Kapitel
behandelt.
CDATE enthält das aktuelle Datum und die Zeit in einer
Realzahl, in der Datum und Zeit durch das Komma getrennt
vorliegen. In eine Zeichenkette umgewandelt, sieht das
wie im folgenden Beispiel aus. Mit
(substr ...)
kann man sich die einzelnen Werte extrahieheren.
(rtos(getvar"cdate")2 6) => "20020129.205906"
(substr(getvar"cdate")2 6)1 4) => "2002" ; Jahr
(substr(getvar"cdate")2 6)5 2) => "01" ; Monat usw.
Wir benötigen also die folgenden Funktionen, um auf
Datum und Zeit zugreifen zu können. Diese Funktionen
greifen auf einige der in den Kapiteln über
Zeichenkettenbearbeitung vorgestellten String-Funktionen
zurück. Sollten Unklarheiten bestehen, bitte erst in
diesen Kapiteln nachlesen.
Die erste Funktion gibt das aktuelle Datum, die zweite
die aktuelle Uhrzeit als formatierten String zurück.
Über das Flag secs kann gesteuert werden, ob
die Sekunden mit ausgegeben werden oder nicht:
(defun date-string( / cd)
(setq cd(rtos(getvar"cdate")2 6))
(strcat
(str-lpadz(substr cd 7 2)2)
"."
(str-lpadz(substr cd 5 2)2)
"."
(substr cd 1 4)
)
)
(date-string) => "29.01.2002"
(defun time-string(secs / cd)
(setq cd(rtos(getvar"cdate")2 6))
(if secs
(strcat
(str-lpadz(substr cd 10 2)2)
":"
(str-lpadz(substr cd 12 2)2)
":"
(str-lpadz(substr cd 14 2)2)
)
(strcat
(str-lpadz(substr cd 10 2)2)
":"
(str-lpadz(substr cd 12 2)2)
)
)
)
(time-string nil) = > "20:59"
(time-string 'T) = > "20:59:06"
Die Kombination von beidem ist ganz einfach implementiert,
das Flag wird einfach weitergegeben:
(defun timedate-string(secs / )
(strcat (date-string) " "(time-string secs))
)
(timedate-string 'T) => "29.01.2002 20:59:06"
Diese Funktionen sind schon mal ein Ansatz, um Datum und
Zeit als Zeichenketten in eine Zeichnung oder Datei auszugeben.
Werfen wir nun einen Blick auf zwei Funktionen, die das
aktuelle Datum bzw. die Uhrzeit als Liste in der Form
(Jahr Monat Tag) bzw. (Stunden Minuten Sekunden) zurückgeben.
Auf das Sekunden-Flag wird hier verzichtet:
(defun date-list( / cd)
(setq cd(rtos(getvar"cdate")2 6))
(append
(list(atoi(substr cd 1 4)))
(list(atoi(substr cd 5 2)))
(list(atoi(substr cd 7 2)))
)
)
(date-list) => (2002 1 29)
(defun time-list( / cd)
(setq cd(rtos(getvar"cdate")2 6))
(append
(list(atoi(substr cd 10 2)))
(list(atoi(substr cd 12 2)))
(list(atoi(substr cd 14 2)))
)
)
(time-list) => (20 59 6)
Diese beiden Funktionen ermöglichen es uns, mit den Angaben
als Zahlen zu rechnen oder z.B. eine Formatierung zu
implementieren, bei der der Monat ausgeschrieben wird. Das
könnte etwa so aussehen:
(defun date-xstring( / d)
(setq d(date-list))
(strcat
(itoa(caddr d))
". "
(nth(1-(cadr d))'("Januar"
"Februar"
"März"
"April"
"Mai"
"Juni"
"Juli"
"August"
"September"
"Oktober"
"November"
"Dezember"
)
)
" "
(itoa(car d))
)
)
(date-xstring) => "20. Januar 2002"
Richtiges Rechnen mit diesen Listen ist natürlich ein
bisschen ungewohnt, da die Stunde nun mal 60 Minuten hat.
Es lässt sich aber leicht hinkriegen, indem man zuerst
alles in Sekunden umrechnet und hinterher wieder eine
Liste bildet.
(defun time-add(t1 t2 / r)
(setq r
(apply'+
(mapcar
'(lambda(tn / )
(+(* 3600(car tn))
(* 60(cadr tn))
(caddr tn)
)
)
(list t1 t2)
)
)
)
(list
(/ r 3600)
(/ (rem r 3600) 60)
(rem r 60)
)
)
(time-add '(9 50 42) '(4 14 31))
=> (15 5 13)
Wenig Sinn macht eine Funktion, die grundsätzlich eine
Subtraktion in bestimmter Reihenfolge vornimmt, da wir hier
evtl. negative Zeiten erhalten würden. Die nachfolgende
Funktion umgeht das Problem, indem immer eine (positive)
Zeitdifferenz ausgegeben wird:
(defun time-diff(t1 t2 / r)
(setq r
(abs
(apply'-
(mapcar
'(lambda(tn / )
(+(* 3600(car tn))
(* 60(cadr tn))
(caddr tn)
)
)
(list t1 t2)
)
)
)
)
(list
(/ r 3600)
(/ (rem r 3600) 60)
(rem r 60)
)
)
(time-diff '(4 14 31) '(9 50 42) )
=> (5 36 11)
Die Funktion (time-diff ...) lässt sich sehr schön
verwenden, um das Laufzeitverhalten von Funktionen abzuschätzen.
Da hier eine zusätzliche Aspekte bedacht werden müssen, habe
ich dieser Angelegenheit ein eigenes Kapitel gewidmet.