【问题标题】:C++ print chrono::time_point<chrono::high_resolution_clock> to be readableC++ 打印 chrono::time_point<ch​​rono::high_resolution_clock> 可读
【发布时间】:2020-07-17 12:42:16
【问题描述】:

我有自 Epoch 以来的纳秒数,我想打印出来以便阅读。

我发现在线打印time_point 的示例使用system_clock,然后转换为std::time_t。但是,我正在使用high_resolution_clock(因为纳秒),因此很难理解如何打印它。

考虑到我处理的是纳秒,最好的技术是什么?如果可能的话,我宁愿坚持使用标准库。

我现在坚持使用 C++17,但请提及 C++20 是否让这变得更容易。

#include <chrono>
#include <iostream>

using Clock = std::chrono::high_resolution_clock;
using TimePoint = std::chrono::time_point<Clock>;

int main()
{
    const uint64_t nanosSinceEpoch = 1517812763001883383;
    const Clock::duration duration_ns_since_epoch = std::chrono::nanoseconds(nanosSinceEpoch);

    const TimePoint tp(duration_ns_since_epoch);

    // Would like to print tp in readable format
}

【问题讨论】:

  • @NathanOliver 该示例使用 system_clock,这会导致从 chrono::nanoseconds 创建编译错误
  • @user997112 但接受的答案以转换为std::time_t 结尾,这对打印更加友好,并提到了打印这种结构的常用方法。
  • @Yksisarvinen 我完全同意,我想使用这种方法,但我不确定如何从 high_resolution_clock 创建 time_t?
  • 啊,对,函数to_time_t只存在于system_clock,我的错。虽然似乎不鼓励直接使用high_resolution_clock(或者至少 cppreference 不鼓励这样做)。

标签: c++ chrono


【解决方案1】:

high_resolution_clock 没有可移植的纪元。可能是 1970 年。可能是您的设备启动时。因此,在打印其time_point 时,可以做的最好的事情就是打印底层的持续时间。

system_clock 可以代表nanoseconds,即使system_clock::time_point 不能。诀窍是使用更通用的time_point 形式,即:

template <class Clock, class Duration>
class time_point;

您可以指定时钟和持续时间,例如:

time_point<system_clock, nanoseconds> tp;

我喜欢设置模板类型别名来执行此操作:

template <class Duration>
    using sys_time = std::chrono::time_point<std::chrono::system_clock, Duration>;

现在我可以使用这个更简单的语法了:

sys_time<nanoseconds> tp;

在 C++20 中,sys_time&lt;chrono&gt; 为您提供。而 C++20 允许您简单地打印出基于 system_clocktime_points。

不幸的是,我认为目前还没有人发布 C++20 的这一部分。但是有一个 header-only, open source, free preview of C++20 &lt;chrono&gt; 可以与 C++11/14/17 一起使用:

#include "date/date.h"

#include <chrono>
#include <iostream>

int main()
{
    const uint64_t nanosSinceEpoch = 1517812763001883383;

    const std::chrono::nanoseconds d(nanosSinceEpoch);
    using date::operator<<;
    std::cout << date::sys_time<std::chrono::nanoseconds>{d} << '\n';
}

输出:

2018-02-05 06:39:23.001883383

更新到时区

在处理时区的标题 tz.h 中的同一链接中有一个 second &lt;chrono&gt; preview library。这个库不是只有标题的。有一个与之关联的源文件 tz.cpp。 Here are directions for compiling it.

该库可用于将sys_time(又名Unix Time / UTC)转换为任何IANA time zone

例如,如果您需要在“America/Chicago”中显示上述输出(即使您的计算机不在芝加哥),那么可以这样完成:

#include "date/tz.h"

#include <chrono>
#include <iostream>

int main()
{
    const uint64_t nanosSinceEpoch = 1517812763001883383;

    using namespace std::chrono;
    date::sys_time<nanoseconds> tp{nanoseconds(nanosSinceEpoch)};
    std::cout << date::zoned_time{"America/Chicago", tp} << '\n';
}

输出:

2018-02-05 00:39:23.001883383 CST

这也是 C++20 &lt;chrono&gt; 的一部分。 zoned_time 是一个时区和 sys_time 的配对,只要是秒或更精确,任何精度都可以。其流式运营商包括时区缩写。还有一个format 函数(C++20 中的std::format,库中的date::format)可用于自定义输出。例如:

date::zoned_time zt{"America/Chicago", tp};
std::cout << date::format("%F %T%z", zt) << '\n';

输出:

2018-02-05 00:39:23.001883383-0600

【讨论】:

  • 谢谢霍华德。我会尝试一下。感谢您将其引入 C++20。 C++中有太多5-10行的琐碎任务。这是其中之一。
  • 不幸地得到编译器错误 date.h:1066:23: error: 'uncaught_exception' 已被弃用。 !std::uncaught_exception() &&
  • 有两种处理方法: 1) 不要将警告转换为错误。或者 2) 在包含 date.h 之前定义 HAS_UNCAUGHT_EXCEPTIONS=1
  • 有办法做到这一点,我会更新我的答案来解决这个问题。但首先,您能否更具体地了解您的目标时区? CET 是几个时区的缩写。也许是“欧洲/柏林”?
  • 没问题。更新了我的答案以使用“美国/芝加哥”。
猜你喜欢
  • 2015-06-04
  • 2016-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-02
  • 2014-03-23
  • 2015-05-14
  • 1970-01-01
相关资源
最近更新 更多