如何将std :: chrono :: time_point转换为字符串

Sei*_* Oh 11 c++11 c++-chrono

如何转换std::chrono::time_point为字符串?例如:"201601161125".

How*_*ant 13

Howard Hinnant的免费,开源,仅标题,便携式日期/时间库是一种现代化的方法,它不会通过旧的C API进行流量传输,并且不要求您丢弃所有的亚秒级信息.该库也被提议用于标准化.

格式化有很多灵活性.最简单的方法是流出:

#include "date.h"
#include <iostream>

int
main()
{
    using namespace date;
    std::cout << std::chrono::system_clock::now() << '\n';
}
Run Code Online (Sandbox Code Playgroud)

这只是输出给我:

2017-09-15 13:11:34.356648
Run Code Online (Sandbox Code Playgroud)

using namespace date;是为了找到流媒体操作符所必需的system_clock::time_point(我的lib插入它是不合法的namespace std::chrono).没有信息以这种格式丢失:system_clock::time_point输出的完整精度(microseconds我在macOS上运行的地方).

完整的类似strftime格式化标志套件可用于其他格式,带有次要扩展来处理分数秒等事情.这是另一个以毫秒精度输出的示例:

#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()));
}
Run Code Online (Sandbox Code Playgroud)

只为我输出:

09/15/17 13:17:40.466 UTC
Run Code Online (Sandbox Code Playgroud)

  • 我认为这里的示例最好不要“使用命名空间”,这样可以更清楚哪些函数和类型来自哪个命名空间。 (7认同)
  • 问题之一是命名空间随着时间而变化:“floor”位于命名空间“date”中,但从 C++17 开始位于命名空间“std::chrono”中。到 C++20 时,一切都将位于 `std::chrono` 中。 (3认同)

Adr*_*ire 9

代码解决方案

以下函数将 from 转换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;

}
Run Code Online (Sandbox Code Playgroud)

时区

time_point数据类型具有用于时区没有内部表示,其结果是,时区是由转化为聚集std::tm(由函数gmtimelocaltime)。不建议在输入中添加/减去时区,因为使用 会显示不正确的时区%Z,因此,最好设置正确的本地时间(取决于操作系统)并使用localtime().

技术与用户友好的序列化

对于技术用途,硬编码时间格式是一个很好的解决方案。但是,要向用户显示,应该使用 alocale来检索用户首选项并以该格式显示时间戳。

C++20

从 C++20 开始,我们为 time_point 和 duration 提供了很好的序列化和解析函数。

  • std::chrono::to_stream
  • std::chrono::format


srd*_*vic 7

最灵活的方法是将其转换为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`
Run Code Online (Sandbox Code Playgroud)

strftime 这里查找文档.

如果您有localtime_slocaltime_r有,您应该优先使用localtime.

还有很多其他方法可以做到这一点,但是,虽然大多数更容易使用,但这些方法会产生一些预定义的字符串表示.您可以在功能中"隐藏"上述所有内容以方便使用.

  • Hinnant 先生的库尚未成为 C++ 标准的一部分,而“strftime()”早已成为 C 标准的一部分。看来在 C++20 中,Hinnant 先生的库将成为 C++ 标准的一部分 - 当这种情况发生时,将很难做出坚定的选择(这将取决于您的需求和经验)。 (3认同)