我有一个任意的历元,比如1988年7月13日。实质上,我想相对于这个时间来测量时间。我正在考虑编写一个自定义的时钟类,这样我就可以像这样编写代码:
using std::chrono;
time_point<My_Clock> tp;
std::cout << duration_cast<seconds>(tp.time_since_epoch()).count() << std::endl;
这是可能的吗?如果不行,最干净的实现方式是什么?
我有一个任意的历元,比如1988年7月13日。实质上,我想相对于这个时间来测量时间。我正在考虑编写一个自定义的时钟类,这样我就可以像这样编写代码:
using std::chrono;
time_point<My_Clock> tp;
std::cout << duration_cast<seconds>(tp.time_since_epoch()).count() << std::endl;
这是可能的吗?如果不行,最干净的实现方式是什么?
now()
函数。在下面的示例中,我以system_clock
的now()
为基础来编写now()
函数。首先,我进行了一些侦探工作,发现我的system_clock
从1970年元旦开始计时,忽略闰秒。这被称为Unix时间。事实证明,我所知道的每个实现(我想我已经检查过它们所有)都有相同的起始时间(但这在C++11标准中没有指定)。接下来,我计算出1988年07月13日是1970年01月01日之后的6768天。有了这两个事实,剩下的就很容易了:
#include <chrono>
struct My_Clock
{
typedef std::chrono::seconds duration;
typedef duration::rep rep;
typedef duration::period period;
typedef std::chrono::time_point<My_Clock> time_point;
static const bool is_steady = false;
static time_point now() noexcept
{
using namespace std::chrono;
return time_point
(
duration_cast<duration>(system_clock::now().time_since_epoch()) -
hours(6768*24)
);
}
};
MyClock
需要嵌套的typedef来描述它的duration
、rep
、period
和time_point
。根据您的问题,我选择了seconds
作为duration
,但您可以选择任何您想要的。
对于now()
函数,我只需调用system_clock::now()
并以秒为单位减去时代。我通过以MyClock::duration
的形式编写计算中的所有内容变得更加聪明,以便更轻松地更改duration
。请注意,我能够以hours
的形式减去时代,它隐式转换为duration
(即seconds
)。或者,我也可以构建自定义的duration
为天数:
typedef std::chrono::duration<int, std::ratio_multiply<std::chrono::hours::period,
std::ratio<24>>> days;
接着now()
的返回值可以这样写:
return time_point
(
duration_cast<duration>(system_clock::now().time_since_epoch()) -
days(6768)
);
无论如何,现在你可以像这样使用它:
#include <iostream>
int
main()
{
using namespace std::chrono;
time_point<My_Clock> tp = My_Clock::now();
std::cout << tp.time_since_epoch().count() << '\n';
}
对我来说,它只是打印出来了:
786664963
这表明今天(2013-06-16)距离1988-07-13大约已经过去了24.9年。
在C++20中,您可以使用更新的<chrono>
日历服务来消除实现中的“神奇数字”:
#include <chrono>
struct My_Clock
{
typedef std::chrono::seconds duration;
typedef duration::rep rep;
typedef duration::period period;
typedef std::chrono::time_point<My_Clock> time_point;
static const bool is_steady = false;
static time_point now() noexcept
{
using namespace std::chrono;
return time_point
{
duration_cast<duration>(system_clock::now() - sys_days{July/13/1988})
};
}
};
这种便利不会增加运行时间的开销。子表达式sys_days{July/13/1988}
在编译时被优化为自system_clock
纪元以来的天数计数,然后进一步转换为system_clock::duration
(仍然在编译时)并从system_clock::now()
中减去。
time_point
接受Clock
作为模板,这是一个概念。你可以自己编写一个满足该特定概念要求的类。但不要完全相信我的话,我只是在胡思乱想。 - Daniel Kamil Kozar