[英]How to convert std::chrono::time_point to calendar datetime string with fractional seconds?
How to convert std::chrono::time_point
to calendar datetime string with fractional seconds?如何将
std::chrono::time_point
转换为带小数秒的日历日期时间字符串?
For example:例如:
"10-10-2012 12:38:40.123456"
If system_clock, this class have time_t conversion.如果是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
}
example result:示例结果:
Thu Oct 11 19:10:24 2012
EDIT: But, time_t does not contain fractional seconds.编辑:但是, time_t 不包含小数秒。 Alternative way is to use time_point::time_since_epoch() function.
另一种方法是使用 time_point::time_since_epoch() 函数。 This function returns duration from epoch.
此函数返回纪元的持续时间。 Follow example is milli second resolution's fractional.
下面的例子是毫秒分辨率的小数。
#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;
}
example result:示例结果:
Thu Oct 11 19:10:24 2012
925
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
.不言自明的代码如下,首先创建一个对应于 10-10-2012 12:38:40 的
std::tm
,将其转换为std::chrono::system_clock::time_point
,加上 0.123456 秒,然后将其打印出来通过转换回std::tm
。 How to handle the fractional seconds is in the very last step.如何处理小数秒是最后一步。
#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';
}
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.您的
std::chrono::system_clock::time_point
可能不够精确以保持微秒。
Update更新
An easier way is to just use this date library .一个更简单的方法是使用这个日期库。 The code simplifies down to (using C++14 duration literals):
代码简化为(使用 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';
}
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
.如果您不需要证明
t
的类型是std::chrono::time_point
,则可以跳过static_assert
。
If the output isn't to your liking, for example you would really like dd-mm-yyyy ordering, you could:如果输出不符合您的喜好,例如您真的很喜欢 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';
}
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:以下是如何以毫秒精度巧妙地格式化当前时间 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()));
}
which just output for me:这只是为我输出:
2016-10-17 16:36:02.975
C++17 will allow you to replace time_point_cast<milliseconds>
with floor<milliseconds>
. C++17 将允许你用
time_point_cast<milliseconds>
替换time_point_cast<milliseconds>
floor<milliseconds>
。 Until then date::floor
is available in "date.h"
.在那
date::floor
在"date.h"
可用。
std::cout << date::format("%F %T\n", date::floor<milliseconds>(system_clock::now()));
In C++20 this is now simply:在 C++20 中,这现在很简单:
#include <chrono>
#include <iostream>
int
main()
{
using namespace std::chrono;
auto t = sys_days{10d/10/2012} + 12h + 38min + 40s + 123456us;
std::cout << t << '\n';
}
Or just:要不就:
std::cout << std::chrono::system_clock::now() << '\n';
std::format
will be available to customize the output. std::format
将可用于自定义输出。
In general, you can't do this in any straightforward fashion.通常,您不能以任何简单的方式执行此操作。
time_point
is essentially just a duration
from a clock-specific epoch. time_point
本质上只是一个特定于时钟的纪元的duration
。
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.如果你有一个
std::chrono::system_clock::time_point
,那么你可以使用std::chrono::system_clock::to_time_t
将time_point
转换为time_t
,然后使用普通的 C 函数如ctime
或strftime
来格式化它。
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 << "output : " << std::put_time(&timetm, "%c %Z") << "+"
<< std::chrono::duration_cast<std::chrono::milliseconds>(tp.time_since_epoch()).count() % 1000 << std::endl;
This worked for me for a format like YYYY.MM.DD-HH.MM.SS.fff.这对我来说适用于 YYYY.MM.DD-HH.MM.SS.fff 这样的格式。 Attempting to make this code capable of accepting any string format will be like reinventing the wheel (ie there are functions for all this in Boost.
试图让这段代码能够接受任何字符串格式就像重新发明轮子一样(即在 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;
}
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.请注意接受的答案,如果 time_point 在纪元之前,则它会失败。
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).如果 ms.count() 为负数(因为 size_t 并不意味着保持负值),则会产生意外的值。
In my case I use chrono and c function localtime_r which is thread-safe (in opposition to std::localtime).就我而言,我使用 chrono 和 c 函数 localtime_r,它是线程安全的(与 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;
}
If you are to format a system_clock::time_point
in the format of numpy datetime64, you could use:如果要以 numpy datetime64 格式格式化
system_clock::time_point
,可以使用:
std::string format_time_point(system_clock::time_point point)
{
static_assert(system_clock::time_point::period::den == 1000000000 && system_clock::time_point::period::num == 1);
std::string out(29, '0');
char* buf = &out[0];
std::time_t now_c = system_clock::to_time_t(point);
std::strftime(buf, 21, "%Y-%m-%dT%H:%M:%S.", std::localtime(&now_c));
sprintf(buf+20, "%09ld", point.time_since_epoch().count() % 1000000000);
return out;
}
sample output: 2019-11-19T17:59:58.425802666
样本输出:
2019-11-19T17:59:58.425802666
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.