Seite 1 von 1
Osterfunktion mit Jahr als Parameter
Verfasst: Do, 05. Jan 2023 13:40
von UliTs
Hallo allerseits,
bestimmt hat schon jemand so etwas (ähnliches) programmiert. Ostern (und diverse andere kirchliche Feiertage, ist der Abstand zu Ostern immer gleich?) hat jedes Jahr ein anderes Datum. Ich könnte eine Funktion, die das Datum in Abhängigkeit vom Jahr als Rückgabewert hat gut brauchen:
Code: Alles auswählen
function OsterSonntag( pJahr )
local dDatum
...
return( dDatum )
Dabei würde es in meinem Fall reichen, wenn die Funktion in diesem Jahrhundert einwandfrei funktioniert.
Hat jemand so etwas schon geschrieben und könnte es hier veröffentlichen oder alternativ mir per PN zur Verfügung stellen?
Vielleicht Jan?
Edit:
Habe gerade im Delphiforum eine ganz gute Seite gefunden, mit der man es (vermutlich innerhalb weniger Minuten) selbst programmieren kann:
http://www.arndt-bruenner.de/mathe/scripts/osterdatum.htm
Uli
Re: Osterfunktion mit Jahr als Parameter
Verfasst: Do, 05. Jan 2023 13:47
von Tom
Keine Ahnung, wo ich diesen steinalten, aber nach wie vor funktionierenden Code herhabe. Man ruft die Funktion mit allen Tagesdaten vom Beginn bis zum Ende des Jahres auf. Feste Feiertage sind ja einfach. Ostern hat irgendwas mit den Mondphasen und so zu tun.
Code: Alles auswählen
FUNCTION BeweglicheFeiertage(ft_datum)
LOCAL ft_jahr := Year(ft_datum), ft_k1, ft_k2, ft_k3, ft_k4, ft_tt, ft_mm, ft_text := ''
ft_k1:=INT(ft_jahr/100)-INT(ft_jahr/400)+4
ft_k2:=ft_k1-INT(ft_jahr/300)+11
ft_k3:=MOD(MOD(ft_jahr,19)*19+ft_k2,30)
ft_k4:=MOD(MOD(ft_jahr,4)*2+(4*ft_jahr)+(6*ft_k3)+ft_k1,7)+ft_k3-9
IF ft_k4<1
ft_tt:=31+ft_k4
ft_mm:=3
ELSE
IF((ft_k4==26) .OR. ((ft_k3==28) .AND. (ft_k4==25) .AND. ;
(11*MOD(ft_k2+1,30)<19)))
ft_k4:=ft_k4-7
ENDIF
ft_tt:=ft_k4
ft_mm:=4
ENDIF
ft_ostern:= CTOD(STR(ft_tt,2,0)+"."+STR(ft_mm,2,0)+"."+ ;
RIGHT(STR(YEAR(ft_datum)),4))
IF ft_datum==ft_ostern-2
ft_text:="Karfreitag"
ELSEIF ft_datum==ft_ostern
ft_text:="Ostersonntag"
ELSEIF ft_datum==ft_ostern+1
ft_text:="Ostermontag"
ELSEIF ft_datum==ft_ostern+49
ft_text:="Pfingstsonntag"
ELSEIF ft_datum==ft_ostern+50
ft_text:="Pfingstmontag"
ELSEIF ft_datum==ft_ostern+39
ft_text:="Christi Himmelfahrt"
ELSEIF ft_datum==ft_ostern+60
ft_text:="Fronleichnam"
ENDIF
RETURN ft_text
Re: Osterfunktion mit Jahr als Parameter
Verfasst: Do, 05. Jan 2023 13:49
von Tom
Siehe auch hier:
https://www.xbaseforum.de/viewtopic.php?p=54946#p54946
Da wird der Rest ebenfalls erklärt. Bisschen runterscrollen.
Re: Osterfunktion mit Jahr als Parameter
Verfasst: Do, 05. Jan 2023 13:50
von Jan
Hallo Uli,
öhm ... wie kommst Du denn jetzt ausgerechnt auf mich?
Aber Du hast recht - ich habe genau diese Funktion. Ergänzt um diverse andere Funktionen, die einen ganzen Schwung Feiertage brechnen. Die sind ja teilweise fixe Tage, teilweise abhängig von Ostern, oder teilweise nach festen Rgeln (wie letzter Donnerstag im Oktober, was jetzt fiktiv ist).
Code: Alles auswählen
FUNCTION feiertag(nJahr, lGregorianisch)
LOCAL nGold := 0
LOCAL nJahrhundert := 0
LOCAL nCorx := 0
LOCAL nCorz := 0
LOCAL nSonntag := 0
LOCAL nEpakte := 0
LOCAL nMond := 0
LOCAL nMonat := 0
LOCAL nTag := 0
UnUsed(lGregorianisch)
nJahr := Val(Var2Char(nJahr))
IF nJahr > 1582
* <<nGold>> ist die Goldene Nummer des Jahres im 19 Jahres Metonic Zyklus
nGold := nJahr % 19 + 1
* <<nJahrhundert>> Jahrhundert
nJahrhundert := INT (nJahr / 100) + 1
* Korrektur:
* <<nCorx>> ist die Anzahl der Jahre in denen Schaltjahre aufgehoben werden um mit der Sonne konform zu bleiben
nCorx := Int((3 * nJahrhundert) / 4 - 12)
* <<nCorz>> ist eine spezielle Korrektur um Ostern mit dem Mondumlauf zu synchronisieren
nCorz := Int((8 * nJahrhundert + 5) / 25 - 5)
* <<nSonntag>> Sonntag finden
nSonntag := Int((5 * nJahr) / 4 - nCorx - 10)
* Epakte <<nEpakte>> finden (Erscheinen des Vollmondes spezifizieren)
nEpakte = Int((11 * nGold + 20 + nCorz - nCorx) % 30)
IF nEpakte < 0
nEpakte += 30
ENDIF
IF ((nEpakte = 25) .AND. (nGold > 11)) .OR. (nEpakte = 24)
++nEpakte
ENDIF
* Vollmond finden - der <<nMond>>te des März ist ein "kalendarischer" Vollmond
nMond := 44 - nEpakte
IF nMond < 21
nMond += 30
ENDIF
* Zum Sonntag
nMond := Int(nMond + 7 - ((nSonntag + nMond) % 7))
* Monat und Tag erhalten
IF nMond > 31
nMonat := 4
nTag = nMond - 31
ELSE
nMonat := 3
nTag := nMond
ENDIF
ENDIF
RETURN CToD(Right("00" + LTrim(Str(Int(nTag))), 2) + "." + ;
Right("00" + LTrim(Str(nMonat)), 2) + "." + ;
Str(nJahr, 4))
Jan
Re: Osterfunktion mit Jahr als Parameter
Verfasst: Do, 05. Jan 2023 14:51
von Marcus Herz
Es gibt da eine Formel von gauss. Bin nächste Woche wieder im Büro. Dann kann ich die reinstellen. Hab's als xbase Code und SQL Funktion
Re: Osterfunktion mit Jahr als Parameter
Verfasst: Do, 05. Jan 2023 14:57
von Jan
Marcus,
wenn ich mich recht erinnere ist mein Code nach Gauss (ist schon ewig her das ich die gebaut hatte, so genau weiß ich das nicht mehr)
Jan
Re: Osterfunktion mit Jahr als Parameter
Verfasst: Mo, 09. Jan 2023 10:28
von Marcus Herz
Witzig:
Es gibt tatsächlich mehrere Versionen der Gausschen Formel. Jans Version bezieht sich auf die 2. Erweiterung, meine auf das Original. Beide kommen aber zum selben Ergebnis.
Hier noch die SQL Funktion für ADS:
Code: Alles auswählen
CREATE FUNCTION Ostern
(
jahr INTEGER
)
RETURNS DATE
BEGIN
declare @x integer;
declare @d integer;
declare @e integer;
declare @off1 integer;
declare @off2 integer;
declare @monat integer;
@Off1 = 0;
@Off2 = 0;
@x = jahr / 100 - 16;
if @x = 1 then
@Off1 = 22;
@Off2 = 2;
elseif @x = 2 then
@Off1 = 23;
@Off2 = 3;
elseif @x = 3 then
@Off1 = 23;
@Off2 = 4;
elseif @x = 4 or @x = 5 then
@Off1 = 24;
@Off2 = 5;
elseif @x = 6 then
@Off1 = 24;
@Off2 = 6;
elseif @x = 7 then
@Off1 = 25;
end if;
@d = ((19 * (jahr % 19) + @off1) % 30);
@e = ((2 * (jahr % 4) + 4 * (jahr % 7) + 6 * @d + @off2) % 7);
@off1 = @d + @e;
if @off1 < 10 then
@off1 = @off1 + 22;
@Monat = 3;
else
@Monat = 4;
@off1 = @off1 - 9;
if @off1 = 26 then
@off1 = 19;
elseif ( @off1 = 25 and @d = 28 and @e = 6 and (jahr % 19) = 10 ) then
@off1 = 18;
end if;
end if;
RETURN cast(CREATETIMESTAMP( jahr, @monat, @off1, 12,0,0,0 ) AS SQL_DATE);
END;
Re: Osterfunktion mit Jahr als Parameter
Verfasst: Mo, 09. Jan 2023 10:31
von Jan
Hallo Marcus,
mit den beiden Erweiterungen hatte Carl Friedrich Gauß ja mehr oder weniger seltene Ausnahmen mit eingebaut. Ob die wirklich jeder braucht sei mal dahin gestellt. Aber ich brauche die unbedingt.
Jan
Re: Osterfunktion mit Jahr als Parameter
Verfasst: Mo, 09. Jan 2023 11:40
von Tom
Die Formel ist in die Funktion eingearbeitet, die ich weiter oben gepostet habe.
https://www.xbaseforum.de/viewtopic.php ... 32#p143632
Re: Osterfunktion mit Jahr als Parameter
Verfasst: Mo, 09. Jan 2023 11:56
von UliTs
Dann hier auch noch die Delphi-Version, die ich aus Euren Lösungen geschrieben habe
.
Code: Alles auswählen
function OsterSonntag( nJahr: integer ): TDate;
var k1,k2,k3,k4,nTag,nMonat: integer;
var dOsterSonntag: TDate;
begin
k1 := (nJahr div 100) - (nJahr div 400) + 4;
k2 := k1 - (nJahr div 300) + 11;
k3 := (( nJahr mod 19 ) * 19 + k2) mod 30;
k4 := (( (nJahr mod 4) * 2 + (4*nJahr) + (6*k3) + k1 ) mod 7) + k3 - 9;
if k4<1 then begin
nTag := 31 + k4;
nMonat := 3;
end else begin
if (k4=26) or ((k3=28) and (k4=25) and ((11 * (k2+1 mod 30)) < 19)) then begin
k4 := k4 - 7;
end;
nTag := k4;
nMonat := 4;
end;
dOsterSonntag := EncodeDate( nJahr,nMonat,nTag );
Result := dOsterSonntag;
end;
Re: Osterfunktion mit Jahr als Parameter
Verfasst: Do, 12. Jan 2023 16:30
von nightcrawler
In Willingen habe ich diese Funktion (ADS SQL) vorgestellt. Nur zur Vollständigkeit.
Code: Alles auswählen
CREATE FUNCTION jde.Ostersonntag(jahr INTEGER) RETURNS Date
BEGIN
DECLARE a INTEGER, b INTEGER, c INTEGER, d INTEGER, e INTEGER, f INTEGER;
DECLARE ts TIMESTAMP;
a = Mod(jahr,19);
b = Jahr/100;
c = (8*b+13)/25-2;
d = b-(Jahr/400)-2;
e = MOD(19*a+MOD(15-c+d,30),30);
IF e=28 THEN
IF a>10 THEN
e=27;
END;
ELSEIF e=29 THEN
e=28;
END;
f = MOD(d+6*e+2*MOD(jahr,4)+4*MOD(jahr,7)+6,7);
ts = CREATETIMESTAMP(jahr,3,1,0,0,0,0);
ts = TIMESTAMPADD(SQL_TSI_DAY,e+f+21,ts);
RETURN CAST(ts AS SQL_DATE);
END;
Anwendung: