Berechnung der Wochennummer

Ich musste feststellen, dass es gar nicht so einfach ist, die Wochennummer zu berechnen.
Im Internet findet man ja haufenweise Funktionen zur Berechnung, aber viele davon sind zu einfach aufgebaut und berücksichtigen nicht die Sonderfälle.
Da ich für meine Wetterstation aber die korrekte Wochennummer wollte, habe ich mal ein paar Funktionen geschrieben, die die ISO8601 (die deutschen/europäischen Regeln) berücksichtigen:

/*  Daten mit Grenzwerten zum testen der Funktionen:
 *  29.12.2014 = ist ein Montag und faellt bereits in die 1. Woche des naechsten Jahres
 *  31.12.2015 = in dem Jahr gab es eine 53. Woche
 *  31.12.2016 = Tag des Jahres wird mit 366 korrekt berechnet (Schaltjahr)
 *  01.01.2017 = ist ein Sonntag und faellt noch in die 52. Woche des Vorjahres
*/
uint16_t year = 2014;
uint8_t month = 12;
uint8_t day = 29;
const char WeekDays[][3] = {"Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"}; // Abkuerzungen der Wochentage

void setup() {
  Serial.begin(115200);
  Serial.println(F("Berechnung nach ISO 8601"));
  
  Serial.print(F("Datum: "));
  Serial.print(day);
  Serial.print(".");
  Serial.print(month);
  Serial.print(".");
  Serial.println(year);

  uint8_t wd = GetWeekday(year, month, day);        // 1 = Mo, 2 = Di, 3 = Mi, 4 = Do, 5 = Fr, 6 = Sa, 7 = So
  Serial.print(F("Wochentag: "));
  Serial.println(WeekDays[wd - 1]);
  
  uint16_t doy = GetDayOfYear(year, month, day);    // den Tag des Jahres berechnen
  Serial.print(F("Tag des Jahres: "));
  Serial.println(doy);
  
  uint8_t WeekNr = GetWeekNumber(year, month, day); // die Wochennummer berechnen
  Serial.print(F("Wochennummer: "));
  Serial.println(WeekNr);

  bool LeapYear = IsLeapYear(year);                 // berechnen, ob das Jahr ein Schaltjahr ist
  Serial.print(F("Schaltjahr: "));
  Serial.println(LeapYear ? F("Ja") : F("Nein"));
}

void loop() {

}

/***** Den Wochentag nach ISO 8601 (1 = Mo, 2 = Di, 3 = Mi, 4 = Do, 5 = Fr, 6 = Sa, 7 = So) berechnen *****/
uint8_t GetWeekday(uint16_t y, uint8_t m, uint8_t d) {
  static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
  y -= m < 3;
  uint8_t wd = (y + y / 4 - y / 100 + y / 400 + t[m - 1] + d) % 7;
  return (wd == 0 ? 7 : wd);
}

/***** Die Wochennummer nach ISO 8601 berechnen *****/
uint8_t GetWeekNumber(uint16_t y, uint8_t m, uint8_t d) {
  bool LeapYear;
  uint16_t doy = GetDayOfYear(y, m, d);  // Anzahl der Tage im Jahr ermitteln
  uint8_t wd = GetWeekday(y, m, d);      // Wochentag ermitteln
  uint8_t wnr = (doy - wd + 7) / 7;     // die Wochennummer berechnen
  switch (wnr) {
    case 0:                              // wenn die Wochennummer Null ergibt, dann liegt der Tag am Anfang des Jahres (1. Sonderfall)
      wd = GetWeekday(y - 1, 12, 31);    // den letzten Wochentag aus dem Vorjahr ermitteln
      LeapYear = IsLeapYear(y - 1);      // ermitteln, ob es sich beim Vorjahr um ein Schaltjahr handelt
      break;                             // und nach dem Switch weitermachen...
    case 52:                             // wenn die Wochennummer 52 ergibt, dann liegt der Tag am Ende des Jahres (2. Sonderfall)
      wd = GetWeekday(y, 12, 31);        // den letzten Wochentag aus diesem Jahr ermitteln
      LeapYear = IsLeapYear(y);          // ermitteln, ob es sich bei diesem Jahr um ein Schaltjahr handelt
      break;                             // und nach dem Switch weitermachen...
    default:                             // in den anderen Faellen kann die Funktion
      return wnr;                        // hier verlassen und die Wochennummer zurueckgegeben werden
  }
  if (wd < 4) {                          // wenn der 31.12. vor dem Donnerstag liegt, dann...
    wnr = 1;                             // ist das die erste Woche des Jahres
  } else {                               // anderenfalls muss ermittelt werden, ob es eine 53. Woche gibt (3. Sonderfall)
    /* wenn der letzte Wochentag auf einen Donnerstag oder,          */
    /* in einem Schaltjahr, auf einen Donnerstag oder Freitag fällt, */
    /* dann ist das die 53. Woche, ansonsten die 52. Woche.          */
    wnr = ((wd == 4) || (LeapYear && wd == 5)) ? 53 : 52;
  }
  return wnr;
}

/***** die Anzahl der Tage (Tag des Jahres) berechnen *****/
uint16_t GetDayOfYear(uint16_t y, uint8_t m, uint8_t d) {
  static const uint16_t mdays[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
  return d + mdays[m - 1] + (m >= 2 && IsLeapYear(y));
}

/***** Testen, ob das Jahr ein Schaltjahr ist *****/
bool IsLeapYear(uint16_t y) {
  return  !(y % 4) && ((y % 100) || !(y % 400)); // Schaltjahrberechnung (true = Schaltjahr, false = kein Schaltjahr)
}

Ich habe die Funktionen mit möglichen Grenzwerten getestet und (bisher) keine Fehler gefunden.
Vielleicht kann ja der Ein oder Andere diese Funktionen ebenfalls gebrauchen…

slartibartfast:
Ich musste feststellen, dass es gar nicht so einfach ist, die Wochennummer zu berechnen.
Im Internet findet man ja haufenweise Funktionen zur Berechnung, aber viele davon sind zu einfach aufgebaut und berücksichtigen nicht die Sonderfälle.

Eigentlich ist es ganz einfach:

der Montag vor dem ersten Donnerstag eines Jahres ist der Beginn von KW 1.
Und immer exakt eine Woche später, beginnt die nachfolgende Kalenderwoche.

Leider läßt es sich in C/C++ nicht ganz so einfach coden wie auf Deutsch hinschreiben.

In dem von Dir geposteten Code fehlt der Quellcode diverser verwendeter Funktionen, ich gehe daher mal davon aus, dass Du irgendeine Datums-Library verwendest, die im Programm inkludiert werden müßte, wenn man beim Kompilieren keine Compile-Errors bekommen möchte.

Und diese Datums-Library enthält wohl keine Funktion zur Berechnung der ISO-Kalenderwoche, sonst würdest Du die verwenden?

jurs:
In dem von Dir geposteten Code fehlt der Quellcode diverser verwendeter Funktionen, ich gehe daher mal davon aus, dass Du irgendeine Datums-Library verwendest, die im Programm inkludiert werden müßte, wenn man beim Kompilieren keine Compile-Errors bekommen möchte.

Und diese Datums-Library enthält wohl keine Funktion zur Berechnung der ISO-Kalenderwoche, sonst würdest Du die verwenden?

Nein, da fehlt nichts! Das habe ich so auf dem UNO getestet und es funktioniert.
Alle verwendeten Funktionen sind dort vorhanden. Es ging mir ja darum, keine zusätzliche Library dafür zu verwenden (das spart Platz).

Stimmt, sogar loop() {} ist da. Auch die Test-Variablen.
Auch der Hinweis, dass dies nur eine von mehreren WochenNummern - Regeln realisiert und zwar die hierzulande geltende.

arduino_1.6.7:
Der Sketch verwendet 3.056 Bytes

Sehr schön, danke.

In welche Woche fiel der 78. Februar 1871 ? :wink:

michael_x:
In welche Woche fiel der 78. Februar 1871 ? :wink:

Ja, auf die Fehlerbehandlung habe ich verzichtet.
Im Normalfall kommen die Werte ja von einer RTC. Die kann zwar auch falsche Werte liefern, aber ich denke, dass man die Fehlerbehandlung dann auch bereits dort implementieren wird.

slartibartfast:
Ja, auf die Fehlerbehandlung habe ich verzichtet.
Im Normalfall kommen die Werte ja von einer RTC. Die kann zwar auch falsche Werte liefern, aber ich denke, dass man die Fehlerbehandlung dann auch bereits dort implementieren wird.

Ich habe auch mal einen Code zur Kalenderwochenberechnung gemacht.

Der Code ist ebenfalls ohne Fehlerbehandlung bei falschen Kalenderdaten.
Aber eine Datumsprüfung ließe sich leicht nachrüsten.

Aber dafür ist mein Code immerhin deutlich kürzer als Deiner, mit weniger als 50 Zeilen, inklusive fünf Zeilen fürdie Berechnung von Datumsbeispielen:

/* DIN/ISO Kalenderwoche berechnen */
long JD(int y,int m,int d)
{ //calculate and return Julian Day Number from calendar date
  long jd=  ( 1461L * ( y + 4800 + ( m - 14 ) / 12 ) ) / 4 +
          ( 367 * ( m - 2 - 12 * ( ( m - 14 ) / 12 ) ) ) / 12 -
          ( 3 * ( ( y + 4900 + ( m - 14 ) / 12 ) / 100 ) ) / 4 +
          d - 32075;
  return jd;
}

byte usWeekday(long J)
// Rückgabewert ist amerikanischer Wochentag mit Sun=0, Mon=1, Sat=6
{return(J+1)%7;}

byte isoWeekDay(long J)
// Parameter ist die Julianische Tagesnummer
// Rückgabewert ist europäischer ISO Wochentag mit  Mon=1, Tue=2,Sat=6, Sun=7
{return J%7+1;}

long kw1JD(int year)
{// liefert die Julianische Tagesnummer der ersten KW des Jahres
  long result=JD(year,1,4);//vierter Januar gehört immer zur 1.KW
  byte weekday=isoWeekDay(result); // Wochentag nach ISO
  return result-weekday+1;
}



int KW(int Year,byte Month, byte Day)
{
  long kwJD=JD(Year,Month,Day); 
  if(Month==12 && kwJD>=kw1JD(Year+1)) return 1; // im Dezember bereits erste Woche des Folgejahres
  else if(Month==1 && kwJD<kw1JD(Year)) return KW(Year-1,12,31);//im Januar noch letzte KW  des Vorjahrs
  else return 1+(kwJD-kw1JD(Year))/7; // Normalfall
} 

void setup() 
{
  Serial.begin(9600);
  Serial.println(KW(2014,12,29));
  Serial.println(KW(2015,12,31));
  Serial.println(KW(2016,12,31));
  Serial.println(KW(2017,1,1));
  Serial.println(KW(2017,5,13));
}

void loop() 
{
}

Ich mache mir dabei zu nutze, dass der 04.Januar immer in die erste Kalenderwoche eines Jahres fällt.

Und als Hilfsfunktion arbeite ich mit der Julianischen Tagesnummer (Julian Day Number), die ich mit derHilfsfunktion “JD” errechnen kann.Von der Julianischen Tagesnummer ausgehend ist es ein Klacks, um sowohl auf die Wochentage nach amerikanischer oder europäischer ISO Zählweise zu kommen, wobei die amerikanischen Wochentage in diesem Programm nicht benötigt werden, das Programm ist also immer noch zu lang, weil es eine für doe ISO-Kalenderwochen nicht benötigte Funktion enthält.

@jurs: Du hast Recht, Dein Code ist kürzer/kleiner!
Und hätte ich ihn vorher gefunden, hätte ich mir die ganze Mühe sparen können.

Aber nur um meinen Code etwas zu verteidigen:
Codezeilen sind ja kein fairer Maßstab. Viele Zeilen bei meinem Code dienen ja der Kommentierung und der Ausgabe.
Um den Vergleich etwas fairer zu machen, sollte man die Ausgabe gleich gestalten und nur die compilierte Größe heranziehen (dabei sind die Kommentare egal):
Deinen Code habe ich mal so übernommen und auf einem UNO compiliert:

Der Sketch verwendet 2582 Bytes (8%) des Programmspeicherplatzes. Das Maximum sind 32256 Bytes.
Globale Variablen verwenden 186 Bytes (9%) des dynamischen Speichers, 1862 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.

Um auf die gleiche Ausgabe zu kommen, habe ich meinen Code angepasst:

/*  Daten mit Grenzwerten zum testen der Funktionen:
 *  29.12.2014 = ist ein Montag und faellt bereits in die 1. Woche des naechsten Jahres
 *  31.12.2015 = in dem Jahr gab es eine 53. Woche
 *  31.12.2016 = Tag des Jahres wird mit 366 korrekt berechnet (Schaltjahr)
 *  01.01.2017 = ist ein Sonntag und faellt noch in die 52. Woche des Vorjahres
*/
/*
uint16_t year = 2014;
uint8_t month = 12;
uint8_t day = 29;
const char WeekDays[][3] = {"Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"}; // Abkuerzungen der Wochentage
*/
void setup() {
  Serial.begin(9600);
  Serial.println(GetWeekNumber(2014, 12, 29));
  Serial.println(GetWeekNumber(2015, 12, 31));
  Serial.println(GetWeekNumber(2016, 12, 31));
  Serial.println(GetWeekNumber(2017, 1, 1));
  Serial.println(GetWeekNumber(2017, 5, 13));
  /*
  Serial.begin(115200);
  Serial.println(F("Berechnung nach ISO 8601"));
  
  Serial.print(F("Datum: "));
  Serial.print(day);
  Serial.print(".");
  Serial.print(month);
  Serial.print(".");
  Serial.println(year);

  uint8_t wd = GetWeekday(year, month, day);        // 1 = Mo, 2 = Di, 3 = Mi, 4 = Do, 5 = Fr, 6 = Sa, 7 = So
  Serial.print(F("Wochentag: "));
  Serial.println(WeekDays[wd - 1]);
  
  uint16_t doy = GetDayOfYear(year, month, day);    // den Tag des Jahres berechnen
  Serial.print(F("Tag des Jahres: "));
  Serial.println(doy);
  
  uint8_t WeekNr = GetWeekNumber(year, month, day); // die Wochennummer berechnen
  Serial.print(F("Wochennummer: "));
  Serial.println(WeekNr);

  bool LeapYear = IsLeapYear(year);                 // berechnen, ob das Jahr ein Schaltjahr ist
  Serial.print(F("Schaltjahr: "));
  Serial.println(LeapYear ? F("Ja") : F("Nein"));
  */
}

void loop() {

}

/***** Den Wochentag nach ISO 8601 (1 = Mo, 2 = Di, 3 = Mi, 4 = Do, 5 = Fr, 6 = Sa, 7 = So) berechnen *****/
uint8_t GetWeekday(uint16_t y, uint8_t m, uint8_t d) {
  static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
  y -= m < 3;
  uint8_t wd = (y + y / 4 - y / 100 + y / 400 + t[m - 1] + d) % 7;
  return (wd == 0 ? 7 : wd);
}

/***** Die Wochennummer nach ISO 8601 berechnen *****/
uint8_t GetWeekNumber(uint16_t y, uint8_t m, uint8_t d) {
  bool LeapYear;
  uint16_t doy = GetDayOfYear(y, m, d);  // Anzahl der Tage im Jahr ermitteln
  uint8_t wd = GetWeekday(y, m, d);      // Wochentag ermitteln
  uint8_t wnr = (doy - wd + 7) / 7;      // die Wochennummer berechnen
  switch (wnr) {
    case 0:                              // wenn die Wochennummer Null ergibt, dann liegt der Tag am Anfang des Jahres (1. Sonderfall)
      wd = GetWeekday(y - 1, 12, 31);    // den letzten Wochentag aus dem Vorjahr ermitteln
      LeapYear = IsLeapYear(y - 1);      // ermitteln, ob es sich beim Vorjahr um ein Schaltjahr handelt
      break;                             // und nach dem Switch weitermachen...
    case 52:                             // wenn die Wochennummer 52 ergibt, dann liegt der Tag am Ende des Jahres (2. Sonderfall)
      wd = GetWeekday(y, 12, 31);        // den letzten Wochentag aus diesem Jahr ermitteln
      LeapYear = IsLeapYear(y);          // ermitteln, ob es sich bei diesem Jahr um ein Schaltjahr handelt
      break;                             // und nach dem Switch weitermachen...
    default:                             // in den anderen Faellen kann die Funktion
      return wnr;                        // hier verlassen und die Wochennummer zurueckgegeben werden
  }
  if (wd < 4) {                          // wenn der 31.12. vor dem Donnerstag liegt, dann...
    wnr = 1;                             // ist das die erste Woche des Jahres
  } else {                               // anderenfalls muss ermittelt werden, ob es eine 53. Woche gibt (3. Sonderfall)
    /* wenn der letzte Wochentag auf einen Donnerstag oder,          */
    /* in einem Schaltjahr, auf einen Donnerstag oder Freitag fällt, */
    /* dann ist das die 53. Woche, ansonsten die 52. Woche.          */
    wnr = ((wd == 4) || (LeapYear && wd == 5)) ? 53 : 52;
  }
  return wnr;
}

/***** die Anzahl der Tage (Tag des Jahres) berechnen *****/
uint16_t GetDayOfYear(uint16_t y, uint8_t m, uint8_t d) {
  static const uint16_t mdays[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
  return d + mdays[m - 1] + (m >= 2 && IsLeapYear(y));
}

/***** Testen, ob das Jahr ein Schaltjahr ist *****/
bool IsLeapYear(uint16_t y) {
  return  !(y % 4) && ((y % 100) || !(y % 400)); // Schaltjahrberechnung (true = Schaltjahr, false = kein Schaltjahr)
}

Was zu dem Ergebnis führt:

Der Sketch verwendet 2184 Bytes (6%) des Programmspeicherplatzes. Das Maximum sind 32256 Bytes.
Globale Variablen verwenden 234 Bytes (11%) des dynamischen Speichers, 1814 Bytes für lokale Variablen verbleiben. Das Maximum sind 2048 Bytes.

Fazit: Beim Programmspeicherplatz liegt mein Code vorn, beim dynamischen Speicher liegt Dein Code vorn.

In Anbetracht der Tatsache, dass einem beim Arduino meist zuerst der dynamische Speicher ausgeht, ist Deine Variante wohl als Sieger anzusehen. Glückwunsch! :slight_smile:

slartibartfast:
Fazit: Programmspeicherplatz liegt mein Code vorn, dynamischer Speicher liegt Dein Code vorn.

Na bravo!

Wie die Suchfunktion mir zeigt, sind sowohl vor drei Jahren(2014) als aauch bereits vor sechs Jahren (2011) in diesem Forum Themen gestartet worden, in denen nach Code für die Kalenderwochen-Berechnung gefragt wurde, ohne dass den Fragestellern damals mit Code weitergeholfen werden konnte.

Wenn es jetzt gleich zwei verschiedene Codes dafür gibt, dann braucht der nächste Fragesteller die fertigen Codes in diesem Thread nur noch finden und kann sich dann was davon aussuchen.

Wenn du deine beiden Tabellen in den Flash verschiebst, ist dein Kode bei gleichem RAM kleiner.

Der Sketch verwendet 2456 Bytes (0%) des Programmspeicherplatzes. Das Maximum sind 253952 Bytes.
Globale Variablen verwenden 186 Bytes (2%) des dynamischen Speichers, 8006 Bytes für lokale Variablen verbleiben. Das Maximum sind 8192 Bytes.

/*  Daten mit Grenzwerten zum testen der Funktionen:
    29.12.2014 = ist ein Montag und faellt bereits in die 1. Woche des naechsten Jahres
    31.12.2015 = in dem Jahr gab es eine 53. Woche
    31.12.2016 = Tag des Jahres wird mit 366 korrekt berechnet (Schaltjahr)
    01.01.2017 = ist ein Sonntag und faellt noch in die 52. Woche des Vorjahres
*/
/*
  uint16_t year = 2014;
  uint8_t month = 12;
  uint8_t day = 29;
  const char WeekDays[][3] = {"Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"}; // Abkuerzungen der Wochentage
*/
void setup() {
  Serial.begin(9600);
  Serial.println(GetWeekNumber(2014, 12, 29));
  Serial.println(GetWeekNumber(2015, 12, 31));
  Serial.println(GetWeekNumber(2016, 12, 31));
  Serial.println(GetWeekNumber(2017, 1, 1));
  Serial.println(GetWeekNumber(2017, 5, 13));
  /*
    Serial.begin(115200);
    Serial.println(F("Berechnung nach ISO 8601"));

    Serial.print(F("Datum: "));
    Serial.print(day);
    Serial.print(".");
    Serial.print(month);
    Serial.print(".");
    Serial.println(year);

    uint8_t wd = GetWeekday(year, month, day);        // 1 = Mo, 2 = Di, 3 = Mi, 4 = Do, 5 = Fr, 6 = Sa, 7 = So
    Serial.print(F("Wochentag: "));
    Serial.println(WeekDays[wd - 1]);

    uint16_t doy = GetDayOfYear(year, month, day);    // den Tag des Jahres berechnen
    Serial.print(F("Tag des Jahres: "));
    Serial.println(doy);

    uint8_t WeekNr = GetWeekNumber(year, month, day); // die Wochennummer berechnen
    Serial.print(F("Wochennummer: "));
    Serial.println(WeekNr);

    bool LeapYear = IsLeapYear(year);                 // berechnen, ob das Jahr ein Schaltjahr ist
    Serial.print(F("Schaltjahr: "));
    Serial.println(LeapYear ? F("Ja") : F("Nein"));
  */
}

void loop() {

}

const int t_Table[] PROGMEM = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};

/***** Den Wochentag nach ISO 8601 (1 = Mo, 2 = Di, 3 = Mi, 4 = Do, 5 = Fr, 6 = Sa, 7 = So) berechnen *****/
uint8_t GetWeekday(uint16_t y, uint8_t m, uint8_t d) {
  y -= m < 3;
  uint8_t wd = (y + y / 4 - y / 100 + y / 400 + pgm_read_word(t_Table + m - 1) + d) % 7;
  return (wd == 0 ? 7 : wd);
}

/***** Die Wochennummer nach ISO 8601 berechnen *****/
uint8_t GetWeekNumber(uint16_t y, uint8_t m, uint8_t d) {
  bool LeapYear;
  uint16_t doy = GetDayOfYear(y, m, d);  // Anzahl der Tage im Jahr ermitteln
  uint8_t wd = GetWeekday(y, m, d);      // Wochentag ermitteln
  uint8_t wnr = (doy - wd + 7) / 7;      // die Wochennummer berechnen
  switch (wnr) {
    case 0:                              // wenn die Wochennummer Null ergibt, dann liegt der Tag am Anfang des Jahres (1. Sonderfall)
      wd = GetWeekday(y - 1, 12, 31);    // den letzten Wochentag aus dem Vorjahr ermitteln
      LeapYear = IsLeapYear(y - 1);      // ermitteln, ob es sich beim Vorjahr um ein Schaltjahr handelt
      break;                             // und nach dem Switch weitermachen...
    case 52:                             // wenn die Wochennummer 52 ergibt, dann liegt der Tag am Ende des Jahres (2. Sonderfall)
      wd = GetWeekday(y, 12, 31);        // den letzten Wochentag aus diesem Jahr ermitteln
      LeapYear = IsLeapYear(y);          // ermitteln, ob es sich bei diesem Jahr um ein Schaltjahr handelt
      break;                             // und nach dem Switch weitermachen...
    default:                             // in den anderen Faellen kann die Funktion
      return wnr;                        // hier verlassen und die Wochennummer zurueckgegeben werden
  }
  if (wd < 4) {                          // wenn der 31.12. vor dem Donnerstag liegt, dann...
    wnr = 1;                             // ist das die erste Woche des Jahres
  } else {                               // anderenfalls muss ermittelt werden, ob es eine 53. Woche gibt (3. Sonderfall)
    /* wenn der letzte Wochentag auf einen Donnerstag oder,          */
    /* in einem Schaltjahr, auf einen Donnerstag oder Freitag fällt, */
    /* dann ist das die 53. Woche, ansonsten die 52. Woche.          */
    wnr = ((wd == 4) || (LeapYear && wd == 5)) ? 53 : 52;
  }
  return wnr;
}

const uint16_t mdays_Table[] PROGMEM = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};

/***** die Anzahl der Tage (Tag des Jahres) berechnen *****/
uint16_t GetDayOfYear(uint16_t y, uint8_t m, uint8_t d) {
  return d + pgm_read_word(mdays_Table + m - 1) + (m >= 2 && IsLeapYear(y));
}

/***** Testen, ob das Jahr ein Schaltjahr ist *****/
bool IsLeapYear(uint16_t y) {
  return  !(y % 4) && ((y % 100) || !(y % 400)); // Schaltjahrberechnung (true = Schaltjahr, false = kein Schaltjahr)
}

Ok, gute Idee! :slight_smile:
Danke!