使用boost :: chrono,如何从单独的年,月,日,小时,分钟,秒开始计算自纪元UTC以来的毫秒数

时间:2013-11-21 20:08:06

标签: c++ boost chrono

我获得了UTC中年,月,日,时,分和秒的值。我需要计算自纪元(UTC)以来的毫秒数。

如何实现这一目标?

由于

1 个答案:

答案 0 :(得分:5)

如果你可以忽略leap seconds,使用合适的工具就可以轻松完成。

您将需要:

  1. days_from_civil位于here
  2. 自定义duration类型,表示天= = 24小时(如下所示)。
  3. C ++ 11的std::chronoboost::chrono库(我用std::chrono显示它。)
  4. 以下是创建代表24小时的自定义chrono::duration的方法:

    typedef std::chrono::duration
    <
        std::int32_t, std::ratio_multiply<std::chrono::hours::period, std::ratio<24>>
    > days;
    

    现在您已准备好编写您的功能:

    std::chrono::milliseconds
    ms_since_UTC(int year, int month, int day, std::chrono::hours h,
                 std::chrono::minutes m, std::chrono::seconds s)
    {
        return days(days_from_civil(year, month, day)) + h + m + s;
    }
    

    days_from_civil会将您的year/month/day转换为自1970年新世纪(UTC时代)以来的天数。您的自定义duration days将与“预定义”计时持续时间无缝互操作:hoursminutessecondsmilliseconds。所有这些持续时间都将隐式转换为milliseconds而没有截断错误。

    如果您需要考虑leap seconds,那么您需要构建一个{days, chrono::seconds}的表,其中条目的第二部分是您需要添加的累计闰秒数days的当前值在表中的days条目之后或之后的持续时间。

    static constexpr std::pair<days, std::chrono::seconds> leap_seconds[25] =
    {
        std::make_pair(days(days_from_civil(1972, 7, 1)), std::chrono::seconds(1)),
        // ...
    };
    

    然后,您需要搜索该表(使用std::find_ifstd::lower_bound),以查看days_from_civil的返回是否位于表格之前,表格之内或之后表。如果在表格之前添加0闰秒。如果在表中,则根据表条目添加适当数量的闰秒。如果超出表格,则添加(当前)25闰秒。

    return d + h + m + s + ls;
    

    这是一种“高维护”解决方案,因为每次决定向UTC添加闰秒时,都需要更新此代码中的表。还应该注意的是,这个解决方案在未来大约6个月内不能高可信度地使用,因为人们根本不知道未来是否会进一步增加(或减少)闰秒。

    days_from_civil代码属于公共领域,因此请随意使用。它很有效率。当给出32位有符号输入时,它具有大约580万年的+/-范围(因此您不必担心会破坏其有效范围)。如果您感兴趣的话,The paper会详细介绍算法的工作原理。