gpt4 book ai didi

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

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:34:32 25 4
gpt4 key购买 nike

如何将chrono::system_clock::time_point值加数月?

谢谢!

最佳答案

概述

这是一个非常有趣的问题,有几个答案。 “正确”的答案是您必须针对特定应用程序决定的。

使用月份,您可以选择按时间顺序进行计算或进行日历计算。按时间顺序的计算处理时间点和持续时间的常规单位,例如小时,分钟和秒。日历计算处理不规则的日历,该日历主要用来给日子起令人难忘的名字。

年表计算

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

  • 婴儿要在9个月内到期。
  • 从现在开始的6个月后,这里的天气如何?

  • 为了对这些事物进行建模,以平均月份为单位进行工作可能就足够了。一个人可以创建一个 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>>;

    最后 monthsyears的1/12:
    using months = std::chrono::duration
    <int, std::ratio_divide<years::period, std::ratio<12>>>;

    现在您可以轻松计算从现在起的8个月:
    auto t = system_clock::now() + months{8};

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

    日历计算

    也可以添加月份,同时保留一天中的时间和一个月中的某天。这样的计算是日历计算,而不是时间计算。

    选择日历后(例如公历,儒略历或伊斯兰,科普特或埃塞俄比亚历-它们都有几个月,但又不是同一个月),流程为:
  • system_clock::time_point转换为日历。
  • 在日历系统中执行月份计算。
  • 将新的日历时间转换回system_clock::time_point

  • 您可以使用 Howard Hinnant's free, open-source date/time library对一些日历执行此操作。这是民用日历的外观:
    #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}进行比较并得到:
    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。

    Side note: system_clock is not specified to be UTC, but the de facto standard is that it is Unix Time which is a very close approximation to UTC.



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

    代码非常相似,您只需要从UTC转换为本地时间,然后转换为本地日历,进行计算,然后返回本地时间,最后回到 system_clock::time_point(UTC):
    #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();
    }

    更新我们的结果,我得到:
    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

    因为我保留了本地时间(上午11:17),所以时间是一个小时之后(UTC),但是计算是从夏时制开始的,并在标准时间结束,因此UTC等效时间晚了1个小时。

    我使用 current_zone()来获取当前位置,但是我也可以使用特定的时区(例如 "Asia/Tokyo")。

    C++ 20更新

    在我撰写此更新时,C++ 20的技术工作已经停止,并且看起来我们将在今年晚些时候制定新的C++标准(仅剩下要做的行政工作来完成C++ 20)。

    此答案中的建议可以很好地转换为C++ 20:
  • 对于按时间顺序计算,std::chrono::months<chrono>提供,因此您不必自己进行计算。
  • 对于UTC日历计算,请松开#include "date.h"并改为使用#include <chrono>,然后删除using namespace date,一切将正常进行。
  • 对于时区敏感的日历计算,请松开#include "tz.h"并改为使用#include <chrono>,删除using namespace date,然后将make_zoned替换为zoned_time,您可以开始使用。
  • 关于c++ - C++向chrono::system_clock::time_point添加月份,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43010362/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com