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; }