|
int tm_yday; /* Tage seit dem 1. Januar [0,365] */
int tm_isdst; /* Flag für Sommerzeit */
};
Um die aktuelle Zeit der internen Uhr Ihres Systems abzufragen,
verwenden Sie die Funktion time():
time_t time(time_t *ptr);
Die Funktion liefert die Anzahl der Sekunden zurück, die seit
Mitternacht des 1. Januar 1970 verstrichen sind. Wenn der Funktion
ein Nicht-NULL-Zeiger übergeben wird, speichert
time() diesen Wert in der Variablen vom Typ time_t,
auf die der Zeiger ptr zeigt. Die beiden folgenden Anweisunge
speichern die aktuelle Zeit in der Variablen jetzt:
time_t jetzt;
jetzt = time(NULL);
Oder Sie verwenden die Rückgabe über das Argument:
time_t jetzt;
time(&jetzt);
Mit der Funktion localtime() wandeln Sie einen
time_t-Wert in eine tm-Struktur um.
struct tm *localtime(time_t *ptr);
Diese Funktion liefert einen Zeiger auf eine statische Variable vom Typ
tm zurück, so dass Sie keine Variable vom Typ tm
deklarieren müssen, sondern nur einen Zeiger auf den Typ tm.
Die statische Variable wird bei jedem Aufruf von localtime()
wieder verwendet und überschrieben. Wenn Sie den zurückgegebenen
Wert sichern wollen, muß das Programm eine separate Variable vom
Typ tm deklarieren und in diese die Werte der statischen Variablen
kopieren.
Die umgekehrte Konvertierung - von einer Variablen vom Typ tm
in einen Wert vom Typ time_t - erfolgt mit Hilfe der Funktion
mktime(). Der Prototyp lautet:
time_t mktime(struct tm *ntime);
Diese Funktion liefert die Anzahl der Sekunden, die zwischen Mitternacht des
1. Januar 1970 und der Zeit verstrichen sind, die durch die Variable vom
Typ tm, auf die ntime zeigt, dargestellt wird.
Um Zeitangaben in formatierte Strings zu konvertieren, die ausgegeben werden
können, gibt es die Funktionen ctime() und asctime().
Beide Funktionen liefern die Zeit als einen String in einem vordefinierten
Format zurück. ctime() wird die Zeit als ein Wert vom Typ
time_t übergeben wird, während asctime() die
Zeit als eine Strukturvariable vom Typ tm entgegennimmt:
char *asctime(struct tm *ptr);
char *ctime(time_t *ptr);
Beide Funktionen liefern einen Zeiger auf einen statischen, nullterminierten
26-Zeichen-String zurück, der die Zeit des Funktionsarguments im folgenden
24-Stunden-Format angibt:
Thu Apr 30 11:22:15 2003
Beide Funktionen verwenden einen statischen String, der bei jedem Aufruf der
Funktion überschrieben wird.
Wenn Sie das Format der Zeit ändern wollen, steht Ihnen dazu die Funktion
strftime() zur Verfügung. Dieser Funktion wird die zu formatierende
Zeitangabe als Strukturvariable vom Typ tm übergeben. Die Formatierung
erfolgt anhand eines Formatstrings. Der Prototyp der Funktion lautet:
size_t strftime(char *s, size_t max, char *fmt, struct tm *ptr);
Die Funktion nimmt die zu formatierende Zeitangabe über die
tm-Strukturvariable entgegen, auf die der Zeiger ptr weist,
formatiert sie nach Vorgabe des Formatstrings fmt und schreibt das
Ergebnis als nullterminierten String an die Speicherpositeon, auf
die s zeigt. Das Argument max sollte die Größe des
Speicherbereichs angeben, der für s reserviert wurde. Wenn der
resultierende String (einschließlich des abschließenden
Nullzeichens) mehr als max Zeichen enthält, liefert die Funktion
0 zurück, und der String s ist ungültig. Im anderen
Fall liefert die Funktion die Anzahl der geschriebenen Zeichen zurück.
Der Formatstring besteht aus einem oder mehreren der folgenden
Konvertierungsspezifizierer:
Spezifizierer | wird ersetzt durch: |
%a | Abgekürzter Wochentagsname |
%A | Voller Wochentagsname |
%b | Abgekürzter Monatsname |
%B | Voller Monatsname |
%c | Datums- und Zeitdarstellung (zum Beispiel, Tue Apr 18 10:41:50 2000) |
%d | Tag des Monats als Dezimalzahl von 01 bis 31 |
%H | Die Stunde als Dezimalzahl von 00 bis 23 |
%I | Die Stunde als Dezimalzahl von 00 bis 11 |
%j | Der Tag des Jahres als Dezimalzahl von 001 bis 366 |
%m | Der Monat als Dezimalzahl von 01 bis 12 |
%M | Die Minute als Dezimalzahl von 00 bis 59 |
%p | AM oder PM |
%S | Die Sekunde als Dezimalzahl von 00 bis 59 |
%U | Die Woche des Jahres als Dezimalzahl von 00 bis 53. Der Sonntag wird als erster Tag der Woche betrachtet |
%w | Der Wochentag als Dezimalzahl von 0 bis 6 (Sonntag = 0) |
%W | Die Woche des Jahres als Dezimalzahl von 00 bis 53. Der Montag wird als erster Tag der Woche betrachtet |
%x | Datumsdarstellung (zum Beispiel, 30-Jun-91) |
%X | Zeitdarstellung (zum Beispiel, 10:41:50) |
%y | Das Jahr, ohne Jahrhundert, als Dezimalzahl von 00 bis 99 |
%Y | Das Jahr, mit Jahrhundert, als Dezimalzahl |
%Z | Der Name der Zeitzone, wenn die Information verfügbar ist, oder leer, wenn er nicht bekannt ist |
%% | Ein einfaches Prozentzeichen % |
Sie können den Zeitunterschied zwischen zwei Zeitangaben mit dem Makro
difftime() in Sekunden berechnen. Dieses Makro subtrahiert zwei
time_t-Werte und liefert die Differenz zurück. Der Prototyp lautet:
double difftime(time_t zeit1, time_t zeit0);
Diese Funktion subtrahiert zeit0 von zeit1 und liefert die Differenz,
das heißt die Anzahl der Sekunden zwischen den beiden Zeiten, zurück.
Häufig wird difftime() dazu verwendet, die verstrichene Zeit zu berechnen.
Die Funktion clock() gibt an, wie viel Millionstelsekunde seit Beginn der
Programmausführung verstrichen sind. Der Prototyp der Funktion lautet:
clock_t clock(void);
Um herauszufinden, wie viel Zeit für die Ausführung eines bestimmten
Programmabschnitts benötigt wird, müssen Sie clock() zweimal
aufrufen - vor und nach dem betreffenden Codeblock - und dann die beiden
Rückgabewerte voneinander subtrahieren.
/* Beispiele fr die Verwendung der Zeitfunktionen. */
#include <stdio.h>
#include <time.h>
int main(void)
{
time_t beginn, ende, jetzt;
struct tm *zgr;
char *c, string[80];
double dauer;
/* Die Zeit des Programmstarts festhalten. */
beginn = time(0);
/* Die aktuelle Zeit festhalten. */
time(&jetzt);
/* Konvertiert den time_t-Wert in eine Struktur vom Typ tm. */
zgr = localtime(&jetzt);
/* Erzeugt einen formatierten String mit der aktuellen */
c = asctime(zgr);
puts(c);
/* Verwendet die strftime()-Funktion, um verschiedene */
/* formatierte Versionen der Zeit zu erzeugen. */
strftime(string,80,"Dies ist %U. Woche des Jahres %Y",zgr);
puts(string);
strftime(string, 80, "Heute ist %A, %m/%d/%Y", zgr);
puts(string);
strftime(string, 80, "Es ist %M Minuten nach %I.", zgr);
getc(stdin);
/* Liest die aktuelle Zeit ein u. berechnet die Programmdauer. */
ende = time(0);
dauer = difftime(ende, beginn);
printf("Ausfhrungszeit mit time() = %f Sekunden.\n", dauer);
/* Gibt die Programmdauer mit clock() in Mikrosekunden an */
printf("Ausfhrungszeit mit clock() = %ld .\n", clock());
return(0);
}
Datumsarithmetik
Die meisten dieser Algorithmen sind in der Literatur seit langem festgelegt. Es
handelt sich um relativ einfache Berechnungen, weshalb keine Struktogramme
beigefügt sind. Meine Informationen stammen aus einer Artikelserie von
Heinz Zemanek in "Elektronische Rechenanlagen" 6/78, 4/79 und 6/79 und
aus Jean Meeus: Astronomische Algorithmen, Barth, 1992, ISBN 3-335-00318-7.
Julianischer Tag
Es gäbe kein Jahr-2000-Problem, wenn alle Programmierer und Computerhersteller
die Julianische Tageszahl für das Datum verwendet hätten. Stattdessen
wurde das Jahr als Zeichenkette (TTMMJJ) gespeichert und das führte dazu,
daß nach 99 das Jahr 00 kommt. Grund für die zweistellige Speicherung
der Jahreszahl war der Zwang zum Speichersparen. Auch hier liegt die Julianische
Tageszahl vorne, sie hätte noch weniger Speicher gebraucht.
Die Julianische Tageszahl - oder einfacher der Julianische Tag -
ist eine fortlaufende Zählung der Tage, beginnend mit dem Tag 0,
der am 1. Januar 4713 v. Chr. (im proleptischen Julianischen Kalender)
um 12 Uhr Mittags begann. Dementsprechend beginnt ein neuer
Julianischer Tag auch immer um 12 Uhr Mittags, was ursprünglich
für die europäische Astronomie den Vorteil besaß, daß alle
Beobachtungen einer Nacht an einem einzigen Julianischen Tag
stattfanden.
Die Julianische Tageszählung läßt sich durch Anhängen des seit
12 Uhr Mittags verflossenen Tagesbruchteils leicht zu einer genauen
Zeitangabe erweitern. So bezeichnet JD 2'451'605 den Tag, der am
1. März 2000 um 12 Uhr beginnt, während JD 2'451'605.25 den Zeitpunkt
um 18 Uhr desselben Tages bestimmt. Diese Erweiterung wird in vielen
Quellen als Julianisches Datum bezeichnet.
Julianische Tage wurden früher in der Regel (sofern nichts anderes
spezifiziert wurde) nach mittlerer Sonnenzeit gezählt, heute nach UT.
Die Weltzeit oder Universal Time (UT) wurde 1926 als Ersatz für
die Greenwich Mean Time (GMT) eingeführt. Zur dieser Zeit waren
mehrere, zum Teil deutlich unterschiedliche Bedeutungen von GMT im Gebrauch.
UT ist für meisten praktische Belange gleichzusetzen mit der mittleren
Sonnenzeit bezogen auf den Nullmeridian von Greenwich.
Alternativ wurden Angaben auch in Ephemeridenzeit gemacht, was durch
die Bezeichnung JED oder JDE gekennzeichnet wurde. Auch heute ist
gelegentlich sinnvoll, Julianische Tage in einer anderen als der
UT-Skala anzugeben. Die verwendete Zeitskala ist dann an die
Zeitangabe anzuhängen, z.B. als JD 2 451 545.0 TDT für den 1.Januar
2000, 12 Uhr Mittags nach TDT-Zeit.
Häufig finden sich auch Zeitangaben in einem Modifizierten
Julianischen Datumsformat (MJD). Die gebräuchlichste Definition
eines MJD folgt aus MJD = JD - 2400000.5
der Nullpunkt liegt daher beim 17. November 1858 um 0 Uhr (!) Weltzeit.
Andere Definitionen existieren allerdings auch, so daß bei der
Verwendung von Daten in MJD Vorsicht geboten ist. Aus diesem Grunde
wird MJD auch von der Internationalen Astronomischen Union nicht
anerkannt.
Die Bedeutung der Julianischen Tagesangabe in der heutigen Astronomie
liegt zum einen in der Möglichkeit einer kompakten, eindeutigen
Zeitangabe, zum anderen in der einfachen Angabe und Berechnung von
Zeitdifferenzen, Perioden usw.
Die Julianische Tageszählung wurde 1581 von dem französischen
Gelehrten Joseph Justus Scaliger (in seinem Werk 'Opus novum de
emendatione temporum') eingeführt, um eine eindeutige Zeitzählung
ohne negative Jahreszahlen zu erhalten. Dazu mußte der Anfang der
Zeitzählung genügend weit in der Vergangenheit in vorhistorischen
Zeiten liegen. Scaliger konstruierte zunächst eine 7980 Jahre
währende Julianische Periode, indem er folgende Zyklen kombinierte:
- den 28jährigen Sonnenzyklus, in dem sich (im Julianischen Kalender)
die Kalenderdaten auf denselben Wochentagen wiederholen (im
Gregorianischen Kalender wäre dieser Zyklus 400 Jahre lang);
- den 19jährigen Metonischen Zyklus, in dem sich die Mondphasen
und Finsternisse an nahezu denselben Kalenderdaten wiederholen; und
- den 15jährigen Indiktionszyklus, der im Römischen Reich zur
Steuererhebung und Volkszählung verwendet wurde und, beginnend
mit dem 25.Dezember 312 n.Chr, zur fortlaufenden Datierung bis in
die heutige Zeit diente.
Das letzte Jahr, in dem alle drei Zyklen gemeinsam einen neuen
Durchlauf begannen, war 4713 v. Chr. Den 1. Januar dieses Jahres
legte Scaliger als Beginn seiner Zeitrechnung fest. Für die meisten
Menschen der damaligen Epoche war dieses Datum allerdings fiktiv,
da nach ihrem Glauben die Welt erst wesentlich später erschaffen
wurde. Scaliger selbst datierte die Erschaffung der Erde auf das
Jahr 3267 v.Chr.
Der Algorithmus stellt sich dann folgendermaßen dar:
Y = Jahr, M = Monat (Januar = 1, Februar = 2, etc.),
D = Tag (eventuell mit Tagesbruchteilen)
Ist M > 2 lasse Y und M unverändert.
Ist M = 1 oder M = 2 dann ist
Y = Y - 1
M = M + 13
Im Gregorianischen Kalender rechnet man weiter:
A = INT (Y/100)
B = 2 - A + INT (A/4)
Im Julianischen Kalender ist B = 0!
Das gesuchte JD ist dann:
JD = INT (365.25 * (Y + 4716))
+ INT (30.6001 * (M + 1)) + D
+ B - 1524.5
Das Programm zum Berechnen des Julianischen Datums stellt sich dann
folgendermaßen dar. Beachten Sie, daß wegen der Besonderheit
des Julianischen Datums der Tag nicht als Integer, sondern als
Gleitpunktzahl dargestellt wird. Im Programm ist noch ein zweites
Unterprogramm enthalten, das den JD wieder in unser gewohntes Datumsformat,
das Gregorianische Datum, umrechnet:
#include <stdio.h>
#include <stdlib.h>
struct datum
{
double tag;
int monat;
int jahr;
};
double julian_day(double day, int month, int year);
struct datum gregorian_date(double jday);
int main(void)
{
int tag, monat, jahr;
double jd;
struct datum dat;
printf("Tag, Monat und Jahr eingeben: ");
scanf("%d %d %d",&tag, &monat, &jahr);
jd = julian_day(1.0*tag, monat, jahr);
printf("\nJulianischer Tag fuer den %d.%d.%d = %1.2f\n",
tag, monat, jahr, jd);
dat = gregorian_date(jd);
printf("\nZurueckgerechnet: %1.0f.%d.%d\n", dat.tag, dat.monat, dat.jahr);
return 0;
}
/* Julianischer Tag (>=1):
* Gegeben: tag, monat, jahr
*
* Die gregorianische Kalenderreform wird beruecksichtigt (der Tag, der
* auf den 4. Oktober 1582 folgt ist der 15. October 1582
* Tage nach dem 15. Oktober 1582 werden als "Gregorianischer Kalender"
* bezeichnet. Der Julianische Tag beginnt um 12 Uhr GMT (Mittag).
* Um beliebige Uhrzeiten beruecksichtigen zu koennen, werden die Tage
* nicht als Integer- sondern als Gleitpunktzahlen angegeben.
*/
double julian_day(double day, int month, int year)
{
int atmp, btmp, monthp, yearp;
double ctmp;
if (month > 2)
{
monthp = month + 1;
yearp = year;
}
else
{
monthp = month + 13;
yearp = year - 1;
}
if ((year > 1582) || (year == 1582 && month >= 10)
|| (year == 1582 && month ==10 && day >= 15))
{
atmp = year / 100;
btmp = 2 - atmp + (atmp / 4);
}
else
btmp = 0;
atmp = 365.25 * yearp;
ctmp = atmp;
atmp = 30.6001 * monthp;
ctmp = ctmp + atmp;
return (ctmp + day + 1720994.5 + btmp);
}
/* gregorian_date: Umrechnung Julianischer Tag
in (Tag, Monat, Jahr) */
struct datum gregorian_date(double jday)
{
int atmp, btmp, ctmp, dtmp, etmp, gtmp, ztmp;
double ftmp;
struct datum dd;
ztmp = jday + 0.5;
ftmp = (jday + 0.5) - ztmp;
if (ztmp >= 2299161)
{
gtmp = (ztmp - 1867216.25) / 36524.25;
ctmp = gtmp / 4;
atmp = ztmp + 1 + gtmp - ctmp;
}
else
atmp = ztmp;
btmp = atmp + 1524;
ctmp = (btmp - 122.1) / 365.25;
dtmp = 365.25 * ctmp;
etmp = ((btmp - dtmp) / 30.6001);
ztmp = 30.6001 * etmp;
dd.tag = btmp - dtmp - ztmp + ftmp;
if (etmp > 13.5)
dd.monat = etmp - 13;
else
dd.monat = etmp - 1;
if (dd.monat > 2.5)
dd.jahr = ctmp - 4716;
else
dd.jahr = ctmp - 4715;
return(dd);
}
Datumsrechnung
Mit Hilfe des Julianischen Tages wir die Datumsrechnung relativ einfach.
Zuerst die wichtigste Funktion, die Schaltjahresberechnung:
Schaltjahr
#include <stdio.h>
#include <stdlib.h>
int schaltjahr(int YY);
int main(void)
{
int jahr;
printf("Jahr eingeben: ");
scanf("%d", &jahr);
if (schaltjahr(jahr))
printf("\n%d ist Schaltjahr\n", jahr);
else
printf("\n%d ist KEIN Schaltjahr\n", jahr);
return 0;
}
int schaltjahr(int yy)
/* 1, falls Schaltjahr, sonst 0 */
{
int sj;
if ((yy%400) == 0) sj = 1;
else if ((yy%100) == 0) sj = 0;
else if ((yy%4) == 0) sj = 1;
else sj = 0;
return(sj);
}
Die Funktion liefert einen Integerwert und man kann dann beispielsweise
auch die Anzahl der Tage eines Jahres berechnen:
tage_im_jahr = 365 + schaltjahr(jahr);
Wochentagsberechnung
Die Wochentagsberechnung ist absolut einfach, wenn man den Julianischen Tag hat.
Ergebnis: Wochentag 0=So, 1=Mo, 2=Di, 3=Mi, 4=Do, 5=Fr, 6=Sa:
wochentag = (Julianischer Tag + 1.5) % 7
Fur Daten nach dem 15.10.1582 gibt es noch einen andere Berechnungsweise:
/* Wochentagsberechnung aus Tag, Monat, Jahr (4-stellig) */
/* Ergebnis: Wochentag 0=So, 1=Mo, 2=Di, 3=Mi, 4=Do, 5=Fr, 6=Sa */
#include <stdio.h>
#include <stdlib.h>
int wota(int tt, int mm, int yy);
int main(void)
{
int tag, monat, jahr;
printf("Tag, Monat und Jahr eingeben: ");
scanf("%d %d %d",&tag, &monat, &jahr);
printf("\nDer Wochentag ist %d\n", wota(tag, monat, jahr));
return 0;
}
int wota(int tt, int mm, int yy)
{
int wt, y, c;
if (mm < 3)
{
mm = mm + 12;
yy = yy - 1;
}
y = yy%100;
c = yy/100;
wt = (tt + (mm+1)*13/5 + y + y/4 + c/4 -2*c)%7;
if (wt < 0) wt = wt + 7;
return(wt);
}
Jahrestag
Der Jahrestag reduziert sich auf eine effektive Zeile:
int day_of_year(double day, int month, int year)
{
return ((int) julian_day(day, month, year)
- (int) julian_day(0.0, 1, year));
}
Ebenso kann man auch ausrechen, wieviele Tage das Jahr noch hat:
days_remaining_in_year(double day, int month, int year)
{
return (365 + schaltjahr(year) - day_of_year(day, month, year));
}
Der n-te Wochentag im Monat
Oft richten sich bestimmte Termine nicht nach einem Datum, sondern nach einem
bestimmten Wochentag in der Nähe eines Datums, z. B. der erste Montag im
Monat oder für Gehaltszahlung der letzte Donnerstag des Monats.
Die Berechnung dafür liefert folgendes Unterprogramm. Gegeben wird der
Wochentag (0 = Sonntag, 1 = Montag, usw.), der wievielte Wochentag es sein
soll (1 - 5), Monat und Jahr (ab 1583).
int nth_day_of_week(int n, int day_of_week, int month, int year)
{
int atmp, btmp, ctmp, dtmp, etmp, ftmp, tmonth, tyear;
if (month > 2)
{
tmonth = month + 1;
tyear = year;
}
else
{
tmonth = month + 13;
tyear = year - 1;
}
atmp = 2.6 * tmonth;
btmp = 1.25 * tyear;
ctmp = (tyear / 100) - 7;
dtmp = 0.75 * ctmp;
etmp = (day_of_week - atmp - btmp + dtmp) % 7;
if (etmp == 0)
{
ftmp = 7;
n--;
}
else
ftmp = etmp;
return (ftmp + (n * 7));
}
Osterdatum (und bewegl. Feste)
Das christliche Osterfest ist aus dem jüdischen Passahfest abgeleitet,
das am ersten Frühlingsvollmond beginnt. Dieser Tag kann offensichtlich
auf einen beliebigen Wochentag fallen, Ostern beginnt dagegen
definitionsgemäß am einem Sonntag. Ursprünglich war die
Festlegung des Ostertermins sehr uneinheitlich geregelt in den verschiedenen
christlichen Gemeinden. Erst im 1. Konzil von Nicäa im Jahre 325 n. Chr.
einigte man sich auf die Formel, daß Ostern auf den ersten Sonntag
nach dem Frühlingsvollmond nach der
Frühjahrs-Tagundnachtgleiche fällt. Der erste
Frühlingsvollmond ist dabei der erste Vollmond, der am Tag der
Frühjahrs-Tagundnachtgleiche oder danach stattfindet.
Mit dem Beschluß von Nicäa waren aber die Schwierigkeiten nicht
endgültig beseitigt, weil die genaue Festlegung des ersten
Frühlingsvollmonds eigene Probleme mit sich brachte. Schließlich
setzte der römische Abt Dionysius Exiguus auf Veranlassung von Papst
Johannes I im Jahre 525 n. Chr. die in Alexandria übliche Rechnung durch.
Danach wird
- der Frühlingsbeginn auf den 21. März 0 Uhr festgesetzt und
- von einem gleichmäßig auf einer Kreisbahn umlaufenden Mond
ausgegangen.
Beide Annahmen sind Vereinfachungen, die zu Abweichungen von den wahren
astronomischen Gegebenheiten führen. So findet der wahre
Frühlingsbeginn etwa zwischen dem 19. März 8 Uhr und dem 21. März
20 Uhr UT statt. Berücksichtigung der wahren Mondbahn liefert Differenzen
von bis zu +/- 0.7 Tagen gegenüber einer kreisförmigen Bahn. Ferner
sind seit der Gregorianischen Kalenderreform zusätzliche
Datumsbeschränkungen zu berücksichtigen, denen zufolge Ostern
zwischen dem 22. März und dem 25. April (jeweils einschließlich)
liegen muß. Aus diesen Gründen kommt es zu Verschiebungen des
faktischen Osterdatums gegenüber dem astronomisch korrekt berechneten
Datum, die als 'Osterparadoxien' bezeichnet werden. Die letzte Paradoxie fand
im Jahre 1974 statt (Ostern war am 14. April statt am 7. April), die
nächste findet im Jahr 2000 statt (23. April statt 26. März).
Durchgeführt wird die Osterrechnung heute durch die kirchlichen
Ostertafeln (Tabellenwerke, die zu diesem Zwecke angelegt wurden) oder durch
die Osterformel von Carl Friedrich Gauß. Beide Verfahren gelten für
alle Jahre ab 532 n.Chr. Hier das Unterprogramm zu Berechnung des Osterdatums
und ein Testprogramm dazu.
/* Berechnung des Osterdatums nach C. F. Gauss */
#include <stdio.h>
#include <stdlib.h>
struct datum
{
int tag;
int monat;
int jahr;
};
struct datum ostern(int yy);
int main(void)
{
int jahr;
struct datum dat;
printf("Jahr eingeben: ");
scanf("%d", &jahr);
dat = ostern(jahr);
printf("\nOstern faellt %d auf den %d.%d.\n",dat.jahr, dat.tag, dat.monat);
return 0;
}
struct datum ostern(int year)
/* Osterdatum */
{
int atmp, btmp, ctmp, dtmp, etmp, ftmp,
gtmp, htmp, itmp, ktmp, ltmp, mtmp;
struct datum dd;
atmp = year % 19;
btmp = year / 100;
ctmp = year % 100;
dtmp = btmp / 4;
etmp = btmp % 4;
ftmp = (btmp + 8) / 25;
gtmp = (btmp - ftmp + 1) / 3;
htmp = ((19 * atmp) + btmp - dtmp - gtmp + 15) % 30;
itmp = ctmp / 4;
ktmp = ctmp % 4;
ltmp = (32 + (2 * etmp) + (2 * itmp) - htmp - ktmp) % 7;
mtmp = (atmp + (11 * htmp) + (22 * ltmp)) / 451;
dd.monat = (htmp + ltmp - (7 * mtmp) + 114) / 31;
dd.tag = ((htmp + ltmp - (7 * mtmp) + 114) % 31) + 1;
dd.jahr = year;
return(dd);
}
Die anderen beweglichen Feste lassen sich aus dem Osterdatum ableiten:
- Rosenmontag -48 Tage
- Faschinsdienstag -47 Tage
- Aschermittwoch -46 Tage
- Palmsonntag -7 Tage
- Gründonnerstag -3 Tage
- Karfreitag -2 Tage
- Christi Himmelfahrt +39 Tage
- Pfingstsonntag +49 Tage
- Fronleichnam +60 Tage
Das Vorgehen ist ganz einfach. Man rechnet das Osterdatum in den Julianischen
Tag um, addiert die o. a. Verschiebung und rechnet das Ergebnis wieder ins
Gregorianische Datum um.
Datums- und Zeitfunktionen
Die ANSI-C-Standard-Bibliothek stellt Funktionen zur Verfügung, die einen
Zugriff zur Systemuhr ermöglichen:
- Funktionen zur Ermittlung von Zeiten und Zeitdifferenzen
- Funktionen zur Umwandlung von Zeitdarstellungen
- Funktionen zur Darstellung von Zeiten als Strings
Es werden drei verschiedenen Zeitdarstellungen verwendet:
- Prozessorzeit (processor time), ausgedrückt in Systemzeit-Perioden.
- Kalenderzeit (calendar time), gemäß dem Gregorianischen Kalender,
in einer implementierungsspezifischen unstrukturierten Darstellung.
- Ortszeit (local time), die für eine spezifische Zeitzone geltende
Kalenderzeit, gegebenenfalls modifiziert als Sommerzeit (daylight saving time),
in einer strukturierten Darstellung.
Die entsprechenden Funktionsdefinitionen befinden sich in der Standard-Header-Datei
<time.h>. Diese ist daher bei Verwendung der Funktionen mittels #include
<time.h> einzubinden. In <time.h> sind außerdem definiert:
Konstante CLK_TCK |
Anzahl der Perioden (ticks) der Systemzeit pro Sekunde |
Typ clock_t |
Arithmetischer Datentyp zur Darstellung der Zeit
|
Typ time_t |
Arithmetischer Datentyp zur Darstellung der Zeit
|
Typ tm |
Structure-Typ zur Darstellung der Kalenderzeit
|
Der Typ tm muß wenigstens die folgenden Komponenten enthalten :
int tm_sec; /* Sekunden nach der Minute [0 .. 59] */
int tm_min; /* Minuten nach der Stunde [0 .. 59] */
int tm_hour; /* Stunden seit Mitternacht [0 .. 23] */
int tm_mday; /* Tag des Monats [0 .. 31] */
int tm_mon; /* Monate seit Januar [0 .. 11] */
int tm_year; /* Jahre seit 1900 */
int tm_wday; /* Tage seit Sonntag [0 .. 6] */
int tm_yday; /* Tage seit 1.Januar [0 ..365] */
int tm_isdst; /* Sommerzeit-Flag */
Für den Wert des Sommerzeit-Flags tm_isdst gilt:
- >0 wenn die Sommerzeit in Kraft ist
- =0 wenn die Sommerzeit nicht in Kraft ist
- <0 wenn die Information nicht verfügbar ist
Funktionen zur Ermittlung von Zeiten und Zeitdifferenzen
clock_t clock(void); |
Ermittlung der Prozessorzeit, die seit Programmstart vergangen ist, in
Systemzeit-Perioden (ticks).
clock()/CLK_TCK ist die Zeit in Sekunden.
Funktionswert = (clock_t)-1, wenn die Prozessorzeit nicht verfügbar ist.
|
time_t time(time_t *timer); |
Ermittlung der Kalenderzeit in einer implementierungsspezifischen Darstellung.
Falls timer!=NULL wird der Funktionswert auch *timer zugewiesen.
Funktionswert = (time_t)-1, wenn Kalenderzeit nicht verfügbar ist.
|
double difftime(time_t t2, time_t t1); |
Bildung der Zeitdifferenz t2 - t1 ausgedrückt in Sekunden (t2 und t1 enthalten
Zeiten in implementierungsspezifischer Darstellung!)
|
Funktionen zur Umwandlung von Zeitdarstellungen
struct tm *gmtime(const time_t *tp); |
Umwandlung der in implementierungsspezifischer Darstellung vorliegenden
Kalenderzeit *tp in eine strukturierte Darstellung der Coordinated Universal Time (UTC).
Falls die UTC nicht ermittelt werden kann, ist der Funktionswert = NULL
|
struct tm *localtime(const time_t *tp); |
Umwandlung der in implementierungsspezifischer Darstellung vorliegenden Kalenderzeit
*tp in eine strukturierte Darstellung der Ortszeit.
|
time_t mktime(struct tm *tptr); |
Umwandlung der in strukturierter Darstellung vorliegenden Ortszeit *tptr
in die implementierungsspezifische Darstellung der Kalenderzeit.
Die Werte der einzelnen Strukturkomponenten müssen nicht normiert sein. Die Funktion führt zusätzlich ihre Normierung durch und berechnet die Werte für die Komponenten tm_wday und tm_yday.
Falls keine darstellbare Kalenderzeit ermittelt werden kann, erzeugt die Funktion
den Wert (time_t)-1.
|
Funktionen zur Darstellung von Zeiten als Strings
char *asctime(const struct tm *tptr); |
Umwandlung der in strukturierter Darstellung vorliegenden Ortszeit *tptr in
einen String der folgenden Form:
"Sun Apr 14 11:23:22 1991\n\0"
Der Funktionswert ist Pointer auf diesen String.
|
char *ctime(const time_t *tp); |
Umwandlung der in implementierungsspezifischer Darstellung vorliegenden
Kalenderzeit *tp in einen String der folgenden Form:
"Sun Apr 14 11:23:22 1991\n\0"
Der Funktionswert ist Pointer auf diesen String.
ctime(tp) ist äquivalent zu asctime(localtime(tp)).
|
size_t strftime( char *s, size_t smax, const char *fmt, const struct tm *tptr); |
Ablage von in *tptr enthaltenen Zeit- und Datumsinformationen in den String s
gemäß den im String fmt enthaltenen Formatspezifikationen.
Jeder sonstiger Text in fmt wird nach s übernommen. Der String s darf
maximal smax Zeichen lang werden.
Funktionswert:
- Anzahl der in s abgelegten Zeichen ohne abschließendes '\0'),
wenn diese <=smax ist.
- 0, wenn s länger als smax Zeichen werden würde.
Der Inhalt von s ist in diesem Fall undefiniert.
Format-Spezifier für strftime():
%a abgekürzter Name des Wochentags
%A ausgeschriebener Name des Wochentags
%b abgekürzter Name des Monats
%B ausgeschriebener Name des Monats
%c geeignete Darstellung der lokalen Zeit (Datum und Zeit)
%d Tag des Monats als Dezimalzahl (01 .. 31)
%H Stunde als Dezimalzahl (24-Std-Uhr) (00 .. 23)
%I Stunde als Dezimalzahl (12-Std-Uhr) (01 .. 12)
%j Tag des Jahres als Dezimalzahl (001 .. 386)
%m Monat als Dezimalzahl (01 .. 12)
%M Minute als Dezimalzahl (00 .. 59)
%p PM oder AM (oder landesspezifisches Žquivalent)
%S Sekunde als Dezimalzahl (00 .. 59)
%U Woche des Jahres dezimal (Sonntag ist 1. Tag der Woche) (00 .. 53)
%w Wochentag als Dezimalzahl (Sonntag = 0) (0 .. 6)
%W Woche des Jahres dezimal(Montag ist 1. Tag der Woche) (00 .. 53)
%x geeignete Darstellung des lokalen Datums
%X geeignete Darstellung der lokalen Zeit
%y (Jahr - Jahrhundert) als Dezimalzahl (00 .. 99)
%Y Jahr als Dezimalzahl (einschließlich Jahrhundert)
%Z Name der Zeitzone, falls ein Name existiert
%% Das Zeichen %
|
|
|
|