Datum mit Zeiträumen vergleichen

Hallo Zusammen,

ich bin immernoch an meinem Kalenderprojekt am basteln und habe ein neues Problem,
das ich zwar sehr umständlich lösen könnte, aber ich vorher wollte wissen, ob es da vll. einen einfacheren Weg gibt.

Folgendes ist die Problemstellung:

Ich lese von Google Calendars Ereignisse aus. Folgende beispielhaften Werte werden extrahiert und sind von Interesse:

DTSTART:20180613T133000Z
DTEND: 20180613T150000Z
SUMMARY:Testeintrag

Der Code den ich jetzt schreiben möchte soll ab dem aktuellen Datum feststellen ob der Eintrag heute oder innerhalb der nächsten 6 Tage stattfindet.

Die Problematik dabei ist der Umbruch von einem Monat/Jahr zum Nächsten.
Man könnte natürlich statische Arrays definieren die die Anzahl der Tage im Monat halten und dann mit einigen verschachtelten if-Bedingungen die folgenden Daten generieren und mit dem des Events vergleichen. (Wirklich hässlich alleine schon wegen dem 29.02 alle 4 Jahre)

Bei anderen Umgebungen gibt es hierfür einfachere Lösungen wie:

Morgen = Heute +1;

Muss ich den komplizierten Weg gehen oder gibt es da bereits etwas fertiges?

Datum/Zeit umwandeln in einen Unix-Timestamp und dann einfach die Differenz auf + 62460*60 prüfen.
Die Timelib ist dein Freund.

Du kannst das jeweilige Datum auf die Unix-Zeit umrechnen. Dann hast du nur eine Zahl mit der du einfach rechnen kannst

Schaue dir mal diese Kalenderalgorithmen an: http://lueersen.homedns.org/Pronix_final/ckurs/ckurs143.html

Der Algorithmus von Robertson weit unten müsste das richtige für dich sein.

Die UNIX-Zeit hat 2038, also schon in 20 Jahren, einen Überlauf, weshalb es nützlich sein könnte, die Sekunden ab einem späteren Zeitpunkt zu verwenden, beispielsweise ab 2000, da Du nur Ereignisse in der Zukunft überprüfen möchtest.

agmue:
Die UNIX-Zeit hat 2038, also schon in 20 Jahren, einen Überlauf

Nur wenn man 32 Bit mit Vorzeichen verwendet. Die Time Library z.B. verwendet unsigned long

Wenn man nur eine Auflösung von einem Tag braucht (statt eine Sekunde wie bei der Unix Zeit) bietet sich das julianische Datum an

Der Ansatz klingt sehr gut, nur die Umsetzung bereitet mir weiterhin Kopfzerbrechen...

in time.h wird auf eine Funktion verwiesen, die mktime heißt.
Nach einigem Testen habe ich herausgefunden, dass Sie genau das Gesuchte tut.

void setup() {
  // Serialschnittstelle für Debug
    Serial.begin(115200);
    //display.init();
    Start_WiFi();
    //Kalender_Wochenansicht_vorbereiten();
    Kalendereintrag_pruefen("20180613T133000Z","20180613T150000Z","C");
}

void Start_WiFi()
{    
    WiFi.begin(Wifi_ssid, Wifi_password);
    delay(2000);
    configTime(3600, 3600, "pool.ntp.org");
    delay(20);
    if (!getLocalTime(&Datum))
    {
      Serial.println("Fehler!");
    }
    else
    {
      Serial.println(&Datum, "%A, %B %d %Y %H:%M:%S");
    }

}

...

void Kalendereintrag_pruefen(String Start, String Ende, String Beschreibung)
{  
  //mktime = UNIX-Zeit: Sekunden seit 01.01.1970 00:00:00

  //Aktuelle Zeit abfragen
  struct tm Heute;
  Heute = Datum;

  //Auf Tagesanfang stellen
  Heute.tm_hour = 0;
  Heute.tm_min = 0;
  Heute.tm_sec = 0;
  time_t HeuteUNIX = mktime(&Heute);
  
  //Event Zeitstempel erstellen
  struct tm Eventstart, Eventende;

Serial.println(Datum.tm_year);
Serial.println(Datum.tm_mon);
Serial.println(Datum.tm_mday);
Serial.println(Datum.tm_hour);
Serial.println(Datum.tm_min);
Serial.println(Datum.tm_sec);

Serial.println(Ende.substring(0,4));
Serial.println(Ende.substring(4,6));
Serial.println(Ende.substring(6,8));
Serial.println(Ende.substring(9,11));
Serial.println(Ende.substring(11,13));
Serial.println(Ende.substring(13,15));


  //Eventstart
  Eventstart.tm_year = (Start.substring(0,4).toInt()-1900);
  Eventstart.tm_mon = (Start.substring(4,6).toInt()-1);
  Eventstart.tm_mday = Start.substring(6,8).toInt();
  Eventstart.tm_hour = Start.substring(9,11).toInt();
  Eventstart.tm_min = Start.substring(11,13).toInt();
  Eventstart.tm_sec = Start.substring(13,15).toInt();
  time_t EventstartUNIX = mktime(&Eventstart);

  //Eventende 
  Eventende.tm_year = (Ende.substring(0,4).toInt()-1900);
  Eventende.tm_mon = (Ende.substring(4,6).toInt()-1);
  Eventende.tm_mday = Ende.substring(6,8).toInt();
  Eventende.tm_hour = Ende.substring(9,11).toInt();
  Eventende.tm_min = Ende.substring(11,13).toInt();
  Eventende.tm_sec = Ende.substring(13,15).toInt();
  time_t EventendeUNIX = mktime(&Eventende);

  time_t JetztUNIX = mktime(&Datum);
  Serial.print("Jetzt: ");
  Serial.println(JetztUNIX);
  Serial.print("Heute: ");
  Serial.println(HeuteUNIX);
  Serial.print("Start: ");
  Serial.println(EventstartUNIX);
  Serial.print("Ende: ");
  Serial.println(EventendeUNIX);
  
}

Das Ergebnis in der Konsole sieht so aus:

Sunday, June 24 2018 17:09:16
118
5
24
17
9
16
2018
06
13
15
00
00
Jetzt: 1529852956
Heute: 1529791200
Start: 1528889400
Ende: 1528898400

Nach etwas testen habe ich herausgefunden, dass die Lib mit einem Versatz bis 1900 arbeitet und die Monate 0-basiert sind.

Rein von der Theorie passt das auch alles so, ABER aus einem mir überhaupt nicht verständlichen Grund ist die letzte berechnete Zeit um eine Stunde falsch.

Entweder habe ich gerade ein massives Brett vorm Kopf oder da stimmt was nicht...

Hi

Das könnte damit zusammen hängen, daß die Funktion ggf. Zulu-Zeit (=GMT, oder eben +0) benutzt.
Wir hier in Deutschland sind in der Alpha-Zeitzone in Alpha-Zeit (MEZ=GMT+1), oder in Bravo-Zeit (MESZ=Sommerzeit, =GMT+2).

Denke, Du 'denkst' in MEZ, der Sketch aber in GMT.
(solltest Du in MESZ 'denken' - sollte Dein Ergebnis eigentlich anders aussehen)

MfG

Daran habe ich auch schon gedacht.

Aber müsste dann nicht der Startzeitpunkt auch verschoben sein?

MfG

Ludacrysis:
in time.h wird auf eine Funktion verwiesen, die mktime heißt.

Es wäre einfacher, Dir zu helfen, wenn Du den Link zu Deiner Bibliothek angeben würdest, da es wohl unterschiedliche gibt.

agmue:
Es wäre einfacher, Dir zu helfen, wenn Du den Link zu Deiner Bibliothek angeben würdest, da es wohl unterschiedliche gibt.

Nicht wirklich. mktime ist eigentlich eine C++ Standard Funktion die da nur nachgebildet wird

Ok, ich glaube es herausgefunden zu haben auch wenn es sich mir nicht erschließt wieso das so ist.

Es scheint mit dem Befehl configTime zu tun zu haben. Der erste Parameter steht für die Zeitzone, wenn man ihn auf 0 lässt oder die Routine start_WiFi nicht ausführt, funktioniert die Berechnung korrekt.

Ein wenig merkwürdig, dass der Befehl mit Verzug reagiert und erst ab einem gewissen Zeitpunkt die anderen Prozesse stört.

Nunja, da es mir aber nicht auf die Stunde ankommt, geht der Kalender eben eine Stunde nach... glaube kaum, dass ich jemals in die Versuchung kommen sollte um Mitternacht den Kalender zu beachten.

Ich habe es mir für die meisten Projekte angewöhnt, intern nur mit UTC zu arbeiten und nur für die Anzeige auf die lokale Zeit umzuwandeln. Dazu nutze ich das Script von Jurs.

Das hat den Vorteil, dass es keine Dopplungen/Sprünge bei der Zeitumstellung gibt, wenn man den Timestamp als primary Key in der Datenbank führt.

Deine Zeiten von der Website mit Z hinten dran deuten auf UTC hin.

Gruß Tommy