如何在C ++中查找上周一的日期

Hem*_*mil 3 c++ date c++-chrono

我想制作一个不输入任何内容并返回上一个星期一的日期的程序。(我不在乎时区。我只担心公历)。我正在使用Howard Hinnant的日期。这是我目前正在做的事情:

#include <iostream>
#include <date/date.h>

int main() {

    auto todays_day = date::year_month_weekday(date::floor<date::days>(std::chrono::system_clock::now()));

    auto todays_date = date::floor<date::days>(std::chrono::system_clock::now());

    int offset = 0;

    auto weekday = todays_day.weekday();

    if(weekday == date::Tuesday)
        offset = 1;
    else if (weekday == date::Wednesday)
        offset = 2;
    else if (weekday == date::Thursday)
        offset = 3;
    else if (weekday == date::Friday)
        offset = 4;
    else if (weekday == date::Saturday)
        offset = 5;
    else if (weekday == date::Sunday)
        offset = 6;

    auto lastMonday = date::year_month_day(todays_date - date::days(offset));

    std::cout << lastMonday;
}
Run Code Online (Sandbox Code Playgroud)

有没有没有boost :: previous_weekday的更好的方法?(不要求不使用boost。我只是想知道是否有可能)

How*_*ant 5

了解如何更简单地执行此操作的关键是了解有关Howard Hinnant的日期库的这一事实:

weekday差异是圆形的(或按需取模7)。即,weekday从任何值weekday中减去的任何结果都将days在[0,6]范围内。这有效地隐藏了的基础编码weekday

因此,无需将[Monday,Sunday]转换为[0,6](或任何其他编码):

#include "date/date.h"
#include <iostream>

int
main()
{
    auto todays_date = date::floor<date::days>(std::chrono::system_clock::now());
    date::year_month_day lastMonday = todays_date -
                                      (date::weekday{todays_date} - date::Monday);
    std::cout << lastMonday << '\n';
}
Run Code Online (Sandbox Code Playgroud)

相反,您只需要确定需要从中减去多少天sys_daystodays_date在此示例中)。那几天就是今天的weekday负数Monday。如果今天是Monday,则结果为days{0}。如果今天是Sunday,则结果为days{6}。我们也可以谈论寻找上一个星期五。逻辑不会改变。

另外,可以将a直接转换sys_days为a weekday。不用走了year_month_weekday

如果今天恰好是星期一,则OP的问题中的代码将“上一个星期一”视为今天。那很好。这是许多“以前的工作日”算法所需要的。这就是我上面编码的逻辑。

但是,如果要查找的工作日是今天,则通常希望上一个工作日算法在上周产生。也就是说,如果今天是星期一,请计算一周前而不是今天。通过几乎相同的算法,这也很容易实现。如果您想要这种行为,只需在算法开始时减去一天:

auto todays_date = ...
todays_date -= date::days{1};
date::year_month_day lastMonday = ...
Run Code Online (Sandbox Code Playgroud)