【问题标题】:How do I add a number of days to a date in C++20 chrono?如何在 C++20 chrono 中为日期添加天数?
【发布时间】:2020-10-25 07:59:35
【问题描述】:

鉴于 C++20 中的新 <chrono> 工具,我如何将一些天数(比如 n)添加到日期?

当我尝试这个时,我得到一个编译时错误:

auto d = July/4/2020;
auto d2 = d + days{5};
          ~ ^ ~~~~~~~
error: invalid operands to binary expression
   ('std::chrono::year_month_day' and 'std::chrono::days')

【问题讨论】:

  • 好吧,这是我第一次听说chrono::operator/。哇。我猜 C++ 还没有足够的嵌入式语言……

标签: c++ c++20 chrono


【解决方案1】:

<chrono> 中的“日期”只是一个以天为单位的时间点。还有一个 “日期时间”只是一个chrono::time_point(通常基于 system_clock) 的精度比 days 更精细。而规范的“日期类型” <chrono> 是:

chrono::time_point<chrono::system_clock, chrono::days>

这不过是基于 days-precision time_point system_clock。这个特别的time_point也有一个方便 输入别名:sys_days

using sys_days = time_point<system_clock, days>;

所以要给sys_days 加上天数就行了:

sys_days tp = ...;
tp += days{n};
// or
auto tp2 = tp + days{n};

如果只是一天,你也可以:

++tp;

这是非常有效的,因为在引擎盖下它只是添加两个 ints.

如果你的time_point 的精度比days 好,它仍然是 将days 添加到它的相同过程:

auto tp = system_clock::now() + days{n};

当我尝试这个时,我得到一个编译时错误:

auto d = July/4/2020;
auto d2 = d + days{5};
          ~ ^ ~~~~~~~
error: invalid operands to binary expression
   ('std::chrono::year_month_day' and 'std::chrono::days')

上面的变量d 的类型为year_month_day。尽管year_month_day 在语义上等价于sys_days, 它不直接支持days-precision 算术。 year_month_day 是天精度时间点(但不是 chrono::time_point)。相反,它是 {year, month, day} 数据 结构体。您可以通过以下方式轻松执行天精度算术 首先将其转换为sys_days

auto d = July/4/2020;
auto d2 = sys_days{d} + days{5};

在这种情况下,结果d2 的类型是sys_days。如果你想 结果有year_month_day,然后将其转换回来:

year_month_day d2 = sys_days{d} + days{5};

此设计的基本原理:

效率。从year_month_daysys_days 的转换(和 返回)需要一些数字运算。这不是一个巨大的数额。但 与单个积分加法相比,它很大。

如果&lt;chrono&gt; 库为year_month_day 提供days-precision 算法, 该算法是将year_month_day 转换为sys_days, 做算术,然后将结果转换回 year_month_day。如果你有很多days-precision 算术 做,最好只流量sys_days,然后转换为 year_month_day 仅在必要时(即当您需要获取 yearmonthday 字段)。

如果库为year_month_day 提供了日精度算术, 客户会盲目地使用它,而没有意识到 year_month_day 是 他们的应用程序的错误数据结构。这类似于给予 std::list 一个索引运算符(这很容易做到):

template <class T, class A>
T&
list<T, A>::operator[](size_type i)
{
    return *advance(begin(), i);
}

提供这样的 API 只会让编写效率低下变得太容易了 代码。 sys_days 是做days 的首选数据结构 精确算术。

它仍然对我不起作用:

auto d = July/4/2020;
auto d2 = sys_days{d} + day{5};
          ~~~~~~~~~~~ ^ ~~~~~~
error: invalid operands to binary expression
   ('std::chrono::sys_days' and 'std::chrono::day')

您需要使用days,而不是dayday 是一个日历说明符 公历一个月的一天。 days 是一个 chrono::duration。请参阅此stack overflow Q/A 以获得更深入的信息 讨论这两个概念之间的区别。

如果我有一个year_month_day 并且我想添加几天 我知道不会到月底,我能做到吗? 转换为sys_days 从而提高效率?

是的。

auto d = July/4/2020;
auto d2 = d.year()/d.month()/(d.day() + days{5});

上面只是将 5 添加到 dday 字段。没有 检查结果是否超过该月的最后一天。如果 它确实超过了该月的最后一天,该结果将被存储 在日期字段中(直到第 255 天),d2.ok() 将返回 false


year_month_day 适用于检索yearmonthday 日期的字段。也适用于yearsmonths 精度历法算术。 sys_days 适合 days 精度算术,并用于转换为更精细的精度 (日期时间)。

year_month_daysys_days 可以相互转换,没有 信息丢失。使用最有意义的数据结构。 如果你忘记了,编译器会提醒你,就像它为 vector(无 push_front)、list(无索引运算符)和 forward_list(没有size)。

【讨论】:

    猜你喜欢
    • 2023-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-04
    • 1970-01-01
    相关资源
    最近更新 更多