如何从自 Unix 纪元以来的毫秒数创建时间点?

8

要创建当前时间的时间点,可以使用:std::chrono::system_clock::now()

然而,我无法弄清楚如何根据自UNIX纪元以来的毫秒数创建时间点?

另外,std::chrono::time_point 是否是表示时间“瞬间”的推荐方式?还是应该优先选择std::time_t


1
我个人更喜欢时间点 time_point 而不是持续时间 time_t。请参考:https://zh.cppreference.com/w/cpp/chrono/time_point/time_since_epoch - Ted Lyngmo
谢谢Ted。抱歉,我可能有点傻,但我仍然无法通过你的链接创建一个给定Unix纪元毫秒的时间点? - user6429576
1
如果你将毫秒数转换为 time_t(通常是秒),你可以使用 from_time_t 函数来获取 time_point。然后,使用 + 运算符和 std::chrono::milliseconds 来添加剩余的毫秒数。 - Ted Lyngmo
1
@Jack,请将勾选标记从我的答案移至HH的答案,后者更好。 - Yakk - Adam Nevraumont
已完成,非常感谢! - user6429576
2个回答

11

这更容易/简单:

std::chrono::system_clock::time_point tp{std::chrono::milliseconds{m}};

上述精度为 system_clock::precision (在 macOS 上为 microseconds,在 Linux 系统上为 nanoseconds,在 Windows 上为 1/10 microseconds)。如果需要,还可以创建精度为 millisecondstime_point
std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds>
    tp{std::chrono::milliseconds{m}};

在C++20中,这可以简化为:
std::chrono::sys_time tp{std::chrono::milliseconds{m}};
sys_time只是一个模板类型别名,代表了任意精度的system_clock时间点。即上述类型与之前创建的milliseconds精度的time_point完全相同。
此外,是否std::chrono::time_point是表示时间“瞬间”的推荐方法呢?还是应该优先考虑std::time_t?
我建议使用std::chrono::system_clock::time_point而不是std::time_t
  • time_point基于system_clock在C++20中有一个明确定义的纪元(在C++17中也是事实上的标准):它计算自1970年01月01日00:00:00 UTC以来的时间,不包括闰秒。这也称为Unix Time。相比之下,没有C或C++标准指定time_t的纪元,尽管使用Unix Time是常见做法,并且由POSIX指定。

  • 虽然未指定,但time_t通常具有seconds的精度。system_clock::time_point通常具有比其细微的百万或十亿倍的精度。确切的精度未指定,但在API中记录,因此您可以在编译时或运行时发现它。system_clock::periodsystem_clock::time_point::period相同,并表示从一次滴答到下一次的编译时每秒的分数。

  • time_t通常只是一个32位或64位有符号整数。这在通用代码中没有类型安全性。例如,您可以添加两个time_t并进行编译。但是添加两个时间点是不合逻辑的(而减去它们是合适的)。chrono库在编译时捕获此类逻辑错误。添加两个time_point不会编译。但是您可以添加time_point和任何durationtime_pointduration的逻辑代数在编译时为您检查。

  • 如果您需要涵盖闰秒,则未指定但通常情况下time_t不包括(通常是Unix Time)。使用system_clockUnix Time已指定(您知道您没有计算闰秒)。但是,在C++20中,还有另一个chrono时钟,它在其计数中包括闰秒:std::chrono::utc_clock。像所有chrono时钟一样,该时钟具有其自己的类型安全的time_point系列,具有称为utc_time<Duration>的方便模板类型别名。您可以使用std::chrono::clock_cast在它们之间进行转换。

像这样:
auto tp_sys = clock_cast<system_clock>(tp_utc);

请注意,在 [tag:C++20] 之前,“system_clock 的时代未指定,但大多数实现使用 Unix 时间(即协调世界时 (UTC) 1970 年 1 月 1 日星期四 00:00:00 起至今的秒数,不包括闰秒)。”-- 但我不知道是否有任何例子。在 [tag:C++20] 中,Unix 时间纪元是必需的。有趣的是,我曾认为 time_t 是 Unix 时间,在我的(较差的)答案中并没有得到改善。 - Yakk - Adam Nevraumont
非常感谢你,霍华德。这真的非常有帮助。 - user6429576
3
所有的 system_clock 实现在 C++17 中都使用 Unix 时间。这就是为什么我们能够在 C++20 中标准化现有的实践经验 :-)。虽然当一个主要的实现宣布要改变其纪元时,我们曾经非常接近无法做到这一点。(参见 http://www.youtube.com/watch?v=P32hvk8b13M&t=54m18s)。我成功地说服了他们,并且他们同意了我[将纪元标准化](http://eel.is/c++draft/time.clock.system#overview-1)的条件。他们非常友善,我非常感激。 - Howard Hinnant

1
auto ms_since_epoch(std::int64_t m){
  return std::chrono::system_clock::from_time_t(time_t{0})+std::chrono::milliseconds(m);
}

这将返回系统时钟时间点。
与大多数日历/时间相关的事物一样,它可能无法正确处理闰秒等内容;例如,您的自 Unix 纪元以来的毫秒值可能会受到它们的影响。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接