Mit MySQL Zeitstempel rechnen

Moin,

ich habe da leider wieder mal ein Problem mit dem MySQL Zeitstempel.

Ich möchte die Differenz von zwei Zeitstempeln bilden, diesmal mit Millisekunden.

Soweit bin ich schon:

const char NewTimestamp[] = "1534030927038", LastTimestamp[] = "1534030923400";

// Differenz ist tatsächlich: 3 s und 638 ms

//***************************************************************************************************************
void unixdiff(uint32_t neuerZeitstempel, uint32_t letzterZeitstempel) {
  uint32_t diff;
  uint8_t ms, ss, mm, hh;
  diff = neuerZeitstempel - letzterZeitstempel;
  ms = diff;
  ss = diff % 60;
  diff /= 60;
  mm = diff % 60;
  diff /= 60;
  hh = diff % 24;
  diff /= 24;
  Serial.print("          Differenz: ");
  Serial.print(diff); Serial.print(F("d "));
  Serial.print(hh); Serial.print(F("h "));
  Serial.print(mm); Serial.print(F("m "));
  Serial.print(ss); Serial.print(F("s "));
  Serial.print(ms); Serial.println(F("ms "));
}
//***************************************************************************************************************

void setup()
{
  Serial.begin(74880);
  uint32_t ts1 = strtoul(NewTimestamp, NULL, 13);
  uint32_t ts2 = strtoul(LastTimestamp, NULL, 13);
  Serial.print("      Aktuelle Zeit: "); Serial.print(NewTimestamp); Serial.print("   nach Umwandlung in Zahl: "); Serial.println(ts1);
  Serial.print("Letzter Zeitstempel: "); Serial.print(LastTimestamp); Serial.print("   nach Umwandlung in Zahl: "); Serial.println(ts2);
  unixdiff(ts1, ts2);
}

void loop() {}

Leider reicht uint32_t wohl nicht vom Wertebereich.
Ich brauche eine Variablentyp mit 13 Stellen.

Und dann hätte ich gerne noch 1534030927038 in 12.08.2018 01:42:07,038 umformatiert

Kann jemand helfen?

Danke und lieben Gruß,
Chris

Meines Wissens hat UNIX Timestamp keine Millisekunden sondern nur Sekunden.
Andererseits woher willst Du die Millisekunden bekommen, da ein RTC nur Sekunden ausgibt?
Grüße Uwe

Oder wie be NTP (Network Time Protocol), Sekunde und Teile davon getrennt halten:

siehe: Structure of the NTP Data packet

z.B.

Reference Timestamp
Seconds (32),
Fraction (32)

Meines Wissens hat UNIX Timestamp keine Millisekunden sondern nur Sekunden.

Doch, kommt aus einer SQL Datenbank.

uint64_t aber dann aufpassen bei einer Ausgabe über Serial.

Hatte ich schon probiert. Ging nicht auf dem ESP8266. Vielleich hast du n Tipp wie ich das zum Laufen bringe?

Der UNIX Timestamp zählt von 1970 an die Sekunden. Du hast dann also etwas Vergleichbares in Millisekunden. Benötigst Du denn die ganze Zeitspanne seit 1970? Bei kürzeren Zeitspannen, in Deinem Beispiel 3638 ms, kannst Du auch den Zeitstempel seit 2000 oder seit Anfang des Jahres nutzen, das erspart Dir große Zahlen.

Ich habe von jursRTCtimeEasy.h das eine oder andere abgeschaut.

Hinweise:

  • Jahr-2038-Problem
  • Schaltsekunden, die erst nach Definition der Unixzeit eingeführt wurden, werden je nach System verschieden behandelt.

Doch, kommt aus einer SQL Datenbank.

Schwachsinn!
Das mag irgendein Timestamp sein.
Aber ganz sicher kein Unix Timestamp.

Wenn du schon eine SQL DB nutzt, dann lass die doch damit rechnen.

Falls die 2 Zeitstempeln nie mehr als c. 4 Monate auseinander sind, einfach die erseten 3 Ziffern weglassen.

Sekunde seit 1.1.1970
1534030927 (August 11, 2018)
1524030927 (April 18, 2018 )

Hi

Wenn Du Deine Zeitstempel um die Millisekunden kürzt, ganz normal mit den dann 32-bit-Zahlen rechnest und Dich selber nur um das dazu zählen der Millisekunden kümmerst?

Nimmt der Compiler uint64_t nicht an, oder streikt 'nur' die Ausgabe via serial.print?
Letzteres ist wohl normal - zumindest Nano und Uno haben sonst mit uint64_t kein Problem.

Für das Zurückwandeln gibt's bestimmt eine Lib, diverse Code-Fetzen habe ich hier im Forum auch schon gesehen, gehen meist den Umweg über 'Sekunden ab 2000'.

MfG

oder streikt 'nur' die Ausgabe via serial.print?

Die Rechenoperatoren funktionieren.
Serial.print versagt

Schwachsinn!
Das mag irgendein Timestamp sein.
Aber ganz sicher kein Unix Timestamp.

Das ist jetzt ein bisschen lustig, denn ich hatte schon mal fast das gleiche Problem, das hast du folgendes selber drauf geantwortet:

combie:
Das kann ich dir sagen!

Alle!
Zumindest alle, welche MySQL und den MySQL Timestamp nutzen.
Wenn man den UnixTimeStamp haben will, muss man das der DB explizit mitteilen.

Aber den MySQL Timestamp auslesen und einfach nur behaupten, das wäre jetzt ein UnixTimeStamp, das kann eigentlich nur ins Versagen führen.
Denn durch einfaches umetikettieren wird auch keine Milch zu Butter.

Okay, ich steck jetzt nicht besonders tief da drin, für mich ist der Unix timestamp das gleiche wie ein MySQL timestamp. Der eine ist dann eben in Sekunden, der andere in Millisekunden. Das ändert aber alles nichts an der Aufgabenstellung.

Es ändert sich auch nichts an der Aufgabenstellung, wenn ich jetzt schreibe, dass ich hier eine S0 Wasseruhr mit einem volkszaehler.org smartmetering auf einem Raspberry Pi 3 logge, dieser über den vzlogger und einer Middleware die Daten in eine MySQL Datenbank speichert. Der vzlogger die Daten zusätzlich über einen Push Server über node-RED an einen MQTT Broker pusht und ich mit einem ESP8266 die Daten vom MQTT Broker subscribe. Und da kommen dann die im Eingangpost erwähnten timestamps her, die ich zur Vereinfachung einfach im Code so definiert habe: "const char NewTimestamp = "1534030927038", LastTimestamp = "1534030923400";"

Ein Rechnen in der Datenbank fällt damit auch aus, spätestens weil ich es nicht will :slight_smile:

Nimmt der Compiler uint64_t nicht an, oder streikt 'nur' die Ausgabe via serial.print?

Das probiere ich jetzt nochmal aus.

Für das Zurückwandeln gibt's bestimmt eine Lib, diverse Code-Fetzen habe ich hier im Forum auch schon gesehen, gehen meist den Umweg über 'Sekunden ab 2000'.

Dast du da mal n heissen Tipp?

Nimmt der Compiler uint64_t nicht an, oder streikt 'nur' die Ausgabe via serial.print?

Der Compiler nimmt uint64_t.
Die serielle Ausgabe streikt und habe deswegen testweise auskommentiert.
Ein Ergebnis gibt es trotzdem nicht :cry:

const char NewTimestamp[] = "1534031527038", LastTimestamp[] = "1533845563400";

//***************************************************************************************************************
void unixdiff(uint64_t neuerZeitstempel, uint64_t letzterZeitstempel) {
  uint64_t diff;
  uint8_t ms, ss, mm, hh;
  diff = neuerZeitstempel - letzterZeitstempel;
  ms = diff;
  ss = diff % 60;
  diff /= 60;
  mm = diff % 60;
  diff /= 60;
  hh = diff % 24;
  diff /= 24;
  Serial.print("          Differenz: ");
//  Serial.print(diff); Serial.print(F("d "));
  Serial.print(hh); Serial.print(F("h "));
  Serial.print(mm); Serial.print(F("m "));
  Serial.print(ss); Serial.print(F("s "));
  Serial.print(ms); Serial.println(F("ms "));
}
//***************************************************************************************************************

void setup()
{
  Serial.begin(74880);
  uint64_t ts1 = strtoul(NewTimestamp, NULL, 13);
  uint64_t ts2 = strtoul(LastTimestamp, NULL, 13);
  Serial.print("      Aktuelle Zeit: ");
  Serial.print(NewTimestamp);
  Serial.print("   nach Umwandlung in Zahl: ");
//  Serial.print(ts1);
  Serial.println("");
  Serial.print("Letzter Zeitstempel: ");
  Serial.print(LastTimestamp);
  Serial.print("   nach Umwandlung in Zahl: ");
//  Serial.print(ts2);
  Serial.println("");
  unixdiff(ts1, ts2);
}

void loop() {}

für mich ist der Unix timestamp das gleiche wie ein MySQL timestamp

Uneinsichtig!
Beharrliche Falschverwendung von definierten Begriffen.
Die Welt hat sich darauf geeinigt, aber du schwimmst beharrlich dagegen.
Alleine.

Das ist jetzt ein bisschen lustig, denn ich hatte schon mal fast das gleiche Problem, das hast du folgendes selber drauf geantwortet:

Natürlich, was soll ich da auch sonst zu sagen.
Offensichtlich hat es nicht gereicht.

Natürlich darfst du gerne in deinen Falschvorstellungen beharren.
Aber dann alleine, bzw. ohne mich.

Hi

Gefunden habe ich nicht viel - aber die hier verlinkte Lib bietet die Umwandlung in beide Richtungen - sofern ich die Innereien halbwegs verstanden habe:
Adafruit, RTC
Dort verlinkt RTClib master.zip
Das Beispiel in der IDE zeigt nur die Nutzung der RTC, in der Lib sind aber diverse Umrechnungen enthalten, Die Dir ganz gut passen müssten.
Dazu die .cpp anschauen, gibt dort verschiedene Aufrufe.

MfG

Meinetwegen uneinsichtig. Ich nenne es unwichtig an dieser Stelle. Gegeben sind zwei const char NewTimestamp = "1534030927038", LastTimestamp = "1534030923400"; So einem char ist es doch völlig egal für was man die Zeichen verwendet..... Den interessiert es nicht ob er ein Unix oder ein MySQL timestamp ist oder was anderes.
Wenns denn irgendjemandem hilft benenn ich eben den Topic vom Unix Timestamp nach MySQL timestamp um. Daran soll es nicht scheitern. So, erledigt.

Machen wir es halt wie in der Schule....

GEGEBEN:
Zwei Zeitstempel in Millisekunden nach 1970:
const char NewTimestamp = "1534030927038", LastTimestamp = "1534030923400";

GESUCHT:
1.) Die Differenz der beiden Zeitstempel in Millisekunden.
2.) Den Zeitstempel 1534030927038 umformatieren in 12.08.2018 01:42:07,038

@postmaster-ino: Danke dir, muss ich mir noch anschauen :slight_smile:

Lieben Gruß,
Chris

themanfrommoon:
. . .
GESUCHT:
. . .
2.) Den Zeitstempel 1534030927038 umformatieren in 12.08.2018 01:42:07,038
. . .
Das wäre in UTC oder im Lokalen Zeit mit der Zeitumstellung auf Sommerzeit ggf. Winterzeit.

Die Zeit, die gerade in Deutschland ist. Wie die jetzt genau definiert ist.....?

Hi

Bravo-Zeit (in Alpha-Zeitzone)

Oder wie meinen?

Wenn man Dein Programm mit der Ausgabe von 64 Bit Werten von combie verbindet, dann sieht man, daß strtoul() nicht tut, was Du erwartest.

const char NewTimestamp[] = "1534031527038", LastTimestamp[] = "1533845563400";
const size_t BufferSize = 64 + 1 + 1; // 64bit +Vorzeichen +NullByte
char buffer[BufferSize];

// combie: Ausgabe von 64 Bit Werten https://forum.arduino.cc/index.php?topic=563311.0
template<typename T> char* bigToStr(char* buffer, T value, uint8_t base = 10)
{
  bool negative = value < 0;
  if (negative) value *= -1LL;

  char* ptr = buffer + BufferSize;
  *(--ptr)  = 0;
  switch (base)
  {

    case  2: while (value) // BINARY
      {
        *(--ptr)  = '0' + (value & 0x01);
        value >>= 1;
      }
      break;

    case  8: while (value) // OKTAL
      {
        *(--ptr)  = '0' + (value & 0x07);
        value >>= 3;
      }
      break;

    case 16: while (value) // HEX
      {
        *(--ptr)  = '0' + (value & 0x0f);
        if (*ptr > '9') *ptr += 'A' - '9' - 1;
        value >>= 4;
      }
      break;

    default: while (value) // UNIVERSAL
      {
        uint8_t rest = value % base;
        *(--ptr)  = '0' + rest;
        if (*ptr > '9') *ptr += 'A' - '9' - 1;
        value /= base;
      }
      break;
  }
  if (negative)  *(--ptr)  = '-';
  return ptr;
}

//***************************************************************************************************************
void unixdiff(uint64_t neuerZeitstempel, uint64_t letzterZeitstempel) {
  uint64_t diff;
  uint8_t ms, ss, mm, hh;
  diff = neuerZeitstempel - letzterZeitstempel;
  ms = diff;
  ss = diff % 60;
  diff /= 60;
  mm = diff % 60;
  diff /= 60;
  hh = diff % 24;
  diff /= 24;
  Serial.print("          Differenz: ");
  Serial.print(bigToStr(buffer, diff));
  Serial.print(F("d "));
  Serial.print(hh); Serial.print(F("h "));
  Serial.print(mm); Serial.print(F("m "));
  Serial.print(ss); Serial.print(F("s "));
  Serial.print(ms); Serial.println(F("ms "));
}
//***************************************************************************************************************

void setup()
{
  Serial.begin(9600);
  uint64_t ts1 = strtoul(NewTimestamp, NULL, 13);
  uint64_t ts2 = strtoul(LastTimestamp, NULL, 13);
  Serial.print("      Aktuelle Zeit: ");
  Serial.print(NewTimestamp);
  Serial.print("   nach Umwandlung in Zahl: ");
  Serial.println(bigToStr(buffer, ts1));
  Serial.println("");
  Serial.print("Letzter Zeitstempel: ");
  Serial.print(LastTimestamp);
  Serial.print("   nach Umwandlung in Zahl: ");
  Serial.println(bigToStr(buffer, ts2));
  Serial.println("");
  unixdiff(ts1, ts2);
}

void loop() {}
[sup]      Aktuelle Zeit: 1534031527038   nach Umwandlung in Zahl: 4294967295

Letzter Zeitstempel: 1533845563400   nach Umwandlung in Zahl: 4294967295

          Differenz: d 0h 0m 0s 0ms 
[/sup]

Hi

Da Du nur die unteren 32 Bit benutzt (und Diese wohl gesetzt sind), kommt diese Zahl heraus.
4294967295 = 2^32-1 (der Linux-Taschenrechner hat direkt eine Anzeige in Binär/Hex/Octal)

Von der Theorie her müsste der combie-Code laufen - zwar schon 'weg kopiert', aber noch unbespielt.

MfG

postmaster-ino:
Von der Theorie her müsste der combie-Code laufen …

Auch in der Praxis, danke dafür :slight_smile:

postmaster-ino:
Da Du nur die unteren 32 Bit benutzt …

Da strtol nicht ausreicht, würde man strtoll (string to long long) benötigen. Auf die Schnelle habe ich nichts Passendes gefunden, daher werkelt nun my_strtoll:

const char NewTimestamp[] = "1534031527038", LastTimestamp[] = "1533845563400";
const size_t BufferSize = 64 + 1 + 1; // 64bit +Vorzeichen +NullByte
char buffer[BufferSize];

// combie: Ausgabe von 64 Bit Werten https://forum.arduino.cc/index.php?topic=563311.0
template<typename T> char* bigToStr(char* buffer, T value, uint8_t base = 10)
{
  bool negative = value < 0;
  if (negative) value *= -1LL;

  char* ptr = buffer + BufferSize;
  *(--ptr)  = 0;
  switch (base)
  {

    case  2: while (value) // BINARY
      {
        *(--ptr)  = '0' + (value & 0x01);
        value >>= 1;
      }
      break;

    case  8: while (value) // OKTAL
      {
        *(--ptr)  = '0' + (value & 0x07);
        value >>= 3;
      }
      break;

    case 16: while (value) // HEX
      {
        *(--ptr)  = '0' + (value & 0x0f);
        if (*ptr > '9') *ptr += 'A' - '9' - 1;
        value >>= 4;
      }
      break;

    default: while (value) // UNIVERSAL
      {
        uint8_t rest = value % base;
        *(--ptr)  = '0' + rest;
        if (*ptr > '9') *ptr += 'A' - '9' - 1;
        value /= base;
      }
      break;
  }
  if (negative)  *(--ptr)  = '-';
  return ptr;
}

//***************************************************************************************************************
void unixdiff(uint64_t neuerZeitstempel, uint64_t letzterZeitstempel) {
  uint64_t diff;
  uint32_t ms, ss, mm, hh;
  diff = neuerZeitstempel - letzterZeitstempel;
  Serial.print("          Differenz: ");
  Serial.print(bigToStr(buffer, diff));
  Serial.print('\t');
  ms = diff % 1000;
  diff /= 1000;
  ss = diff % 60;
  diff /= 60;
  mm = diff % 60;
  diff /= 60;
  hh = diff % 24;
  diff /= 24;
  Serial.print(bigToStr(buffer, diff)); Serial.print(F("d "));
  Serial.print(hh); Serial.print(F("h "));
  Serial.print(mm); Serial.print(F("m "));
  Serial.print(ss); Serial.print(F("s "));
  Serial.print(ms); Serial.println(F("ms "));
}
//***************************************************************************************************************

uint64_t my_strtoull(const char* zeichenkette)
{
  uint64_t wert = 0;
  byte j = 0;
  do
  {
    wert *= 10;
    wert += zeichenkette[j] - '0';
    j++;
  } while (zeichenkette[j] != '\0');
  return wert;
}

void setup()
{
  Serial.begin(9600);
  uint64_t ts1 = my_strtoull(NewTimestamp);
  uint64_t ts2 = my_strtoull(LastTimestamp);
  Serial.print("      Aktuelle Zeit: ");
  Serial.print(NewTimestamp);
  Serial.print("   nach Umwandlung in Zahl: ");
  Serial.println(bigToStr(buffer, ts1));
  Serial.println("");
  Serial.print("Letzter Zeitstempel: ");
  Serial.print(LastTimestamp);
  Serial.print("   nach Umwandlung in Zahl: ");
  Serial.println(bigToStr(buffer, ts2));
  Serial.println("");
  unixdiff(ts1, ts2);
}

void loop() {}
[sup]      Aktuelle Zeit: 1534031527038   nach Umwandlung in Zahl: 1534031527038

Letzter Zeitstempel: 1533845563400   nach Umwandlung in Zahl: 1533845563400

          Differenz: 185963638 2d 3h 39m 23s 638ms 
[/sup]