mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Feiertage berechnen


Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Bin auf der Suche nach einer Funktion, welche mir die gesetzlichen 
Feiertage anhand des Jahres berechnen.

Ostern habe ich nach der Gauss'schen Osterformel bereits berechnet, ist 
soweit auch kein Problem.

http://www.a-m-i.de/tips/datetime/datetime.php

Hat aber jemand eine Idee, wie man anhand des Osterdatums elegant auf 
zBsp. Pfingstsonntag schliessen kann (49Tage nach Ostern).

Mit einer höheren Programmiersprache (Delphi, C# usw.) kein Problem, 
hier hat man die entsprechenden Funktionen, um Daten zu berechnen.

Wie aber mach ich das am besten mit meinem CCS- Pic Compiler?

Ist ziemlich mühsam das ganze mit if-Anweisungen durch zu kauen.

Bin für Tip's sehr dankbar.

Gruss Andy

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Hat aber jemand eine Idee, wie man anhand des Osterdatums elegant auf
>zBsp. Pfingstsonntag schliessen kann (49Tage nach Ostern).

49/7=7 Rest 0.

Hm.. vielleicht exakt 7Wochen später?

Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gesucht:
Compiler der folgenden Ausdruck auswerten kann:
Pfingsten = 23.03.2008 + 7Wochen; :-)

Autor: Frank Link (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Andy
schau Dir mal diesen Delphi-Code an:

http://www.delphi-fundgrube.de/files/feiertg.txt

Den setzen wir ein, um alle möglichen Feiertage zu berechnen.

Gruß
Frank

Autor: Ulli (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Datum in Absolutzahl von Tagen seit Jahresbeginn umrechnen dann 49 Tage 
addieren und Absolutzahl wieder in Datum umrechen.

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Pfingsten = 23.03.2008 + 7Wochen; :-)

Hm..

  23.   03.   2008
 +49
----------------
  72.   03.   2008
 -31   + 1           ( da März )
----------------
  41.   04.   2008   (weil größer als 30[April] ):
 -30   + 1           ( da April )
----------------
  11.   05.   2008

Denkbar?

Autor: spess53 (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Ich habe mir für Delphi mal die Routinen im Anhang ausgedacht.
Vielleicht hilft es.

MfG Spess

Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Danke Leute für die Infos!

@Frank: Sowas hab ich auch gefunden, nur werden dort immer spezielle 
Funktionen (Encodedate usw.) verwendet, welches das ganze natürlich zum 
Kinderspiel werden lassen.

@Matthias: Funktioniert sicher auch, wird aber glaub ich doch recht 
aufwändig, wenn es für alle Feiertage gemacht werden muss.

Der Vorschlag von Ulli scheit ziemlich universell zu sein, werd ich mal 
versuchen:

Hier mal der erste Teil. Datum in Absolutzahl von Tagen seit 
Jahresbeginn umrechnen:

[c]

bool istEinSchaltjahr(const UINT uJahr)
{
  // Die Regel lautet: Alles, was durch 4 teilbar ist, ist ein 
Schaltjahr.
  // Es sei denn, das Jahr ist durch 100 teilbar, dann ist es keins.
  // Aber wenn es durch 400 teilbar ist, ist es doch wieder eins.

  if ((uJahr % 400) == 0)
    return true;
  else if ((uJahr % 100) == 0)
    return false;
  else if ((uJahr % 4) == 0)
    return true;

  return false;
}

// -----------------------

short getAnzahlTageImMonat(const UINT uMonat, const UINT uJahr)
{
  // 
ungült,Jan,Feb,Mrz,Apr,Mai,Jun,Jul,Aug,Sep,Okt,Nov,Dez
  int arrTageImMonat[13] = {  0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 
30, 31 };

  if (uMonat == 2)
  {
    // Februar: Schaltjahr unterscheiden
    if (istEinSchaltjahr(uJahr))
      return 29;
    else
      return 28;
  }

  if ((uMonat >= 1) && (uMonat <= 12))
    return arrTageImMonat[uMonat];
  else
  {
    _ASSERT(0); // ungültiger Monat !
    return 0;
  }
}

// -----------------------

short getTagDesJahres(const UINT uTag, const UINT uMonat, const UINT 
uJahr)
{
  // Der wievielte Tag des Jahres ist dieser Tag
  if ((uMonat == 0) || (uMonat > 12))
  {
    _ASSERT(0);
    return -1;
  }

  UINT uLokalTag = uTag;
  UINT uLokalMonat = uMonat;

  while (uLokalMonat > 1)
  {
    uLokalMonat--;
    uLokalTag += getAnzahlTageImMonat(uLokalMonat, uJahr);
  }

  return uLokalTag;
}

[-c]

Hat vielleicht jemand gerade C-Source zur Hand, um anhand einer 
Absolutzahl ein Datum zu berechnen? Bin nicht gerade der geborene 
Mathematiker.

Würde das ganze bei Erfolg in die Codesammlung stellen.

Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo spess53

Sieht gut aus! Werd ich mir für die Delphi Programmierung auch mal 
anschauen.

Im Moment geht es mir aber wie gesagt um ANCI-C Code, welcher ich für 
verschiedene uC C- Compiler verwenden kann.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

Mir ging es weniger um Delphi. Aber ich habe damals einige Zeit 
verbracht, die Beziehungen zwischen den Feiertagen heraus zu bekommen. 
Die Osterberechnung stammt z.B. aus einem Brockhaus von 1936.

MfG Spess

Autor: Frank Link (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hier mal der Funktionscode für EncodeDate in Delphi.

[c]
  MonthDays: array [Boolean] of TDayTable =
    ((31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31),
     (31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31));


function IsLeapYear(Year: Word): Boolean;
begin
  Result := (Year mod 4 = 0) and ((Year mod 100 <> 0) or (Year mod 400 = 
0));
end;

function TryEncodeDate(Year, Month, Day: Word; out Date: TDateTime): 
Boolean;
var
  I: Integer;
  DayTable: PDayTable;
begin
  Result := False;
  DayTable := @MonthDays[IsLeapYear(Year)];
  if (Year >= 1) and (Year <= 9999) and (Month >= 1) and (Month <= 12) 
and
    (Day >= 1) and (Day <= DayTable^[Month]) then
  begin
    for I := 1 to Month - 1 do Inc(Day, DayTable^[I]);
    I := Year - 1;
    Date := I * 365 + I div 4 - I div 100 + I div 400 + Day - DateDelta;
    Result := True;
  end;
end;


procedure DecodeDate(const DateTime: TDateTime; var Year, Month, Day: 
Word);
var
  Dummy: Word;
begin
  DecodeDateFully(DateTime, Year, Month, Day, Dummy);
end;

function DecodeDateFully(const DateTime: TDateTime; var Year, Month, 
Day, DOW: Word): Boolean;
const
  D1 = 365;
  D4 = D1 * 4 + 1;
  D100 = D4 * 25 - 1;
  D400 = D100 * 4 + 1;
var
  Y, M, D, I: Word;
  T: Integer;
  DayTable: PDayTable;
begin
  T := DateTimeToTimeStamp(DateTime).Date;
  if T <= 0 then
  begin
    Year := 0;
    Month := 0;
    Day := 0;
    DOW := 0;
    Result := False;
  end else
  begin
    DOW := T mod 7 + 1;
    Dec(T);
    Y := 1;
    while T >= D400 do
    begin
      Dec(T, D400);
      Inc(Y, 400);
    end;
    DivMod(T, D100, I, D);
    if I = 4 then
    begin
      Dec(I);
      Inc(D, D100);
    end;
    Inc(Y, I * 100);
    DivMod(D, D4, I, D);
    Inc(Y, I * 4);
    DivMod(D, D1, I, D);
    if I = 4 then
    begin
      Dec(I);
      Inc(D, D1);
    end;
    Inc(Y, I);
    Result := IsLeapYear(Y);
    DayTable := @MonthDays[Result];
    M := 1;
    while True do
    begin
      I := DayTable^[M];
      if D < I then Break;
      Dec(D, I);
      Inc(M);
    end;
    Year := Y;
    Month := M;
    Day := D + 1;
  end;
end;

[c]

Diese Routinen sollten sich eigentlich sehr einfach in C umsetzen 
lassen.

Gruß
Frank

function EncodeDate(Year, Month, Day: Word): TDateTime;
begin
  if not TryEncodeDate(Year, Month, Day, Result) then
    ConvertError(@SDateEncodeError);
end;

Autor: Frank Link (franklink)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry, copy und Paste Fehler.

Autor: Andy (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke, werd ich mir mal anschauen...

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.