Time.cpp berechnet das Schaltjahr falsch

Hallo,

was meint ihr dazu?

#include <Streaming.h>

#define LEAP_YEAR(Y)     ( ((1970+(Y))>0) && !((1970+(Y))%4) && ( ((1970+(Y))%100) || !((1970+(Y))%400) ) )

void setup(){
  Serial.begin(9600);
  Serial.println("Osterdatum berechnen");
  for(int j=2018;j<2050;j++){
    Serial<<j<<"  "<<Schaltjahr(j)<<"  "<<LEAP_YEAR(j)<<endl;
  }
}

void loop()
{
}

boolean Schaltjahr(int Y){return ((1972+(Y))>0) && !((1972+(Y))%4) && ( ((1972+(Y))%100) || !((1972+(Y))%400));}

Am Serialmonitor habe ich dann folgendes

2018  0  1
2019  0  0
2020  1  0  //Schaltjahr
2021  0  0
2022  0  1
2023  0  0
2024  1  0
2025  0  0
2026  0  1
2027  0  0
2028  1  0
2029  0  0
2030  0  1
2031  0  0
2032  1  0
2033  0  0
2034  0  1
2035  0  0
2036  1  0
2037  0  0
2038  0  1
2039  0  0
2040  1  0
2041  0  0

2042  0  1
2043  0  0
2044  1  0
2045  0  0
2046  0  1
2047  0  0
2048  1  0
2049  0  0

In der Bibliothek lese ich in Time.cpp:

"leap year calulator expects year argument as years offset from 1970" also LEAP_YEAR(j-1970), oder?

Jetzt habe ich noch etwas!

In meiner Schleife wird das Jahr 2024 nicht als Schaltjahr bewertet.

#include <Streaming.h>
#define LEAP_YEAR(Y)     ( ((1970+(Y))>0) && !((1970+(Y))%4) && ( ((1970+(Y))%100) || !((1970+(Y))%400) ) )



void setup(){
  Serial.begin(9600);

  for(int j=2018;j<2050;j++){
    Serial<<j<<"  "<<Schaltjahr(j)<<"  "<<LEAP_YEAR(j)<<endl;
    Serial<<j<<" "<<1<<"."<<3<<" "<<Jahrestag(1,3,j)<<endl;
  }
  
}

void loop()
{

}



boolean Schaltjahr(int Y){return ((1968+(Y))>0) && !((1968+(Y))%4) && ( ((1968+(Y))%100) || !((1968+(Y))%400));}

int Jahrestag(byte D, byte M, byte Y){
  if(M<3) return (D+(153*(M+12)-162)/5)-365;
  else return Schaltjahr(Y)+D+(153*M-162)/5;
}
2018  0  1
2018 1.3 60
2019  0  0
2019 1.3 60  
2020  1  0
2020 1.3 61  //hier stimmt alles
2021  0  0
2021 1.3 60
2022  0  1
2022 1.3 60
2023  0  0
2023 1.3 60
2024  1  0
2024 1.3 60  //bei einen Schaltjahr ist der 1.März der 61. Tag im Jahr
2025  0  0
2025 1.3 60
2026  0  1
2026 1.3 60
2027  0  0
2027 1.3 60

agmue:
In der Bibliothek lese ich in Time.cpp:

"leap year calulator expects year argument as years offset from 1970" also LEAP_YEAR(j-1970), oder?

Ich lese das eher so, dass die Zahl größer 1970 sein muss.

Aber ich habs probiert und

#define LEAP_YEAR(Y) ( (Y>0) && !(Y%4) && ( (Y%100) || !(Y%400) ) )

liefert richtige Ergebnisse.

@ar182:

in der deiner Makro-Definition

#define LEAP_YEAR(Y)     ( ((1970+(Y))>0) && !((1970+(Y))%4) && ( ((1970+(Y))%100) || !((1970+(Y))%400) ) )

ist Y tatsächlich die Anzahl Jahre seit 1970 (wie agmue schon zitiert hat).
Ist also offensichtlich nicht für die Verwendung mit unseren üblichen Jahreszahlen gedacht. Weder 18 noch 2018 passt für das aktuelle Jahr.

Der der unserer Schaltjahrberechnung zugrundeliegende Gregorianische Kalender wurde übrigens erst 1582 erfunden, der erste Check ((1970+(Y))>0) ist also Unsinn.

Hi

Die 1970 werden wohl vom Unix-Timestamp herrühren.
Den gibt Es erst seit 1970, ist weltweit greifbar sowie identisch und man kann damit errechnen, in welchem Jahr man sich befindet.
Davon ausgehend kann man dann noch erkennen, ob's sich dabei um ein Schaltjahr handelt.

MfG

Es gibt solche "historischen" Jahreszahlen: Zu zweistelligen Jahreszahlen größer gleich 70 wird 1900 addiert, sonst 2000.

Bei Excel ist oder war die "historischen" Jahreszahl 1900, wenn ich mich richtig erinnere.

Die Library hat Makros um das umzurechnen!

//convenience macros to convert to and from tm years 
#define  tmYearToCalendar(Y) ((Y) + 1970)  // full four digit year 
#define  CalendarYrToTm(Y)   ((Y) - 1970)

Hallo,

es ist wie es ist bei mir funktioniert jetzt alles.

Wen es interessiert, ich habe mir einen Feiertagsberechnung incl. der beweglichen
Feiertage gebastelt.

Natürlich fürs katholische Bayern. Leider bin ich kein Augsburger, da wäre es noch einer mehr. :wink:

Gruß Aron

#include <Streaming.h>

void setup(){
  byte oTag, oMonat;
  Serial.begin(9600);
  Serial.println("Feiertage berechnen");
    //kleiner Test
    for(int m=1;m<13;m++){
      for(int t=1;t<32;t++){    //die überzähligen Tage für die Kurzen Monate selber wegdenken ;)
        Serial<<t<<"."<<m<<" "<<Feiertag(t,m,2019)<<endl;
      }
    }
}

void loop(){}

boolean Feiertag(byte Tag, byte Monat, int Jahr){
  int jTag = Jahrestag(Tag, Monat, Jahr);                     //Tage seit 1.Januar
  byte oTag, oMonat;
  Oster_Datum(Jahr, &oTag, &oMonat);                          //Datum Ostersonntag berechnen
  int jTagO = Jahrestag(oTag, oMonat, Jahr);                  //Tage seit 1.Januar bis Ostersonntag
  if(Tag==1 && Monat==1) return true;                         //Neujahr
  else if(Tag==6 && Monat==1) return true;                    //Heilig Drei König
  else if(jTag==jTagO-2) return true;                         //Karfreitag
  else if(jTag==jTagO) return true;                           //Ostersonntag
  else if(jTag==jTagO+1) return true;                         //OsterMontag
  else if(Tag==1 && Monat==5) return true;                    //Tag der Arbeit
  else if(jTag==jTagO+39) return true;                        //Christi Himmelfahrt
  else if(jTag==jTagO+49) return true;                        //Pfingstsonntag
  else if(jTag==jTagO+50) return true;                        //Pfingstmontag
  else if(jTag==jTagO+60) return true;                        //Fronleichnam
  else if(Tag==15 && Monat==8) return true;                   //Mariä Himmelfahrt
  else if(Tag==3 && Monat==10) return true;                   //Tag der Deutschen Einheit
  else if(Tag==1 && Monat==11) return true;                   //Allerheiligen
  else if(Tag>23 && Tag<26 && Monat==12) return true;         //Weihnachten
  else return false;                                          //kein Feiertag
}

byte Oster_Datum(int Jahr, byte *oTag, byte *oMonat){
  int k, m, s, a, d, r, og, sz, oe, os;
  k = Jahr /100;
  m = 15 + (3*k+3)/4-(8*k+13)/25;
  s = 2 -(3*k+3)/4;
  a = Jahr %19;
  d = (19*a+m)%30;
  r = d/29 +(d/28-d/29) * a /11;
  og = 21 +d -r;
  sz = 7 - ((Jahr+Jahr/4+s)%7);
  oe = 7 - ((og-sz)%7);

  os = og +oe;

  if (os <=31){
  *oTag = os;
  *oMonat = 3;
  }
  else{
  *oTag = os - 31;
  *oMonat = 4;
  }
}

boolean Schaltjahr(int Y){return (Y>0) && !(Y%4) && ( (Y%100) || !(Y%400));}

int Jahrestag(byte D, byte M, byte Y){
  if(M<3) return (D+(153*(M+12)-162)/5)-365;
  else return Schaltjahr(Y)+D+(153*M-162)/5;
}

Die Osterformel ist beeindruckend.

Der Reformationstag 2018 fehlt :stuck_out_tongue:
Den habt ihr Bayern ja auch nicht wirklich verdient gehabt.

michael_x:
Die Osterformel ist beeindruckend.

Gaußsche Osterformel :slight_smile:

michael_x:
Der Reformationstag 2018 fehlt :stuck_out_tongue:

Ich arbeite am 31.10.

Hallo Gemeind.

Ich bin ziemlicher Ardunio Neuling und versuche mal hier mein Glück.
Ich bastel an einem kleine NTP Server der die Arduino Systemzeit die ich über eine http Oberfläche stellen kann hostet.

Dazu verwende ich diesen Sketch:

Allerdings ist der Schaltjahrteil buggy:

const uint8_t daysInMonth PROGMEM = {
31,28,31,30,31,30,31,31,30,31,30,31 }; //const or compiler complains

const unsigned long seventyYears = 2208988800UL; // to convert unix time to epoch

// NTP since 1900/01/01
static unsigned long int numberOfSecondsSince1900Epoch(uint16_t y, uint8_t m, uint8_t d, uint8_t h, uint8_t mm, uint8_t s) {
if (y >= 1970)
y -= 1970;
uint16_t days = d;
for (uint8_t i = 1; i < m; ++i)
days += pgm_read_byte(daysInMonth + i - 1);
if (m > 2 && y % 4 == 0)
++days;
days += 365 * y + (y + 3) / 4 - 1;
return days24L3600L + h3600L + mm60L + s + seventyYears;
}

Schalthjahre werden hier wohl falsch berechnet, denn ab dem 1.1.87 ist immer ein Tag in der Zukunft und ich glaub ab dem 1.1.21 passet es wieder um dann aber ein paar Jahre später falsch zu gehen.

Leider übersteigt der Code mein Verständniss. Jetzt hatte ich gehofft, das hier einer mehr durchblick hat was den hier flasch ist?

Schon mal vielen Dank im Voraus :slight_smile:

Ich bin ziemlicher Ardunio Neuling und versuche mal hier mein Glück.

Dann mal ein Tipp:
Bitte keine fremden Threads hijacken.

Neues Problem, neuer Thread.

combie:
Dann mal ein Tipp:
Bitte keine fremden Threads hijacken.

Neues Problem, neuer Thread.

Oh, sorry, ich dacht ich hänge mich einfach an da da Proplem sehr ähnlich ist ...
Habs in einen neuen Thread verpackt.