如何将std :: chrono :: time_point转换为具有小数秒的日历date时间string?

如何将std :: chrono :: time_point转换为具有小数秒的日历date时间string? 例如:“10-10-2012 12:38:40.123456”。

如果system_clock,这个类有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 } 

示例结果:

 Thu Oct 11 19:10:24 2012 

编辑:但是,time_t不包含小数秒。 另一种方法是使用time_point :: time_since_epoch()函数。 这个函数返回从纪元开始的持续时间。 例如是毫秒分辨率的分数。

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

示例结果:

 Thu Oct 11 19:10:24 2012 925 

自解释代码如下,首先创build一个std::tm对应于10-10-2012 12:38:40,将其转换为一个std::chrono::system_clock::time_point ,添加0.123456秒,然后打印出来通过转换回std::tm 。 如何处理小数秒是在最后一步。

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

对我来说这个输出:

 10-10-2012 12:38:40.123456 

你的std::chrono::system_clock::time_point可能精确到可以保持微秒。

更新

更简单的方法就是使用这个date库 。 代码简化为(使用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'; } 

其输出:

 2012-10-10 12:38:40.123456 

如果您不需要certificatet的types是std::chrono::time_point ,则可以跳过static_assert

如果输出不符合你的喜好,例如你真的很喜欢dd-mm-yyyy命令,你可以:

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

它给出了请求的输出:

 10-10-2012 12:38:40.123456 

更新

这里是如何整洁地格式化当前时间的UTC毫秒精度:

 #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())); } 

这只是为我输出:

 2016-10-17 16:36:02.975 

C ++ 17将允许您用time_point_cast<milliseconds>replacetime_point_cast<milliseconds> floor<milliseconds> 。 在那date::floor是在"date.h"可用的。

 std::cout << date::format("%F %T\n", date::floor<milliseconds>(system_clock::now())); 

一般来说,你不能以任何直接的方式来做到这一点。 time_point本质上只是一个特定于时钟的历元的duration

如果你有一个std::chrono::system_clock::time_point ,那么你可以使用std::chrono::system_clock::to_time_ttime_point转换为time_t ,然后使用正常的C函数,例如ctimestrftime来格式化它。


示例代码:

 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; 

我会在接受的答案中提出这个意见,因为那是它所属的地方,但我不能。 所以,如果有人得到不可靠的结果,这可能是为什么。

要小心接受的答案,如果time_point在时代之前就会失败。

这行代码:

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

如果ms.count()是负数(因为size_t不是为了保持负值)将会产生意外的值。

这对我来说像YYYY.MM.DD-HH.MM.SS.fff格式。 试图使这个代码能够接受任何string格式将像重新发明轮子(即在Boost有所有这些function。

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