27

我有一些任意的时代,比如 1988 年 7 月 13 日。基本上我想测量与此相关的时间。我正在考虑编写一个自定义时钟类,这样我就可以编写如下代码:

using std::chrono;
time_point<My_Clock> tp;
std::cout << duration_cast<seconds>(tp.time_since_epoch()).count() << std::endl;

这可能吗?如果不是,那么最干净的方法是什么?

4

1 回答 1

40

编写这个自定义时钟的难点在于弄清楚如何编写它的now()功能。在下面的示例中,我now()system_clock's为基础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,periodtime_point. 根据您的问题,我选择secondsduration,但您可以选择任何您想要的。

对于该now()函数,我只需调用system_clock::now()并以秒为单位减去纪元。通过编写所有内容,我对这个计算有点聪明,MyClock::duration这样我就可以更容易地改变duration. 请注意,我能够用 减去 epoch 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 更新

在 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().

于 2013-06-16T22:08:52.663 回答