ein Kapitel zurück                                           ein Kapitel weiter

Kommen wir nun zur Headerdatei <time.h> worin einige Zeit- und Datumsfunktionen enthalten sind. Zuerst will ich Ihnen die 4 Datentypen die ebenfalls in der Headerdatei <time.h> enthalten sind auflisten mit deren Bedeutung....

Datentyp Bedeutung
size_t arithmetischer Datentyp für Größenangaben
clock_t arithmetischer Datentyp für CPU-Zeit
time_t arithmetischer Datentyp für Datum- und Zeitangabe
struc tm enthält alle zu einer Kalenderzeit (Gregorianischen) relevanten Komponenten.


Laut ANSI-C sollten in der Struktur....

struct tm  

...folgende Komponenten enthalten sein....

int tm_sec;    //Sekunden (0-61)
int tm_min;    //Minuten (0-59)
int tm_hour;   //Stunden (0-23)
int tm_mday;   //Monatstag (1-31)
int tm_mon;    //Monate (0-11)
int tm_year;   //ab 1900
int tm_wday;   //Tag seit Sonntag (0-6)
int tm_yday;   //Tag seit 1.Januar (0-365)
int tm_isdst;  //Sommerzeit== >0; Winterzeit== 0; nicht verfügbar== <0  

Auf Linux ist außerdem noch folgende Komponenten vorhanden.....

long int tm_gmtoff;  

...gibt die Sekunden östlich von UTC bzw. den negativen Wert westlich von UTC für Zeitzonen an. Diese Angabe kann aber auch unter der Schreibweise...

long int __tm_gmtoff  

...vorliegen. Ebenfalls nur unter Linux ist folgendende Komponente enthalten...

const char *tm_zone;  

...die den Namen der aktuellen Zeitzone enthält. Es kann aber auch in dieser Schreibweise vorhanden sein...

const char *__tm_zone;  

Konstanten
Folgende 2 Konstanten sind in der Headerdatei <time.h> definiert...

CLOCKS_PER_SEC  

Konstante enthält die Anzahl von clock_t-Einheiten pro Sekunde.

NULL  

Der selbe NULL-Zeiger den wir schon in der Headerdatei <stdio.h> kennen gelernt haben.

Datums -und Zeitfunktionen
Die Zeit mit der der Systemkern arbeitet sind die Sekunden die seit 00:00:00 Uhr des 1.Januar 1970 vergangen sind. Diese Zeit wird immer mit dem Datentyp time_t dargestellt und enthält das Datum und die Uhrzeit. Diese Zeit wollen wir jetzt mit der Funktion....

time_t time(time_t *zeitzeiger);  

...ermitteln. Wenn sie für den Parameter zeitzeiger keinen NULL-Zeiger angeben wird der entsprechende Rückgabewert (Kalenderzeit) auch noch im Speicherplatz hinterlegt, auf dem zeitzeiger zeigt. Hier nun ein kleines Programm das uns die Zeit in Sekunden fortlaufend seit dem 1.Januar 1970 um 00:00:00 Uhr ausgibt und die Funktion time() demonstrieren soll.

/*Download:time1.c*/
#include <stdio.h> #include <time.h> #ifdef __MSDOS__ #define clrscr() system("cls") #else #define clrscr() printf("\x1B[2J") #endif int main() { time_t t; time(&t); while(1) { clrscr(); printf("%ld\n",t); printf("Mit <STRG><C> beenden!! "); time(&t); } return 0; }

Nun nach dem Y2K-Problem steht uns bis zum Jahre 2038 das nächste Problem an. Mittlerweile steht bei Schreiben dieses Textes die Sekundenzahl seit 1970 auf einer Milliarde.

time_t ist intern als long implementiert, also Platz für etwa 2 Milliarden Sekunden. Sicherlich werden wir uns wieder in letzter Minute dessen längst bekannten Problem annehmen.

Nun ist die Ausgabe der Sekunden nicht gerade sehr originell. Man kann nun anfangen eine Funktion zu schreiben womit die Sekunden die unsere Funktion time() zurückliefert in ein entsprechendes Format ausgibt wie man es benötigt. Aber das bleibt uns zum Glück erspart denn das nehmen uns die beiden Funktionen......

struct tm *localtime(time_t *zeitzeiger);  

...oder...

struct tm *gmtime(time_t *zeitzeiger);  

...ab. Sie sehen schon der Rückgabewert beider Funktionen ist vom Typ 'struct tm'. Diese Struktur haben wir bereits zu beginn dieses Kapitels durchgenommen. Die Funktion localtime() wandelt die Kalenderzeit auf die time_t *zeitzeiger zeigt in lokaler Ortszeit unter der Berücksichtigung von Sommer- und Winterzeit. gmtime() dagegen wandelt die Kalenderzeit in die UTC-Zeit um.

Hierzu nun ein Beispiel die als Eingabe Ihr Geburtsdatum erwartet und Ihnen anschließend Ihr Alter in Jahre, Monate und Tage ausgibt.....

/*Download:time2.c*/
#include <stdio.h> #include <time.h> struct tm *tmnow; /*Globale Variable*/ long today(void) { time_t tnow; time(&tnow); tmnow = localtime(&tnow); printf("Heute ist der "); printf("%d.%d.%d\n",tmnow->tm_mday,tmnow->tm_mon + 1,tmnow->tm_year + 1900); return 1; } int main() { int tag,monat,jahr; long dnow; unsigned int i=0,tmp; printf("Bitte gib dein Geburtstag ein!\n"); printf("Tag : "); scanf("%d",&tag); printf("Monat : "); scanf("%d",&monat); printf("Jahr (jjjj) : "); scanf("%d",&jahr); today(); if(tmnow->tm_mon<monat) { i=1; tmp=tmnow->tm_mon+1-monat; monat=tmp+12; } else { tmp=tmnow->tm_mon+1-monat; monat=tmp; } printf("Sie sind %d Jahre %d Monate %d Tage alt\n", tmnow->tm_year+1900-jahr-i, monat, tmnow->tm_mday-tag); return 0; }

Noch eine Anmerkung zur if-else-Anweisung im Programm. Die war nötig damit im Monatsdatum kein negativer Wert herauskommt und sie auf einmal 1 Jahr älter sind als erwartet.

Nun kommen wir zu einer Funktion die etwa das Gegenteil unserer Funktionen 'localtime()' und 'gmtime()' macht.....

time_t mktime(struct tm *zeitzeiger);  

...damit wandeln wir eine Zeit im 'struct tm' wieder um in eine Zeit im 'time_t' Format. Ist die Kalenderzeit nicht darstellbar gibt diese Funktion -1 zurück. Die echten Werte der Komponenten tm_yday und tm_wday in 'zeitzeiger' werden ignoriert. Die ursprünglichen Werte der Felder tm_sec, tm_min, tm_hour, tm_mday und tm_mon sind nicht auf den durch die tm-Struktur festgelegten Bereich beschränkt. Befinden sich die Felder nicht im korrekten Bereich, werden sie angepaßt. Das heißt jetzt konkret wenn sie z.B. das Datum '38.3.2001' eingeben muss die Funktion mktime() dies Datum richtig setzen. Bei richtiger Rückgabe erhalten wir entsprechende Werte für tm_yday und tm_wday .

Die zulässige Bereich für die Kalenderzeit liegt zwischen dem 1. Januar 1970 00:00:00 und dem 19. Januar 2038 03:14:07.

Und was erwartet uns nach diesem Datum? Nach dem Y2-Problem nun das Y-38-Problem ;) Hierzu nun ein Beispiel wie sie den genauen Wochentag durch diese Funktion erhalten können....

/*Download:time3.c*/
#include <stdio.h> #include <time.h> char *wday[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Unknown"}; int main(void) { struct tm time_check; int year, month, day; /*jahr,monat und tag eingeben zum herausfinden des Wochentags*/ printf("Year: "); scanf("%d", &year); printf("Month: "); scanf("%d", &month); printf("Day: "); scanf("%d", &day); /*Wir füllen unsere Struktur struct tm time_check mit Werten*/ time_check.tm_year = year - 1900; time_check.tm_mon = month - 1; time_check.tm_mday = day; /* 00:00:01 Uhr*/ time_check.tm_hour = 0; time_check.tm_min = 0; time_check.tm_sec = 1; time_check.tm_isdst = -1; /* call mktime to fill in the weekday field of the structure */ if (mktime(&time_check) == -1) time_check.tm_wday = 7; /*==Unbekannter Tag*/ /* Der Tag des Datums wird ausgegeben */ printf("That day is a %s\n", wday[time_check.tm_wday]); return 0; }

Jetzt kommen wir zu zwei Funktionen die beide Zeitformen, zum einen die Zeit in Form von 'struct tm' und zum anderen in Form von 'time_t', in einen String oder richtig ausgedrückt einen Zeiger auf einem String zurückliefern. Hier der Syntax der beiden Funktionen....

char *asctime(struct tm *zeitzeiger);  

...und...

char *ctime(time_t *zeitzeiger);  

Hierzu auch ein kleines Beispiel beider Funktionen in einem Programm....

/*Download:time4.c*/
#include <stdio.h> #include <time.h> #include <string.h> int main(int argc, char **argv) { FILE *datei; time_t time1; struct tm *time2; char zeit[25]; int c; if(argc<2) { fprintf(stderr,"Bitte Eingeben : %s textdatei.txt\n",*argv); exit(0); } if((datei = fopen(*++argv,"w+")) == NULL) { fprintf(stderr,"Konnte Datei : %s nicht ”ffnen!!!!\n",*argv); exit(1); } /*Wir schreiben in unsere Datei und beenden diese mit dem Zeichen # */ while((c=getchar()) != '#') putc(c, datei); putc('\n', datei); /*Zuerst time_t - Format*/ time(&time1); printf("Heute ist %s und sie haben eben die Datei %s geschlossen\n", ctime(&time1),*argv); /*Jetzt struct tm Format mit asctime() */ time1=time(NULL); time2=localtime(&time1); strcpy(zeit,asctime(time2)); /* Das Datum schreiben wir in die Datei...*/ fprintf(datei,"%s\n",zeit); fclose(datei); return 0; }

Diese Beispiel schreibt zum einen das heutige Datum mit der Funktion ctime() auf dem Bildschirm und mit der Funktion asctime() in die Textdatei als String.

Als nächste Funktion wollen wir die Differenz zwischen zwei Zeiten ermitteln. Hier der Syntax zu dieser Funktion.....

double difftime(time_t zeit1, time_t zeit0);  

Diese Funktion liefert die Differenz zwischen zeit1-zeit0 als double-Wert zurück. Hierzu ein einfaches und kurzes Beispiel.....

/*Download:time5.c*/
#include <stdio.h> #include <time.h> int main() { time_t start, stop; double diff; start=time(NULL); while((diff=difftime(stop=time(NULL),start)) !=5); printf("%.1f sek. vorbei!!\n",diff); return 0; }

Das Programm wartet 5 Sekunden bis es dementsprechenden Text ausgibt. An der Schreibweise.... ...könn

while((diff=difftime(stop=time(NULL),start)) !=5);  

en sie sehen das die Funktion 'time()' gleich in der Funktion 'difftime()' ausführen können. Natürlich ist das ganze nicht so gut lesbar aber es erfüllt den selben Zweck wie....

while((diff=difftime(stop,start)) !=5)
   stop=time(NULL);  

Eine weitere häufig gestellte Frage lautet, wie kann man herausfinden wie lange das Programm schon läuft. Dies können wir mit der Funktion.....

clock_t clock();  

...ermitteln. Die Funktion liefert die verbrauchte CPU-Zeit seit Programmstart. Falls die CPU-Zeit nicht verfügbar ist liefert diese Funktion -1 zurück. Wenn sie die CPU-Zeit in Sekunden benötigen müssen sie den Rückgabewert dieser Funktion durch CLOCK_PER_SEC dividieren. Beispiel.....

/*Download:time6.c*/
#include <stdio.h> #include <time.h> int main() { clock_t prgstart, prgende; int c; prgstart=clock(); printf("Bitte geben sie irgendetwas ein und beenden sie mit '#'!!\n"); printf("\n > "); while((c=getchar())!= '#') putchar(c); prgende=clock(); printf("Die Programmlaufzeit betrug %.2f Sekunden\n", (float)(prgende-prgstart) / CLOCKS_PER_SEC); return 0; }

Damit dürfte es nicht schwierig sein die Benutzungsdauer des Programms zu ermitteln.

Nun bleibt uns eigentlich nur noch eine Funktion die zumindest auf allen Systemen funktioniert.....

size_t strftime(char *puffer, int maxzeichen, const char *format, struct tm *zeitzeiger);  

Das ist sozusagen die sprintf - Funktion für Zeit- und Datumswerte. Damit können wir die Kalenderzeit aus struct tm *zeitzeiger in das entsprechende Format an die Adresse puffer schreiben. Folgende Umwandlungsvorgaben stehen uns dabei zur Verfügung...

Angabe wird ersetzt durch Beispiel
%a abgekürzter Wochenname Sat
%A ausgeschriebener Wochenname Saturday
%b abgekürzter Monatsname Jan
%B ausgeschriebener Monatsname January
%c entsprechende Zeit-und Datumsdarstellung Sat Jan 22 22:22:22 MET 2001
%d Monatstag (0-31) 22
%H Stunde (0-23) 23
%I Stunde (1-12) 5
%j Tag des Jahres (1-365) 133
%m Monat (1-12) 5
%M Minute (0-59) 40
%p AM oder PM (USA) PM
%S Sekunden (0-61) 55
%U Wochennummer (0-52) 33
%w Wochentag (0-6, 0=Sonntag) 3
%W Wochennummer (0-52) 4
%x geeignete Datumsdarstellung 02/20/02
%X geeignete Zeitdarstellung 20:15:00
%y Jahreszahl (ohne Jahrhundertzahl) 01 (2001)
%Y Jahreszahl (mit Jahrhundertzahl) 2001
%Z Zeitzone MET
%% %  


Hier nun ein kleines Beispiel wie sie diese Funktion anwenden können....

/*Download:time7.c*/
#include <stdio.h> #include <time.h> int main() { struct tm *zeit; time_t sekunde; char string[80]; time(&sekunde); zeit = localtime(&sekunde); strftime(string, 80, "Es ist %H Uhr und %M Minuten (%Z) %A, %B %d 20%y",zeit); printf("%s\n",string); return 0; }

Es wird übrigens empfohlen bei der Formatierten Zeitausgabe des Jahres %Y anstatt %y zuverwenden, um Probleme mit dem Jahr 2000 zu vermeiden.

Das wären nun alles Standartfunktion für Zeit-und Datumsangaben die auf allen System laufen. Im nächsten Kapitel will ich noch ein paar Funktionen durchnehmen die nur unter Linux/Unix - Systemen zur Verfügung stehen. Ich hoffe das diese Kapitel nicht allzu theoretisch war aber bei der Menge an Zeitfunktionen habe ich mich entschlossen dieses Kapitel zu kurz wie möglich zu halten. Bei Fragen oder Kritik zu diesem Thema schicken sie mir bitte eine E-Mail.

ein Kapitel zurück          nach oben           ein Kapitel weiter


© 2001,2002 Jürgen Wolf