Abstand zwischen zwei Tagen berechnen nach dem 19.01.2038

Moin,

auf die folgende Art berechne ich aktuell den Abstand zwischen zwei Daten/Datums/wei heißt das nochmal;-)

#include <time.h> 

tm dayval;

void setup() {
  delay(2000);
  Serial.begin(115200);
  Serial.println(daydiff(2022, 8, 19, 2023, 2, 25));
}

void loop() {
  // put your main code here, to run repeatedly:

}

int daydiff (int16_t jahr_von, int16_t monat_von, int16_t tag_von,int16_t jahr_bis, int16_t monat_bis, int16_t tag_bis) {
  dayval.tm_year = jahr_von - 1900;
  dayval.tm_mon = monat_von - 1;
  dayval.tm_mday = tag_von;
  time_t timestamp_von = mktime(&dayval);

  dayval.tm_year = jahr_bis - 1900;
  dayval.tm_mon = monat_bis - 1;
  dayval.tm_mday = tag_bis;
  time_t timestamp_bis = mktime(&dayval);

  return((timestamp_bis - timestamp_von)/60/1440);
}

Aber: Ist es so, dass ich ab dem 19.01.2038 um 3:34 Uhr nicht mehr glücklich sein werde mit dem Ergebnis?

Gibt es auch einen Lösungsansatz, der über dieses Datum hinaus funktioniert?

LG
Daniel

Meinst Du, dass Deine Arduinoprogramme bis dahin noch unverändert im Einsatz sind?
Mir ist bisher kein neuer Time-Standard für nach diesem Zeitpunkt bekannt.

Du könntest die bestehenden Routinen auf uint32_t oder auf (u)int64_t umschreiben.

Gruß Tommy

Epochalypse ➜ mktime() gibt den Zeitstempel zurück, der ein time_t (eine Ganzzahl) ist. Auf einem 32-Bit-System ist der maximal mögliche Zeitstempel der 19. Januar 2038 03:14:07 UTC

für ein ESP32 siehe time_t is 32-bit wide, please change to 64-bit to make applications Y2K38 safe (IDF-350) · Issue #584 · espressif/esp-idf · GitHub und die Umstellung auf 64 Bit

Ganz sicher nicht :wink: Trotzdem wollte ich mal fragen, man will ja immer das beste rausholen

Mein Englisch ist nicht das allerbeste, aber:
Verstehe ich es richtig, dass es sich hier um ein ESP32-Firmware(Core)-Problem handelt und die time_t Variablen nur 4-Bit sind? Der Beitrag ist aber ja von 2018, d.h. ist das dann nicht evtl. schon behoben?

Ich befürchte, dazu bin ich nicht fähig...
Ich hab mal die Time.cpp aufgemacht und nach int32 gesucht.
Die sind schon alle auf uint32_t gesetzt, sollte doch dann passen, oder?
Aber wie gesagt: hier rumzuändern "trau" ich mich noch nicht :upside_down_face:

Aber vielleicht hast du Recht und ich sollte das erstmal ignorieren. Bis 2038 sinds ja noch ein paar Tage.

Leider ist der Master-Branch (bf43076) nicht das, was wir in Produktion haben, denke ich

#include <time.h>

void setup() {
  Serial.begin(115200);
  Serial.print("sizeof time_t = "); 
  Serial.println(sizeof(time_t));
}

void loop() {}

sizeof time_t = 4

yep... kann ich soeben bestätigen ;-(

Die gute Nachricht ist, dass wir noch mehr als 15 Jahre haben, bevor die neue Version in Produktion geht ...

(Sie müssen den Code neu kompilieren und erneut bereitstellen ...)

Du machst mir grad gute Laune ! Auch hier muss ich dir wieder zu 100% zustimmen.

Nach dem Motto "Lebe im Hier und Jetzt" lege ich dieses Problem HIERmit ad-akta

Beschreibe kurz, was Du mit Zeit nach 2038 vorhast.
Ich habe hier irgendwann eine Routine geschrieben, die unabhängig von time_t() die Anzahl Tage Stunden etc. zurückgibt und sogar das Schaltjahr richtig berücksichtigt.
Damals ging es darum die Zeit bis zu einem in der Zukunft liegendem Datum zu errechnen....
- Ich such mal....
gefunden: DateDiff - Differenz zwischen zwei Daten - #62 by my_xy_projekt
Es gibt zwei Array-Variablen startDatum und endDatum, die musst Du füttern. (das include time.h kann raus. das stammte noch aus eienr früheren version)

16:12:47.138 -> Berechnung vom: 15.2.2022 23:59:59 bis 15.3.2042 0:0:0
16:12:47.138 -> Differenz: 20 Jahre 0 Monate 27 Tage sowie 0 Stunden 0 Minuten 1 Sekunde

Hi,

deinen Sketch hatte ich sogar schon gefunden (vor meinem Post) :smiley:
Aber da wird am Ende ja Jahre, Monate und Tage ausgegeben. Da ich nur Tage brauch, hat das für meinen Zweck nicht gepasst. Bestimmt kann man das auch so umschreiben, dass nur Tage ausgegeben werden, aber ich habs nicht wirklich hinbekommen.

Wenn da als Ergebnis z.B. 1 Jahr, 4 Monate und 5 Tage rauskommt kann ich ja nicht einfach sagen, 16 Monate = 16 * 30 Tage. Man müsste dann für jeden Monat denk ich wieder ermitteln, wieviel Tage der hat - spätestens da bräuchte ich bestimmt dann wieder die time-library, oder?

Nichts besonderes, ich wollte halt nur, dass das Skript - falls möglich - nicht im Jahr 2038 Goodbye sagt.

Grüßle
Daniel

Nö, wieso solltest Du? Im Code oben ist ein Array. dort ist für jeden Monat die Anzahl Tage drin.
Ganz unten ist eine Funktion, die Dir zurück gibt, ob Schaltjahr oder nicht.
Vom Prinzip her einfach durchzählen und aufaddieren. Volle Jahre mit 365 beim Schaltjahr +1, Monate aus der Tabelle Tage einfach.

:see_no_evil: OK, dann kuck ich nochmal rein.

Edit: Wie konnte ich den Array übersehen...manchmal zweifelt man an seinem Verstand.

Beachten Sie, dass Sie die DateTime- und TimeSpan-Klassen von GitHub - adafruit/RTClib: A fork of Jeelab's fantastic RTC Arduino library verwenden könnten

Diese Klassen haben das 2038-Problem nicht

Klingt auch gut, aber:
Mir ists grundsätzlich immer lieber, wenn ich auf das Einbinden einen Library verzichten kann.
Von daher werd ich mich für die Lösung von @my_xy_projekt entscheiden.
Danke dafür :hugs:

Du kannst ja die Funktionen der Bibliothek, die Du brauchst, in Deinen Sketch kopieren.
Die IDE hat die Möglichkeit den Sketch in mehrere Files aufteilen. Diese werden beim kompilieren zusammengefügt.
Grüße Uwe

Was gefunden?
Ich hätte sonst seit gestern eigentlich nen Kurzzeiler...

Hi :v:

Nein, bin noch nicht dazu gekommen.
Ne Mischung aus Arbeit und Freizeitstress ist mir dazwischen gekommen :smile:
Ich hoff ich kann mich morgen damit beschäftigen. Sollte aber ja gut lösbar sein, deine Funktion hält ja tatsächlich schon alles bereit, was ich brauch;-)

LG Daniel

Ich hab die Tage nach 50 Zeilen Code in der Hand. (incl.setup und Variablenanlage und 9 Zeilen sermon)
Das Einzige was ich übernommen habe ist das tageArray und die Errechnung des Schaltjahres.
Bin gespannt, welchen Weg Du gehts. :wink:
na denne..

Oh, dann scheint es wohl doch nicht so einfach zu sein :grimacing: :see_no_evil: na wenn du da schon so viel Zeit reinstecken musstest, werd ichs wohl garnicht erst hinbekommen :woozy_face:

Also wenns für dich ok ist, freu ich mich natürlich über deine Lösung.
Soll aber natürlich nicht heißen, dass ich mich nicht damit beschäftigen will.
Aber es hört sich dann anscheinend doch nicht nach wenigen Anpassungen an...

Naja, ich hab die Kurzvariante genommen und versucht das mit Logik zu lösen.


const byte tagemonate[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
uint8_t startTag = 18, startMonat = 12;
uint16_t startJahr = 2020;
uint8_t endTag = 15, endMonat = 6;
uint16_t endJahr = 2021;
uint16_t startJahrTage = 0;  // Ergebnismerker von Start bis Jahresende
uint16_t endJahrTage = 0;
uint32_t jahresTage = 0;


void setup()
{
  delay(300);
  Serial.begin(115200);
  Serial.println(F("Start..."));
  tage();
}

void loop()
{
}

void tage()
{
  addition(startJahrTage, startTag, startMonat, startJahr);
  addition(endJahrTage, endTag, endMonat, endJahr);
  for (uint16_t b = startJahr; b < endJahr; b++)        // Jahre durchzählen
  {
    jahresTage += 365;                                  // Addition der Jahrestage
    if (isSchaltJahr(b) &&                              // Prüfung auf Schaltjahr
        b != startJahr)                                 // wenn nicht bereits enthalten
    { jahresTage++; }                                   // Korrekturtag setzen
  }
  ausgabe();
}

void ausgabe()
{
  Serial.print(F("Tage von Start bis Jahresende: "));
  Serial.println(startJahrTage);
  Serial.print(F("Tage von End bis Jahresende: "));
  Serial.println(endJahrTage);
  Serial.print(F("Tage der dazwischenliegenden Jahre: "));
  Serial.println(jahresTage);
  Serial.print(F("Gesamttage... "));
  uint32_t x = (startJahrTage + jahresTage) - endJahrTage;
  Serial.println(x);
}

void addition(uint16_t &ergebnis, const byte aDay, const byte aMonth, const uint16_t aYear)
{
  ergebnis += addSchaltDay(aMonth, aYear);
  ergebnis += tagemonate[aMonth] - aDay;
  for (byte b = aMonth + 1; b <= 12; b++)
  { ergebnis += tagemonate[b]; }
}
bool isSchaltJahr(const uint16_t jahr )
{
  if ((jahr % 400) == 0)
  { return true; }
  else if ((jahr % 100) == 0)
  { return false; }
  else if ((jahr % 4) == 0)
  { return true; }
  return false;
}
byte addSchaltDay(const uint8_t sMonth, const uint16_t sYear )
{
  byte returnWert = 0;
  if (isSchaltJahr(sYear) &&                // Nur im Schaltjahr prüfen
      sMonth <= 2)                          // entweder Januar oder Februar
  { returnWert++; }
  return returnWert;
}

Noch nicht ganz durchgetestet, aber es sollte tun.
Sollte das nicht klar sein, was die Funktionen machen, kommentiere ich es noch weiter.
Den month-vergleich im Schaltjahr noch zusammengefasst auf <=