如何将 std::chrono::time_point 转换为字符串
How to convert std::chrono::time_point to string
如何将std::chrono::time_point
转成字符串?
例如:"201601161125"
.
最灵活的方法是将其转换为 struct tm
,然后使用 strftime
(就像 sprintf
表示时间)。类似于:
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
std::time_t now_c = std::chrono::system_clock::to_time_t(now);
std::tm now_tm = *std::localtime(&now_c);
/// now you can format the string as you like with `strftime`
查找 strftime
here 的文档。
如果您有 localtime_s
或 localtime_r
可用,您应该优先使用 localtime
。
还有很多其他方法可以做到这一点,但是,虽然大多数方法更容易使用,但这些方法会产生一些预定义的字符串表示形式。为了便于使用,您可以 "hide" 将上述所有内容放在一个函数中。
Howard Hinnant's free, open source, header-only, portable date/time library is a modern way to do this that doesn't traffic through the old C API, and doesn't require that you discard all of your sub-second information. This library is also being proposed for standardization.
格式化有很大的灵活性。最简单的方法就是流出:
#include "date.h"
#include <iostream>
int
main()
{
using namespace date;
std::cout << std::chrono::system_clock::now() << '\n';
}
这只是为我输出:
2017-09-15 13:11:34.356648
需要 using namespace date;
才能找到 system_clock::time_point
的流媒体运算符(我的库将其插入 namespace std::chrono
是不合法的)。这种格式不会丢失任何信息:将输出你的 system_clock::time_point
的完整精度(microseconds
,我在 macOS 上 运行 这个)。
完整的 strftime
-like formatting flags 套件可用于其他格式,并有一些小的扩展来处理小数秒之类的事情。这是另一个以毫秒精度输出的示例:
#include "date.h"
#include <iostream>
int
main()
{
using namespace date;
using namespace std::chrono;
std::cout << format("%D %T %Z\n", floor<milliseconds>(system_clock::now()));
}
这只是为我输出:
09/15/17 13:17:40.466 UTC
代码解决方案
以下函数将chrono
time_point
转换为字符串(序列化)。
#include <chrono>
#include <iomanip>
#include <sstream>
using time_point = std::chrono::system_clock::time_point;
std::string serializeTimePoint( const time_point& time, const std::string& format)
{
std::time_t tt = std::chrono::system_clock::to_time_t(time);
std::tm tm = *std::gmtime(&tt); //GMT (UTC)
//std::tm tm = *std::localtime(&tt); //Locale time-zone, usually UTC by default.
std::stringstream ss;
ss << std::put_time( &tm, format.c_str() );
return ss.str();
}
// example
int main()
{
time_point input = std::chrono::system_clock::now();
std::cout << serializeTimePoint(input, "UTC: %Y-%m-%d %H:%M:%S") << std::endl;
}
时区
time_point
数据类型没有时区的内部表示,因此,时区通过转换为 std::tm
(通过函数 gmtime
或 localtime
)。不建议 add/substract 输入时区,因为 %Z
会显示不正确的时区,因此最好设置正确的本地时间 (OS 依赖)并使用 localtime()
.
技术与用户友好的序列化
对于技术用途,硬编码时间格式是一个很好的解决方案。但是,要向用户显示,应该使用 locale
来检索用户偏好并以该格式显示时间戳。
C++20
从 C++20 开始,我们为 time_point 和持续时间提供了很好的序列化和解析函数。
std::chrono::to_stream
std::chrono::format
很像 Adrian 的回答,但有(可选的)毫秒和 GMT/localtime 开关。
#include <chrono>
#include <iostream>
#include <iomanip>
#include <sstream>
using Clock = std::chrono::high_resolution_clock;
static std::string timePointToString(const Clock::time_point &tp, const std::string &format, bool withMs = true, bool utc = true)
{
const Clock::time_point::duration tt = tp.time_since_epoch();
const time_t durS = std::chrono::duration_cast<std::chrono::seconds>(tt).count();
std::ostringstream ss;
if (const std::tm *tm = (utc ? std::gmtime(&durS) : std::localtime(&durS))) {
ss << std::put_time(tm, format.c_str());
if (withMs) {
const long long durMs = std::chrono::duration_cast<std::chrono::milliseconds>(tt).count();
ss << std::setw(3) << std::setfill('0') << int(durMs - durS * 1000);
}
}
// gmtime/localtime() returned null ?
else {
ss << "<FORMAT ERROR>";
}
return ss.str();
}
int main() {
const auto tp = Clock::now();
std::cout << timePointToString(tp, "%Z %Y-%m-%d %H:%M:%S.") << std::endl;
return 0;
}
> GMT 2022-04-30 13:44:09.720
测试:https://www.mycompiler.io/view/43wsMbrMcmx
当然它只附加毫秒并且它们不是模板的一部分......那会额外收费!
如何将std::chrono::time_point
转成字符串?
例如:"201601161125"
.
最灵活的方法是将其转换为 struct tm
,然后使用 strftime
(就像 sprintf
表示时间)。类似于:
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
std::time_t now_c = std::chrono::system_clock::to_time_t(now);
std::tm now_tm = *std::localtime(&now_c);
/// now you can format the string as you like with `strftime`
查找 strftime
here 的文档。
如果您有 localtime_s
或 localtime_r
可用,您应该优先使用 localtime
。
还有很多其他方法可以做到这一点,但是,虽然大多数方法更容易使用,但这些方法会产生一些预定义的字符串表示形式。为了便于使用,您可以 "hide" 将上述所有内容放在一个函数中。
Howard Hinnant's free, open source, header-only, portable date/time library is a modern way to do this that doesn't traffic through the old C API, and doesn't require that you discard all of your sub-second information. This library is also being proposed for standardization.
格式化有很大的灵活性。最简单的方法就是流出:
#include "date.h"
#include <iostream>
int
main()
{
using namespace date;
std::cout << std::chrono::system_clock::now() << '\n';
}
这只是为我输出:
2017-09-15 13:11:34.356648
需要 using namespace date;
才能找到 system_clock::time_point
的流媒体运算符(我的库将其插入 namespace std::chrono
是不合法的)。这种格式不会丢失任何信息:将输出你的 system_clock::time_point
的完整精度(microseconds
,我在 macOS 上 运行 这个)。
完整的 strftime
-like formatting flags 套件可用于其他格式,并有一些小的扩展来处理小数秒之类的事情。这是另一个以毫秒精度输出的示例:
#include "date.h"
#include <iostream>
int
main()
{
using namespace date;
using namespace std::chrono;
std::cout << format("%D %T %Z\n", floor<milliseconds>(system_clock::now()));
}
这只是为我输出:
09/15/17 13:17:40.466 UTC
代码解决方案
以下函数将chrono
time_point
转换为字符串(序列化)。
#include <chrono>
#include <iomanip>
#include <sstream>
using time_point = std::chrono::system_clock::time_point;
std::string serializeTimePoint( const time_point& time, const std::string& format)
{
std::time_t tt = std::chrono::system_clock::to_time_t(time);
std::tm tm = *std::gmtime(&tt); //GMT (UTC)
//std::tm tm = *std::localtime(&tt); //Locale time-zone, usually UTC by default.
std::stringstream ss;
ss << std::put_time( &tm, format.c_str() );
return ss.str();
}
// example
int main()
{
time_point input = std::chrono::system_clock::now();
std::cout << serializeTimePoint(input, "UTC: %Y-%m-%d %H:%M:%S") << std::endl;
}
时区
time_point
数据类型没有时区的内部表示,因此,时区通过转换为 std::tm
(通过函数 gmtime
或 localtime
)。不建议 add/substract 输入时区,因为 %Z
会显示不正确的时区,因此最好设置正确的本地时间 (OS 依赖)并使用 localtime()
.
技术与用户友好的序列化
对于技术用途,硬编码时间格式是一个很好的解决方案。但是,要向用户显示,应该使用 locale
来检索用户偏好并以该格式显示时间戳。
C++20
从 C++20 开始,我们为 time_point 和持续时间提供了很好的序列化和解析函数。
std::chrono::to_stream
std::chrono::format
很像 Adrian 的回答,但有(可选的)毫秒和 GMT/localtime 开关。
#include <chrono>
#include <iostream>
#include <iomanip>
#include <sstream>
using Clock = std::chrono::high_resolution_clock;
static std::string timePointToString(const Clock::time_point &tp, const std::string &format, bool withMs = true, bool utc = true)
{
const Clock::time_point::duration tt = tp.time_since_epoch();
const time_t durS = std::chrono::duration_cast<std::chrono::seconds>(tt).count();
std::ostringstream ss;
if (const std::tm *tm = (utc ? std::gmtime(&durS) : std::localtime(&durS))) {
ss << std::put_time(tm, format.c_str());
if (withMs) {
const long long durMs = std::chrono::duration_cast<std::chrono::milliseconds>(tt).count();
ss << std::setw(3) << std::setfill('0') << int(durMs - durS * 1000);
}
}
// gmtime/localtime() returned null ?
else {
ss << "<FORMAT ERROR>";
}
return ss.str();
}
int main() {
const auto tp = Clock::now();
std::cout << timePointToString(tp, "%Z %Y-%m-%d %H:%M:%S.") << std::endl;
return 0;
}
> GMT 2022-04-30 13:44:09.720
测试:https://www.mycompiler.io/view/43wsMbrMcmx
当然它只附加毫秒并且它们不是模板的一部分......那会额外收费!