我从一个神奇的格林姆林获得了一个内存中非负整数值的数组,例如类型I
。每一个代表从某个时期开始的天数(在ISO 8601日历中,该时间比0早许多年)。
现在,我想用C ++类包装这些值(基本上是通过指针或重新解释),这些类可以与std::chrono
的代码很好地交互,或者也许我应该说将它们与通常使用{{ 1}}时间点和持续时间。
为此,我最好的做法是什么?请注意,我不想替换数组中的任何数据,也不想为其他地方的每个现有数据创建新值。
答案 0 :(得分:6)
每一个代表自纪元(ISO 8601日历中的0之前很多年)以来的天数。
假设您指的是Julian Day Number的时代。此时期与您的描述一致。链接上说这个时期是公元前4714年11月24日。我发现不使用“ BC”系统,而是使用负数年的系统比较方便,这样在0年内就可以进行平稳的数学转换。在这个系统中,纪元是11月24日,-4713。
使用Howard Hinnant's free, open-source, header-only date library,这很容易做到。如果我记错了纪元,只需在明显的地方替换正确的纪元即可。
#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
的{{1}},精度为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
中减去2440588。 i
(clang ++ -O3)的优化机器代码从字面上是:
to_sys_days
即所有类型更改业务都是在编译时 发生的。免费。在运行时发生的唯一事情是时间偏移调整。无论您将纪元与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));
}
如果您不想使用date library,仍然可以完成工作,这只是更多的工作。
首先创建一个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
然后计算出从1970-01-01到您的纪元之间的天数。
然后取积分值using days = std::chrono::duration
<int, std::ratio_multiply<std::ratio<24>, std::chrono::hours::period>>;
,将其包装在i
中,然后减去历元差。然后,您可以使用值为days
的{{1}}。
注意:重要的是,以system_clock::time_point
为单位进行历元调整,而不是先转换为days
的单位然后进行调整。后一种策略将在某些平台上溢出。如果以days
精度进行历元偏移,则可以防止溢出。
我强烈建议您不要使用system_clock::time_point
工具来完成这项工作。似乎既不必要又危险。
更新
我忘记了Julian Day epoch是中午而不是午夜的部分。如果您要考虑到这一点,则date lib的使用非常简单:
days
我只是减去了时差12小时,然后让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)};
}
的{{1}},精度为{{1} }。
具有相同输入的完全相同的auto
函数现在输出:
system_clock
答案 1 :(得分:0)
如果实际上只是持续时间,那么您可以简单地
std::chrono::days(integer_value);
,您将获得一个计时持续时间类型。