C++ strftime-将周数ISO8601转换为公历标准C++;

C++ strftime-将周数ISO8601转换为公历标准C++;,c++,iso8601,strftime,week-number,gregorian-calendar,C++,Iso8601,Strftime,Week Number,Gregorian Calendar,我使用strftime获得ISO 8601格式(%V)的周数,并希望将其转换为outlook中显示的周数(猜测它是格里高利) Outlook日历设置为: 一周的第一天(星期日) 一年的第一周从1月1日开始 在某些年份,strftime与outlook中显示的weeknumber匹配,但在某些年份则不匹配 一个简单的代码检查: #包括 #包括 对于上面带有输入的代码,输出将是2018-W35,它与my outlook calendar()匹配 然而,如果将年份改为2019年,输出将为2019-

我使用strftime获得ISO 8601格式(%V)的周数,并希望将其转换为outlook中显示的周数(猜测它是格里高利)

Outlook日历设置为:

  • 一周的第一天(星期日)
  • 一年的第一周从1月1日开始
在某些年份,strftime与outlook中显示的weeknumber匹配,但在某些年份则不匹配

一个简单的代码检查:

#包括
#包括

对于上面带有输入的代码,输出将是2018-W35,它与my outlook calendar()匹配

然而,如果将年份改为2019年,输出将为2019-W35,但在我看来,它将落在2019-W36()

是否可以将ISO8601周编号映射为格里高利风格

任何建议或代码示例都将非常有用


谢谢大家!

您参考的网站似乎使用了一种非常独特的周编号系统。它对周数的定义似乎反映了ISO的定义,但一周的第一天是星期天而不是星期一。这意味着一年的第一天是一年中第一个星期四之前的星期日

没有strftime标志提供具有此定义的周数。但是您可以使用C++20
工具轻松地计算它。不幸的是,它们还没有上市,但是您可以使用C++11/14/17

除了计算周数,您还需要计算年份,因为有时公历年与周关联的年份不匹配。例如,根据统计,2018年12月31日是2019年第1周

因此,这里有一个函数,在给定日期的情况下计算年份和周数:

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

// {year, week number}
std::pair<int, int>
outlook_weeknum(date::sys_days sd)
{
    using namespace date;
    auto y = year_month_day{sd + (Thursday - Sunday)}.year();
    auto year_start = sys_days{Thursday[1]/January/y} - (Thursday - Sunday);
    if (sd < year_start)
    {
        --y;
        year_start = sys_days{Thursday[1]/January/y} - (Thursday - Sunday);
    }
    return {int{y}, (sd - year_start)/weeks{1} + 1};
}
其中,
y
是周编号系统中的年份(通常,但并不总是与公历年相同)。当日期在一年中很晚的时候,即12月28日至31日,它可能在下一年的第一周。为了抓住这种可能性,首先将日期增加4天(星期日和星期四之间的差值),然后计算当前年份

         S  M  T  W  T  F  S
y-1 WL  21 22 23 24 25 26 27
y   W1  28 29 30 31  1  2  3
完成此操作后,计算年初。如果一年的开始恰好在日期之后,那么你的日期就属于上一年。在这种情况下,周数年可能比公历年少一个。这可能发生在1月1日星期五或星期六

         S  M  T  W  T  F  S
y-1 WL  27 28 29 30 31  1  2
y   W1   3  4  5  6  7  8  9
总之,12/28-12/31日期的周年数可以等于其公历年,也可以大于一周。而日期01/01和01/02的周年数可以等于公历年,也可以小于公历年所有这些都取决于一月的第一个星期四在哪一天[1-7]

一旦计算出年份的周数(
y
),那么周数就是日期和一年中第一个日期之间的差值除以7天(1周),再加上1,将第一周偏移为1,而不是0

这可以像这样进行:

int
main()
{
    using namespace date;

    auto [i, w] = outlook_weeknum(2019_y/9/1);
    std::cout << i << "-W" << w << '\n';
}
要将此代码移植到C++20,请执行以下操作:

  • 删除
    #包括“date/date.h”
  • 命名空间日期
    更改为
    命名空间std::chrono
  • 2019年
    更改为
    2019年

  • 你读过这个吗?我们的环境。目前有gcc-c++-4.8.5,我们已经使用您的逻辑构建了我们自己的函数,并且运行良好。非常感谢。伟大的如果有帮助,以下是公共领域中一些非常有效的底层算法:
             S  M  T  W  T  F  S
    y-1 WL  27 28 29 30 31  1  2
    y   W1   3  4  5  6  7  8  9
    
    int
    main()
    {
        using namespace date;
    
        auto [i, w] = outlook_weeknum(2019_y/9/1);
        std::cout << i << "-W" << w << '\n';
    }
    
    2019-W36