如何使"days-since-epoch"值与 std::chrono 配合使用?
How do I make "days-since-epoch" values play nice with std::chrono?
我从一个神奇的小精灵那里获得了内存中的非负整数值数组,比如I
型。其中每个都代表自某个纪元(在 ISO 8601 日历中比 0 早很多年)以来的天数。
现在,我想通过C++类来包装这些值 - 基本上是通过指针或重新解释 - 这些类可以与std::chrono
代码很好地交互,或者也许我应该说与通常需要std::chrono
时间点和持续时间的代码一起使用。
为此,我最好的行动方案是什么?注意 我不想替换数组中的任何数据,也不想为其他地方的每个现有数据创建新值。
其中每个都表示自纪元以来的天数(在 ISO 8601 日历中比 0 早很多年)。
假设您指的是儒略日数字的纪元。 这个时代与你的描述是一致的。 该链接说这个纪元是公元前 4714 年 11 月 24 日,在公历中。 与其使用"BC"系统,我发现使用负年份的系统很方便,这样就可以在 0 年之间有一个平滑的数学过渡。 在这个系统中,纪元是-4713年11月24日。
使用 Howard Hinnant 的免费、开源、仅标题日期库,这很容易做到。 如果我有错误的时代,只需在明显的地方替换正确的时代。
#include "date/date.h"
#include <iostream>
date::sys_days
to_sys_days(int i)
{
using namespace date;
return sys_days{days{i} -
(sys_days{1970_y/January/1} - sys_days{-4713_y/November/24})};
}
date::sys_days
返回类型是std::chrono::time_point<std::chrono::system_clock, std::chrono::duration<int, std::ratio<86400>>>
。或者用英语:它是一种基于system_clock
time_point
,精度为days
. 此time_point
将隐式转换为您平台的system_clock::time_point
。
现在你可以将int
传递给to_sys_days
,并将结果传递给采用system_clock::time_point
的函数。 例如:
void
display(std::chrono::system_clock::time_point tp)
{
using date::operator<<;
std::cout << tp << 'n';
}
int
main()
{
display(to_sys_days(2'458'674));
}
这输出:
2019-07-09 00:00:00.000000
to_sys_days
是一个非常便宜的操作。 每次读取数据的单个元素时,您都可以负担得起这样做的费用。 它所做的只是从i
中减去2440588。 优化的to_sys_days
机器代码(clang++ -O3)的字面意思是:
leal -2440588(%rdi), %eax
即所有类型更改业务都发生在编译时。 它是免费的。 运行时唯一发生的是纪元偏移调整。 这是必须完成的最低限度,无论如何使您的纪元与system_clock
纪元对齐。
因此,如果您有一个int
数组作为数据,则不必复制整个数组。 您只需根据需要转换其中的每个元素即可。 例如:
int
main()
{
int data[] = {2'458'674, 2'458'675, 2'458'676, 2'458'677, 2'458'678};
for (auto i : data)
display(to_sys_days(i));
}
输出:
2019-07-09 00:00:00.000000
2019-07-10 00:00:00.000000
2019-07-11 00:00:00.000000
2019-07-12 00:00:00.000000
2019-07-13 00:00:00.000000
如果您不想使用日期库,您仍然可以完成工作,这只是多做一点工作。
首先创建一个表示天的duration
类型:
using days = std::chrono::duration
<int, std::ratio_multiply<std::ratio<24>, std::chrono::hours::period>>;
然后计算出 1970-01-01 和你的纪元之间的天数。
然后取你的整数值i
,用days
包裹,减去你的纪元差。 然后,您可以使用值days
构造一个system_clock::time_point
。
注: 以days
为单位进行纪元调整非常重要,而不是先转换为system_clock::time_point
单位,然后再进行调整。 后一种策略将在某些平台上溢出。 如果以days
精度执行纪元偏移,则可以防止溢出。
我强烈建议不要使用reinterpret_cast
工具来完成这项工作。 这似乎既不必要又危险。
更新
我忘记了说儒略日纪元是中午而不是午夜的部分。 如果你想考虑到这一点,使用日期库很容易:
auto
to_sys_days(int i)
{
using namespace date;
using namespace std::chrono;
return sys_time<hours>{days{i} -
(sys_days{1970_y/January/1} - sys_days{-4713_y/November/24} - 12h)};
}
我只是简单地从纪元差异中减去 12 小时,auto
为我推断返回类型(现在是一个基于system_clock
的time_point
,精度为hours
)。
具有相同输入的完全相同的display
函数现在输出:
2019-07-09 12:00:00.000000
如果真的只是关于持续时间,那么你可以简单地做
std::chrono::days(integer_value);
你会得到一个计时持续时间类型。
- 从持续时间构造std::chrono::system_clock::time_point
- 如何在c++迭代器类型中包装std::chrono
- 在两台机器之间进行时间戳的最佳c++chrono函数是什么
- 如何在 Gnuplot 中分别绘制 2 个文件数据?我有一个文件"sin.txt",另一个文件"cos.txt",我想将它们分别绘制在一个图表上
- 使用 memcpy() 复制到 std::chrono::milliseconds 会给出错误 -Werror=clas
- std::multimap<std::chrono::milliseconds, T>::rbegin 在 MSVS-13 中指向 end()?
- 如何在C++中将 chrono::秒转换为 HH:MM:SS 格式的字符串?
- C++ Chrono 确定一天是否是周末?
- std::adjacent_difference with std::chrono time_point
- 为什么 std::round(sin(pi/6)) 不等于 1?
- MacOS 上的 Xcode 11 项目不在一个函数中使用 sin 和 cos:未定义的符号"___sincosf_stret"
- VSCode 说 std::chrono 是模棱两可的,如果运算符<<重载
- 是否确保 2 个连续的 std::chrono::steady_clock::now() 不相等?
- std::chrono::d uration 可以按秒初始化,但不能按毫秒初始化?
- chrono::month 和 chrono::month 有什么区别
- 比较两个 std::chrono::time_point 实例时出错
- 来自 std::chrono 的编译器警告,但未被使用
- 从编译时已知的日历日期创建"std::chrono::time_point"
- std::chrono::time_point from std::string
- 如何使"days-since-epoch"值与 std::chrono 配合使用?