Osterfunktion mit Jahr als Parameter

Konzeptionelles, Technisches, Termine, Fragen zum Hersteller usw.

Moderator: Moderatoren

Antworten
UliTs
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2828
Registriert: Fr, 10. Feb 2006 9:51
Wohnort: Aachen
Hat sich bedankt: 259 Mal
Danksagung erhalten: 12 Mal
Kontaktdaten:

Osterfunktion mit Jahr als Parameter

Beitrag 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
Zuletzt geändert von UliTs am Do, 05. Jan 2023 13:48, insgesamt 1-mal geändert.
-------
Mitglied XuG Cologne
Mitglied XuG Osnabrück
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: Osterfunktion mit Jahr als Parameter

Beitrag 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. 8)

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
Herzlich,
Tom
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: Osterfunktion mit Jahr als Parameter

Beitrag von Tom »

Siehe auch hier: https://www.xbaseforum.de/viewtopic.php?p=54946#p54946
Da wird der Rest ebenfalls erklärt. Bisschen runterscrollen.
Herzlich,
Tom
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14641
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 87 Mal
Kontaktdaten:

Re: Osterfunktion mit Jahr als Parameter

Beitrag 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
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Marcus Herz
1000 working lines a day
1000 working lines a day
Beiträge: 851
Registriert: Mo, 16. Jan 2006 8:13
Wohnort: Allgäu
Hat sich bedankt: 39 Mal
Danksagung erhalten: 192 Mal
Kontaktdaten:

Re: Osterfunktion mit Jahr als Parameter

Beitrag 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
Gruß Marcus

Erkenne, was du findest, dann weißt du, wonach du gesucht hast
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14641
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 87 Mal
Kontaktdaten:

Re: Osterfunktion mit Jahr als Parameter

Beitrag 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
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Marcus Herz
1000 working lines a day
1000 working lines a day
Beiträge: 851
Registriert: Mo, 16. Jan 2006 8:13
Wohnort: Allgäu
Hat sich bedankt: 39 Mal
Danksagung erhalten: 192 Mal
Kontaktdaten:

Re: Osterfunktion mit Jahr als Parameter

Beitrag 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;
Gruß Marcus

Erkenne, was du findest, dann weißt du, wonach du gesucht hast
Benutzeravatar
Jan
Marvin
Marvin
Beiträge: 14641
Registriert: Fr, 23. Sep 2005 18:23
Wohnort: 49328 Melle
Hat sich bedankt: 21 Mal
Danksagung erhalten: 87 Mal
Kontaktdaten:

Re: Osterfunktion mit Jahr als Parameter

Beitrag 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
Mitglied der XUG Osnabrück
Mitglied der XUG Berlin/Brandenburg
Mitglied des Deutschsprachige Xbase-Entwickler e. V.
Benutzeravatar
Tom
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 9345
Registriert: Do, 22. Sep 2005 23:11
Wohnort: Berlin
Hat sich bedankt: 100 Mal
Danksagung erhalten: 359 Mal
Kontaktdaten:

Re: Osterfunktion mit Jahr als Parameter

Beitrag von Tom »

Die Formel ist in die Funktion eingearbeitet, die ich weiter oben gepostet habe. https://www.xbaseforum.de/viewtopic.php ... 32#p143632
Herzlich,
Tom
UliTs
Der Entwickler von "Deep Thought"
Der Entwickler von "Deep Thought"
Beiträge: 2828
Registriert: Fr, 10. Feb 2006 9:51
Wohnort: Aachen
Hat sich bedankt: 259 Mal
Danksagung erhalten: 12 Mal
Kontaktdaten:

Re: Osterfunktion mit Jahr als Parameter

Beitrag 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;
-------
Mitglied XuG Cologne
Mitglied XuG Osnabrück
Benutzeravatar
nightcrawler
1000 working lines a day
1000 working lines a day
Beiträge: 650
Registriert: Di, 24. Apr 2012 16:33
Wohnort: 72184 Weitingen
Hat sich bedankt: 3 Mal
Danksagung erhalten: 96 Mal
Kontaktdaten:

Re: Osterfunktion mit Jahr als Parameter

Beitrag 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:

Code: Alles auswählen

SELECT jde.Ostersonntag(2017) FROM SYSTEM.IOTA;
--
Joachim
Joachim Dürr Softwareengineering
https://www.jd-engineering.de
Antworten