How to convert std::chrono::time_point to calendar datetime string with fractional seconds?

匿名 (未验证) 提交于 2019-12-03 02:42:02

问题:

How to convert std::chrono::time_point to calendar datetime string with fractional seconds? For example: "10-10-2012 12:38:40.123456".

回答1:

If system_clock, this class have time_t conversion.

#include  #include  #include   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 

example result:

Thu Oct 11 19:10:24 2012 

EDIT: But, time_t does not contain fractional seconds. Alternative way is to use time_point::time_since_epoch() function. This function returns duration from epoch. Follow example is milli second resolution's fractional.

#include  #include  #include   using namespace std::chrono;  int main() {   high_resolution_clock::time_point p = high_resolution_clock::now();    milliseconds ms = duration_cast(p.time_since_epoch());    seconds s = duration_cast(ms);   std::time_t t = s.count();   std::size_t fractional_seconds = ms.count() % 1000;    std::cout 

example result:

Thu Oct 11 19:10:24 2012  925 


回答2:

Self-explanatory code follows which first creates a std::tm corresponding to 10-10-2012 12:38:40, converts that to a std::chrono::system_clock::time_point, adds 0.123456 seconds, and then prints that out by converting back to a std::tm. How to handle the fractional seconds is in the very last step.

#include  #include  #include   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  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() 

For me this outputs:

10-10-2012 12:38:40.123456 

Your std::chrono::system_clock::time_point may or may not be precise enough to hold microseconds.

Update

An easier way is to just use this date library. The code simplifies down to (using C++14 duration literals):

#include "date.h" #include  #include   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>{}, "");     std::cout 

which outputs:

2012-10-10 12:38:40.123456 

You can skip the static_assert if you don't need to prove that the type of t is a std::chrono::time_point.

If the output isn't to your liking, for example you would really like dd-mm-yyyy ordering, you could:

#include "date.h" #include  #include   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(t);     auto time = make_time(t-dp);     auto ymd = year_month_day{dp};     cout.fill('0');     cout (ymd.month())          

which gives exactly the requested output:

10-10-2012 12:38:40.123456 

Update

Here is how to neatly format the current time UTC with milliseconds precision:

#include "date.h" #include   int main() {     using namespace std::chrono;     std::cout (system_clock::now())); } 

which just output for me:

2016-10-17 16:36:02.975 

C++17 will allow you to replace time_point_cast with floor. Until then date::floor is available in "date.h".

std::cout (system_clock::now())); 


回答3:

In general, you can't do this in any straightforward fashion. time_point is essentially just a duration from a clock-specific epoch.

If you have a std::chrono::system_clock::time_point, then you can use std::chrono::system_clock::to_time_t to convert the time_point to a time_t, and then use the normal C functions such as ctime or strftime to format it.


Example 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 (tp.time_since_epoch()).count() % 1000 


回答4:

I would have put this in a comment on the accepted answer, since that's where it belongs, but I can't. So, just in case anyone gets unreliable results, this could be why.

Be careful of the accepted answer, it fails if the time_point is before the epoch.

This line of code:

std::size_t fractional_seconds = ms.count() % 1000; 

will yield unexpected values if ms.count() is negative (since size_t is not meant to hold negative values).



回答5:

This worked for me for a format like YYYY.MM.DD-HH.MM.SS.fff. Attempting to make this code capable of accepting any string format will be like reinventing the wheel (i.e. there are functions for all this 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(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; } 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!