C ++向chrono :: system_clock :: time_point添加月份

时间:2017-03-24 22:47:46

标签: c++ c++11 std chrono

如何将月份添加到chrono :: system_clock :: time_point值?

谢谢!

1 个答案:

答案 0 :(得分:6)

概述

这是一个非常有趣的问题,有几个答案。 “正确”答案是您必须根据具体应用决定的。

有几个月,您可以选择按时间顺序计算日历计算。按时间顺序计算处理常规单位的时间点和持续时间,例如小时,分钟和秒。日历计算处理不规则的日历,主要用于提供令人难忘的名字。

按时间顺序计算

如果问题是关于未来几个月的物理过程,物理学并不关心不同的月份有不同的长度,因此按时间顺序计算就足够了:

  • 宝宝将在9个月内到期。

  • 从现在起6个月后天气会怎样?

为了对这些事情进行建模,根据平均值月来工作可能就足够了。可以创建一个{em} 精确平均格里高利(民间)月份的std::chrono::duration。最简单的方法是定义一系列以days开头的持续时间:

days是24小时:

using days = std::chrono::duration
    <int, std::ratio_multiply<std::ratio<24>, std::chrono::hours::period>>;

years是365.2425 days,或 146097 / 400 days

using years = std::chrono::duration
    <int, std::ratio_multiply<std::ratio<146097, 400>, days::period>>;

最后months是<{1}}的 1 / 12

years

现在您可以在8个月后轻松计算:

using months = std::chrono::duration
    <int, std::ratio_divide<years::period, std::ratio<12>>>;

重要说明:此计算保留一天中的时间,甚至是一个月中的某一天。

Calendrical Computation

还可以在保留时间日期的同时添加月份。此类计算是日历计算,而不是按时间顺序计算

选择日历(例如格里高利(民事)日历,朱利安日历,或者伊斯兰,科普特或日历的日历 - 它们都有几个月,但它们不是同一个月),过程如下:

  1. auto t = system_clock::now() + months{8}; 转换为日历。

  2. 在日历系统中执行月计算。

  3. 将新日历时间转换回system_clock::time_point

  4. 您可以使用Howard Hinnant's free, open-source date/time library为几个日历执行此操作。这是民事日历的样子:

    system_clock::time_point

    对于笑脸我只是跑了这个,并将其与#include "date.h" int main() { using namespace date; using namespace std::chrono; // Get the current time auto now = system_clock::now(); // Get a days-precision chrono::time_point auto sd = floor<days>(now); // Record the time of day auto time_of_day = now - sd; // Convert to a y/m/d calendar data structure year_month_day ymd = sd; // Add the months ymd += months{8}; // Add some policy for overflowing the day-of-month if desired if (!ymd.ok()) ymd = ymd.year()/ymd.month()/last; // Convert back to system_clock::time_point system_clock::time_point later = sys_days{ymd} + time_of_day; } 进行了比较并得到了:

    now + months{8}

    这给出了日历计算与时间计算的不同之处的粗略“感觉”。后者平均完全准确;它只是偏离了几天的平均值。有时候更简单(后一种)的解决方案足够接近,有时则不然。只有可以回答那个问题。

    Calendrical Computation - 现在有时区

    最后,您可能希望在特定时区执行日历计算。以前的计算是UTC。

      

    旁注:now is 2017-03-25 15:17:14.467080 later is 2017-11-25 15:17:14.467080 // calendrical computation now + months{8} is 2017-11-24 03:10:02.467080 // chronological computation 未指定为UTC,但事实上的标准是Unix Time,它非常接近UTC。

    您可以使用Howard Hinnant's free, open-source timezone library进行此计算。这是前面提到的datetime library的扩展。

    代码非常相似,您只需要从UTC转换为本地时间,然后转换为本地日历,然后计算然后返回本地时间,最后返回system_clock(UTC):

    system_clock::time_point

    更新我的结果我得到:

    #include "tz.h"
    
    int
    main()
    {
        using namespace date;
        using namespace std::chrono;
    
        // Get the current local time
        auto lt = make_zoned(current_zone(), system_clock::now());
        // Get a days-precision chrono::time_point
        auto ld = floor<days>(lt.get_local_time());
        // Record the local time of day
        auto time_of_day = lt.get_local_time() - ld;
        // Convert to a y/m/d calendar data structure
        year_month_day ymd{ld};
        // Add the months
        ymd += months{8};
        // Add some policy for overflowing the day-of-month if desired
        if (!ymd.ok())
            ymd = ymd.year()/ymd.month()/last;
        // Convert back to local time
        lt = local_days{ymd} + time_of_day;
        // Convert back to system_clock::time_point
        auto later = lt.get_sys_time();
    }
    

    时间是一小时后(UTC),因为我保留了当地时间(上午11:17),但计算在夏令时开始,以标准时间结束,因此UTC等效时间晚1小时。 / p>

    我使用now is 2017-03-25 15:17:14.467080 later is 2017-11-25 15:17:14.467080 // calendrical: UTC later is 2017-11-25 16:17:14.467080 // calendrical: America/New_York now + months{8} is 2017-11-24 03:10:02.467080 // chronological computation 来获取当前位置,但我也可以使用特定时区(例如current_zone())。

相关问题