Time format von c++ nach c#



  • Hallo zusammen

    in meinem c++ Programm ermittle ich die aktuelle Zeit und sende sie über mqtt im json Format an eine c# Applikation.
    Diese Applikation sollte nun den Zeitstempel die im Json als string abgelegt ist wieder interpretieren.

    In c# macht man dies normalerweise mit dem DateTime Datentyp.

    Doch wie schaffe ich das nun in c++ den Zeitspempel so bereit zu stellen dass dies c# wieder deserialisieren kann.

    Hierzu habe ich mir zunächst mal das Beispiel von std::time_point angeschaut.

    Und folgendes übernommen:

    auto now = std::chrono::system_clock::now();
    auto time = std::chrono::system_clock::to_time_t(now  - std::chrono::hours(24));
    auto timestamp =  std::put_time(std::localtime(&time), "%F %T");
    

    damit ich dann zunächst mal das Format in der Form
    2011-10-25 12:00:08
    habe.

    hier aber schon mein erstes Problem.
    Der Compiler (VS 2017) meldet:

    Error C4996: 'localtime': This function or variable may be unsafe. Consider using localtime_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details. (27)

    std::localtime_s gibt es ja nicht. Also localtime_s aus c verwenden.

    1. wieso ist localtime zusätlich in der std drin und wieso localtime_s nicht
    2. wieso verwenden alle Beipiele noch die veralteten Versionen.

    ersetze ich nun std::localtime durch localtime_s
    wie es hier im Beispiel gezeigt wird.

    sollte das so aussehen:

    struct tm buf;
    auto now = std::chrono::system_clock::now();
    auto time = std::chrono::system_clock::to_time_t(now  - std::chrono::hours(24));
    localtime_s(&time, &buf);
    auto timestamp =  std::put_time(&buf, "%F %T");
    

    jetzt erhalte ich folgende Fehlermeldungen vom compiler:

    Error C2664: 'errno_t localtime_s(tm *const ,const time_t *const )': cannot convert argument 1 from '__time64_t *' to 'tm *const ' (28)

    Also die Parameter von localtime_s sind vertauscht. Ist das ein Fehler in der Hilfe oder liegt das Problem woanders.

    Desweiteren wie erhalte ich von std::put_time nun einen string. Im Beispiel von std::chrono::time_point wird das einfach an cout ausgegeben.

    wenn ich das mit der json lib in nen string schreiben will bekomme ich nen Fehler.

    Muss ich das zuerst in nen stringstream schreiben oder mit asctime_s wandeln.

    Wieso ist das denn in c++ so kompliziert im gegensatz zu c#.

    Wie ich das Zeitformat dann in das Format von c# bekomme ist mir auch noch nicht klar-



  • https://en.cppreference.com/w/c/chrono/localtime behauptet dass localtime_s ein C11 Feature wäre. Ich hätte es mit Godbolt probiert, scheint kein aktuelles System zu haben.

    Die localtime_s die du versuchst zu verwenden ist dagegen eine MSVC Erweiterung. Und die hat die Parameter in der umgekehrten Reihenfolge.

    Wieso ist das denn in c++ so kompliziert im gegensatz zu c#

    Willkommen in der wundervollen Welt von C++.

    Wie ich das Zeitformat dann in das Format von c# bekomme ist mir auch noch nicht klar-

    Äh. Notfalls mit sprintf?



  • @booster Mach alles in epoch, also in Sekunden seit dem 01.01.1970.

    Das ist dann ein Zahlenwert. Die 32-Bit Grenze wird bis 2038 auch fallen.



  • du kannst ja auch einfach _CRT_SECURE_NO_WARNINGS definieren.



  • Am einfachsten nimmst du Howard Hinnants date.h dazu -> https://github.com/HowardHinnant/date

    Damit:

    auto now = std::chrono::system_clock::now();
    auto t = now - std::chrono::hours(24);
    std::string s = date::format("%F %T", t);
    

    Wenn du mit Zeitzonen arbeiten willst, schau dir auch H. Hinnants tz.h an bzw. lies https://github.com/HowardHinnant/date/wiki/Examples-and-Recipes#localtime



  • @hustbaer sagte in Time format von c++ nach c#:

    https://en.cppreference.com/w/c/chrono/localtime behauptet dass localtime_s ein C11 Feature wäre. Ich hätte es mit Godbolt probiert, scheint kein aktuelles System zu haben.

    jo so steht es da, ein c11 feature. Und wie komme ich an das c11 feature ran und nicht an die MSVC Erweiterung?
    Was ist godbolt und wer oder was "scheint kein aktuelles System zu haben"

    struct tm buf;
    auto time = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now() - std::chrono::hours(24));
    localtime_s(&buf, &time);
    stringstream ss;
    ss << std::put_time(&buf, "%F %T");
    auto timestamp = ss.str();
    

    ganz einfach in einem 6 Zeiler was in c# mit einem 1 Zeiler geht.

    Dieses Format lässt sich dann aber zum Glück dann in ein Datetime in c# wandeln. Geht doch! Wieso einfach wenn es auch kompliziert geht.

    Also manchmal ist das ganze ja schon ziemlich suspekt.

    1. Beispiele passen nicht, sind veraltet.
    2. Wieso muss man das Zeitformat überhaupt erst 5 mal umwandeln.
    3. Wieso ist das so kompliziert dass einem auch noch dazu geraten wird eine lib von github runter zu laden
    4. Und dann auch noch solche pragmatischen Lösungen wie einfach _CRT_SECURE_NO_WARNINGS definieren.
      Damit es beim nächsten Compiler Update auf jeden Fall kracht.


  • @booster sagte in Time format von c++ nach c#:

    Was ist godbolt

    Matt Godbolt. Jemand, der einen "Compiler Explorer" entwickelt hat. Großartiges Tool -> https://gcc.godbolt.org

    Also manchmal ist das ganze ja schon ziemlich suspekt.

    1. Beispiele passen nicht, sind veraltet.

    Tja.

    1. Wieso muss man das Zeitformat überhaupt erst 5 mal umwandeln.

    Solltest du besser nicht, da du so Präzision verlierst, da time_t in Sekunden ist. Deine system_clock hat aber vermutlich eine höhere Präzision.

    1. Wieso ist das so kompliziert dass einem auch noch dazu geraten wird eine lib von github runter zu laden

    Diese lib wird (so ähnlich) in C++20 vorhanden sein. Sozusagen "from future import date", wenn es Python wäre.
    Es ist so kompliziert, weil die C++-Zeittypen unglaublich viele Dinge unterstützen. Wie zum Beispiel verschiedene Uhren, zum Beispiel die GPS-Uhr. Es gibt Schaltsekunden, Schalttage, sich ändernde Zeitzonen, ... Datumsberechnung ist nicht einfach. Du kannst verschiedene Datentypen für die Uhr bzw. die Länge wählen. Das alles typsicher. Dennoch ein Punkt für dich: ohne das date.h sind gewissen Dinge nervig zu implementieren.



  • @booster sagte in Time format von c++ nach c#:

    jo so steht es da, ein c11 feature. Und wie komme ich an das c11 feature ran und nicht an die MSVC Erweiterung?

    Na vermutlich gar nicht wenn du C++ verwendest. Und vermutlich nichtmal wenn du C verwendest. Weil halt

    scheint kein aktuelles System zu haben.

    was "scheint kein aktuelles System zu haben"

    Na die optionale (!) Erweiterung die localtime_s enthält.



  • @booster sagte in Time format von c++ nach c#:

    1. Und dann auch noch solche pragmatischen Lösungen wie einfach _CRT_SECURE_NO_WARNINGS definieren.
      Damit es beim nächsten Compiler Update auf jeden Fall kracht.

    naja eigentlich sorgt diese anweisung nur dafür, dass "gefährliche" funktionen der c-standardbibliothek (gets, scanf, localtime usw) nicht durch microsoft-spezifische funktionen mit _s hinten dran ersetzt werden müssen. 😔

    aber warum bietet c# eigentlich keine möglichkeit, den unixzeitstempel in lokalzeit umzuwandeln?🤔



  • @Wade1234 sagte in Time format von c++ nach c#:

    aber warum bietet c# eigentlich keine möglichkeit, den unixzeitstempel in lokalzeit umzuwandeln?🤔

    Ich beantworte mal deine Frage: https://docs.microsoft.com/de-de/dotnet/api/system.datetimeoffset.fromunixtimeseconds?view=netframework-4.7.2



  • und warum wird das dann nicht verwendet?



  • @Wade1234 sagte in Time format von c++ nach c#:

    und warum wird das dann nicht verwendet?

    Die Präzision spielt eigentlich keine so große Rolle. Schaden tut sie allerdings auch nicht. Vorteil die Zeit war leserlich in der json Struktur. Aber auch nicht entscheidend.

    also mit

    auto now = std::chrono::system_clock::now();
    

    erhalte ich einen time_point. Den wandle ich dann mit

    now.time_since_epoch().count();
    

    in einen int ?? Den kann ich dann an c# übertragen. Richtig?



  • @booster hast du es versucht? wenn ja: funktionierts? wenn nein: was ist falsch?



  • @Swordfish

    ja habe es versucht.
    ja es funktioniert.
    mir war nur nicht klar ob das dann die richtige vorgehensweise ist.
    Aber danke.



  • es gibt doch system_clock::to_time_t, was, wenn ich das jetzt nicht falsch sehe, den unixzeitstempel ergibt. den kannst du dann an c# übertragen und da umwandeln. ganz ohne aufwand und ohne #define _CRT_SECURE_NO_WARNINGS.😀



  • @Wade1234 sagte in Time format von c++ nach c#:

    es gibt doch system_clock::to_time_t, was, wenn ich das jetzt nicht falsch sehe, den unixzeitstempel ergibt

    ja, und was macht time_since_epoch()?



  • wenn ich das richtig sehe, mikrosekunden dran hängen. keine ahnung, dein problem ist ja gelöst.



  • Problem ist gelöst. Das mit dem to_time_t hatte ich mir auch angeschaut. Aber nicht ganz verstanden was der unterschied ist zu time_since_epoch().

    Darum habe ich gefragt ob meine Lösung die richtige ist. Man will ja nicht nur das Problem lösen sondern auch was dazu lernen.



  • Die Genauigkeit von time_t ist implementierungsspezifisch.
    https://en.cppreference.com/w/cpp/chrono/system_clock/to_time_t



  • naja time_t ist immer eine ganze anzahl von sekunden seit dem 1.1.1970, das ist für uhrzeiten eigentlich genau genug.

    also ich würde dann eher sagen, dass to_time_t das richtige ist, weil das ja auch das ist, was fromunixtimeseconds unter c# dann erwartet. aber warum funktioniert time_since_epoch dann?


Log in to reply