Wie konvertiert man std :: chrono :: time_point in die DateTime-Zeichenkette mit Sekundenbruchteilen? Zum Beispiel: "10-10-2012 12: 38: 40.123456".Wie konvertiert man std :: chrono :: time_point in die DateTime-Zeichenkette mit Sekundenbruchteilen?
Antwort
Wenn system_clock, diese Klasse hat time_t Konvertierung.
#include <iostream>
#include <chrono>
#include <ctime>
using namespace std::chrono;
int main()
{
system_clock::time_point p = system_clock::now();
std::time_t t = system_clock::to_time_t(p);
std::cout << std::ctime(&t) << std::endl; // for example : Tue Sep 27 14:21:13 2011
}
Beispiel Ergebnis:
Thu Oct 11 19:10:24 2012
EDIT: Aber Time_t enthält keine Sekundenbruchteile. Alternative Möglichkeit ist die Verwendung der Funktion time_point :: time_since_epoch(). Diese Funktion gibt die Dauer aus der Epoche zurück. Beispiel folgt Millisekunden Auflösung ist fraktional.
#include <iostream>
#include <chrono>
#include <ctime>
using namespace std::chrono;
int main()
{
high_resolution_clock::time_point p = high_resolution_clock::now();
milliseconds ms = duration_cast<milliseconds>(p.time_since_epoch());
seconds s = duration_cast<seconds>(ms);
std::time_t t = s.count();
std::size_t fractional_seconds = ms.count() % 1000;
std::cout << std::ctime(&t) << std::endl;
std::cout << fractional_seconds << std::endl;
}
Beispiel Ergebnis:
Thu Oct 11 19:10:24 2012
925
In der Regel können Sie diese nicht in irgendeiner Art und Weise einfach tun. time_point
ist im Wesentlichen nur eine duration
aus einer Clock-spezifischen Epoche.
Wenn Sie ein std::chrono::system_clock::time_point
haben, dann können Sie std::chrono::system_clock::to_time_t
verwenden, um die time_point
zu einem time_t
, zu konvertieren und dann verwenden, um die normalen C-Funktionen wie ctime
oder strftime
es zu formatieren.
Beispielcode:
std::chrono::system_clock::time_point tp = std::chrono::system_clock::now();
std::time_t time = std::chrono::system_clock::to_time_t(tp);
std::tm timetm = *std::localtime(&time);
std::cout << "output : " << std::put_time(&timetm, "%c %Z") << "+"
<< std::chrono::duration_cast<std::chrono::milliseconds>(tp.time_since_epoch()).count() % 1000 << std::endl;
Das Problem mit dieser Lösung ist, dass std :: localtime nicht Thread-sicher ist. – minexew
Selbsterklär Code folgt dem zunächst ein std::tm
zu 10-10-2012 12.38.40 entsprechenden schafft umwandelt, das zu einem std::chrono::system_clock::time_point
, 0,123456 Sekunden lang hinzufügt, und druckt das dann aus, indem es zurück in std::tm
konvertiert. Wie man mit den Sekundenbruchteilen umgeht, ist im allerletzten Schritt.
#include <iostream>
#include <chrono>
#include <ctime>
int main()
{
// Create 10-10-2012 12:38:40 UTC as a std::tm
std::tm tm = {0};
tm.tm_sec = 40;
tm.tm_min = 38;
tm.tm_hour = 12;
tm.tm_mday = 10;
tm.tm_mon = 9;
tm.tm_year = 112;
tm.tm_isdst = -1;
// Convert std::tm to std::time_t (popular extension)
std::time_t tt = timegm(&tm);
// Convert std::time_t to std::chrono::system_clock::time_point
std::chrono::system_clock::time_point tp =
std::chrono::system_clock::from_time_t(tt);
// Add 0.123456 seconds
// This will not compile if std::chrono::system_clock::time_point has
// courser resolution than microseconds
tp += std::chrono::microseconds(123456);
// Now output tp
// Convert std::chrono::system_clock::time_point to std::time_t
tt = std::chrono::system_clock::to_time_t(tp);
// Convert std::time_t to std::tm (popular extension)
tm = std::tm{0};
gmtime_r(&tt, &tm);
// Output month
std::cout << tm.tm_mon + 1 << '-';
// Output day
std::cout << tm.tm_mday << '-';
// Output year
std::cout << tm.tm_year+1900 << ' ';
// Output hour
if (tm.tm_hour <= 9)
std::cout << '0';
std::cout << tm.tm_hour << ':';
// Output minute
if (tm.tm_min <= 9)
std::cout << '0';
std::cout << tm.tm_min << ':';
// Output seconds with fraction
// This is the heart of the question/answer.
// First create a double-based second
std::chrono::duration<double> sec = tp -
std::chrono::system_clock::from_time_t(tt) +
std::chrono::seconds(tm.tm_sec);
// Then print out that double using whatever format you prefer.
if (sec.count() < 10)
std::cout << '0';
std::cout << std::fixed << sec.count() << '\n';
}
Für mich ist diese Ausgänge:
10-10-2012 12:38:40.123456
Ihre std::chrono::system_clock::time_point
kann oder nicht präzise genug sein, Mikrosekunden zu halten.
aktualisieren
Ein einfacherer Weg ist, einfach this date library zu verwenden. Der Code vereinfacht bis auf (unter Verwendung von C++ 14 Dauer Literale):
#include "date.h"
#include <iostream>
#include <type_traits>
int
main()
{
using namespace date;
using namespace std::chrono;
auto t = sys_days{10_d/10/2012} + 12h + 38min + 40s + 123456us;
static_assert(std::is_same<decltype(t),
time_point<system_clock, microseconds>>{}, "");
std::cout << t << '\n';
}
die Ausgänge:
2012-10-10 12:38:40.123456
Sie können die static_assert
überspringen, wenn Sie nicht beweisen müssen, dass die Art der t
ist ein std::chrono::time_point
.
Wenn die Ausgabe nicht nach Ihrem Geschmack ist, können Sie zum Beispiel würde wirklich gerne dd-mm-yyyy Ordnung, man kann:
#include "date.h"
#include <iomanip>
#include <iostream>
int
main()
{
using namespace date;
using namespace std::chrono;
using namespace std;
auto t = sys_days{10_d/10/2012} + 12h + 38min + 40s + 123456us;
auto dp = floor<days>(t);
auto time = make_time(t-dp);
auto ymd = year_month_day{dp};
cout.fill('0');
cout << ymd.day() << '-' << setw(2) << static_cast<unsigned>(ymd.month())
<< '-' << ymd.year() << ' ' << time << '\n';
}
das gibt genau die gewünschte Ausgabe:
10-10-2012 12:38:40.123456
aktualisiert
Hier ist, wie fein säuberlich mit Millisekunden Genauigkeit der aktuellen Uhrzeit UTC zu formatieren:
#include "date.h"
#include <iostream>
int
main()
{
using namespace std::chrono;
std::cout << date::format("%F %T\n", time_point_cast<milliseconds>(system_clock::now()));
}
, die nur für mich ausgegeben:
2016-10-17 16:36:02.975
C++ 17 ermöglicht es Ihnen, time_point_cast<milliseconds>
mit floor<milliseconds>
zu ersetzen. Bis dahin ist date::floor
in "date.h"
verfügbar.
Dies wird derzeit dem C++ - Standardkomitee vorgeschlagen: https://howardhinnant.github.io/date/d0355r1.html –
Das funktionierte für mich für ein Format wie YYYY.MM.DD-HH.MM.SS.fff. Der Versuch, diesen Code zu machen fähig ist jedes String-Format zu akzeptieren, wie das Rad neu erfinden sein wird (dh es gibt Funktionen für das alles in-Boost.
std::chrono::system_clock::time_point string_to_time_point(const std::string &str)
{
using namespace std;
using namespace std::chrono;
int yyyy, mm, dd, HH, MM, SS, fff;
char scanf_format[] = "%4d.%2d.%2d-%2d.%2d.%2d.%3d";
sscanf(str.c_str(), scanf_format, &yyyy, &mm, &dd, &HH, &MM, &SS, &fff);
tm ttm = tm();
ttm.tm_year = yyyy - 1900; // Year since 1900
ttm.tm_mon = mm - 1; // Month since January
ttm.tm_mday = dd; // Day of the month [1-31]
ttm.tm_hour = HH; // Hour of the day [00-23]
ttm.tm_min = MM;
ttm.tm_sec = SS;
time_t ttime_t = mktime(&ttm);
system_clock::time_point time_point_result = std::chrono::system_clock::from_time_t(ttime_t);
time_point_result += std::chrono::milliseconds(fff);
return time_point_result;
}
std::string time_point_to_string(std::chrono::system_clock::time_point &tp)
{
using namespace std;
using namespace std::chrono;
auto ttime_t = system_clock::to_time_t(tp);
auto tp_sec = system_clock::from_time_t(ttime_t);
milliseconds ms = duration_cast<milliseconds>(tp - tp_sec);
std::tm * ttm = localtime(&ttime_t);
char date_time_format[] = "%Y.%m.%d-%H.%M.%S";
char time_str[] = "yyyy.mm.dd.HH-MM.SS.fff";
strftime(time_str, strlen(time_str), date_time_format, ttm);
string result(time_str);
result.append(".");
result.append(to_string(ms.count()));
return result;
}
Wenn tatsächlich nur 1 MS vorhanden ist, erhalten Sie ein falsches Ergebnis, wenn to_String() konvertiert wird long (ms.count (()). du musst die millisekunden mit einem sprintf_s konvertieren –
Ich habe dies auf der akzeptierte Antwort in einem Kommentar setzen würde, denn das ist, wo es hingehört, aber ich kann nicht. Also, falls jemand unzuverlässige Ergebnisse bekommt, könnte dies sein, warum.
der akzeptierte Antwort Seien sie vorsichtig, es schlägt fehl, wenn die time_point vor der Epoche ist.
Diese Codezeile:
std::size_t fractional_seconds = ms.count() % 1000;
werden unerwartete Werte ergeben, wenn ms.count() negativ ist (da size_t keine negativen Werte enthalten soll).
Und, wie die Bruchteilsekunden zur Ausgabezeichenfolge hinzuzufügen? –
time_t enthält keine Sekundenbruchteile. Ich füge mehr Beispielcode hinzu. –
Danke! Jetzt sind die Antworten besser und näher an dem, was die OP gefragt hat. –