如何安全地记录测试天数



我使用HowardHinnant/date来代替Clang/GCC中尚未提供的新的C++20日历/时区功能。我的问题同样适用于这两种实现:如何安全地使用具有days持续时间的clock_casttime_point

当我尝试时:

using namespace date; // or using std::chrono in C++20
tai_time<days> tai{days{42}};
sys_days sys = clock_cast<std::chrono::system_clock>(tai);

我得到了一个";没有可行的转化";最后一条语句出错。结果使用的持续时间是common_type<days, seconds>,它来自转换中使用的utc_clock::to_sys()。常见的持续时间类型是std::chrono::seconds,因此不能直接转换为days持续时间是正常的。

如果我使用显式duration_cast:,我可以编译它

using namespace date; // or using std::chrono in C++20
tai_time<days> tai{days{42}};
auto casted = clock_cast<std::chrono::system_clock>(tai);
sys_days sys{std::chrono::duration_cast<days>(casted.time_since_epoch())};

但我担心,由于截断(尤其是纪元之前的日期(,结果可能会推迟一天。这是做我想做的事情的正确方式吗?我应该使用floor而不是duration_cast吗?

为什么utc_clock::to_sys()中甚至有一个std::common_type_t<Duration, std::chrono::seconds>?它不应该简单地返回相同的持续时间类型吗?

clock_cast坚持至少seconds精度的原因是因为system_clocktai_clock的历元之间的偏移具有seconds:的精度

auto diff = sys_days{} - clock_cast<system_clock>(tai_time<days>{});
cout << diff << " == " << duration<double, days::period>{diff} << 'n';

输出:

378691210s == 4383.000116d

因此,days精密铸造会有损耗。这是另一种看待它的方式:

cout << clock_cast<tai_clock>(sys_days{2021_y/June/1}) << 'n';

输出:

2021-06-01 00:00:37

也就是说,TAI目前在日历方面领先system_clock37秒。

如果你只想要日期,我推荐round<days>(result):

cout << round<days>(clock_cast<tai_clock>(sys_days{2021_y/June/1})) << 'n';

输出:

2021-06-01 00:00:00

可以想象,在一个方向上使用floor,在另一个方向使用ceil,但这非常容易出错。round会做得很好,因为与整数天数的偏移目前只有37秒,并且增长非常缓慢。

最新更新