Comment convertir std::chrono::time_point
à la chaîne date/heure du calendrier avec des fractions de secondes?
Par exemple:
"10-10-2012 12:38:40.123456"
Si system_clock, cette classe a une conversion time_t.
#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
}
exemple de résultat:
Thu Oct 11 19:10:24 2012
EDIT: Mais time_t ne contient pas de fractions de secondes. Une autre méthode consiste à utiliser la fonction time_point :: time_since_Epoch (). Cette fonction renvoie la durée de Epoch. Suivez l'exemple est la résolution fractionnaire en millisecondes.
#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;
}
exemple de résultat:
Thu Oct 11 19:10:24 2012
925
Suit le code explicite qui crée le premier un std::tm
correspondant au 10-10-2012 12:38:40, convertit cela en un std::chrono::system_clock::time_point
, ajoute 0,123456 seconde, puis l’imprime en reconvertissant en un std::tm
. La dernière étape consiste à gérer les secondes fractionnelles.
#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';
}
Pour moi cela génère:
10-10-2012 12:38:40.123456
Votre std::chrono::system_clock::time_point
peut être ou ne pas être assez précis pour contenir des microsecondes.
Mettre à jour
Un moyen plus simple consiste simplement à utiliser cette bibliothèque de dates . Le code se simplifie jusqu'à (en utilisant des littéraux de durée C++ 14):
#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';
}
qui produit:
2012-10-10 12:38:40.123456
Vous pouvez ignorer le static_assert
si vous n’avez pas besoin de prouver que le type de t
est un std::chrono::time_point
.
Si la sortie ne vous convient pas, par exemple, vous aimeriez vraiment commander jj-mm-aaaa, vous pouvez:
#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';
}
ce qui donne exactement le résultat demandé:
10-10-2012 12:38:40.123456
Mettre à jour
Voici comment formater proprement le temps UTC actuel avec une précision de quelques millisecondes:
#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()));
}
qui vient de sortir pour moi:
2016-10-17 16:36:02.975
C++ 17 vous permettra de remplacer time_point_cast<milliseconds>
avec floor<milliseconds>
. Jusque là date::floor
est disponible dans "date.h"
.
std::cout << date::format("%F %T\n", date::floor<milliseconds>(system_clock::now()));
En général, vous ne pouvez pas le faire de manière simple. time_point
est essentiellement juste un duration
d’une époque spécifique à une horloge.
Si tu as un std::chrono::system_clock::time_point
, alors vous pouvez utiliser std::chrono::system_clock::to_time_t
pour convertir le time_point
à un time_t
, puis utilisez les fonctions C normales telles que ctime
ou strftime
pour le formater.
Exemple de code:
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;
Cela a fonctionné pour moi pour un format tel que YYYY.MM.DD-HH.MM.SS.fff. Vouloir rendre ce code capable d’accepter n’importe quel format de chaîne reviendra à réinventer la roue (c’est-à-dire qu’il existe des fonctions pour tout cela dans 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;
}
J'aurais mis cela dans un commentaire sur la réponse acceptée, puisque c'est là sa place, mais je ne peux pas. Donc, juste au cas où quelqu'un obtiendrait des résultats peu fiables, cela pourrait être la raison.
Faites attention à la réponse acceptée, elle échouera si le time_point est avant l’époque.
Cette ligne de code:
std::size_t fractional_seconds = ms.count() % 1000;
produira des valeurs inattendues si ms.count () est négatif (puisque size_t n'est pas censé contenir des valeurs négatives).
Dans mon cas, j'utilise chrono et la fonction c localtime_r qui est thread-safe (contrairement à std :: localtime).
#include <iostream>
#include <chrono>
#include <ctime>
#include <time.h>
#include <iomanip>
int main() {
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
std::time_t currentTime = std::chrono::system_clock::to_time_t(now);
std::chrono::milliseconds now2 = std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_Epoch());
struct tm currentLocalTime;
localtime_r(¤tTime, ¤tLocalTime);
char timeBuffer[80];
std::size_t charCount { std::strftime( timeBuffer, 80,
"%b %d %T",
¤tLocalTime)
};
if (charCount == 0) return -1;
std::cout << timeBuffer << "." << std::setfill('0') << std::setw(3) << now2.count() % 1000 << std::endl;
return 0;
}