The website you reference seems to use a very unique week numbering system. Its definition of week number appears to mirror the ISO definition with the exception that the first day of the week is Sunday instead of Monday. This means that the first day of the year is the Sunday prior to the first Thursday of the year.
There is no strftime flag to give a week number with this definition. But you can easily compute it with the C++20 <chrono> tools. Unfortunately they aren't shipping yet, but you can use this free, open-source C++20 chrono preview library which works with C++11/14/17.
In addition to computing week number, you'll also need to compute the year, as sometimes the gregorian year does not match the year associated with the week. For example according to https://www.calendar-365.com/2019-calendar.html, December 31, 2018 falls on week 1 of 2019.
So here is a function that computes both the year and the week number, given a date:
#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};
}
The logic is a little tricky. The hard part is finding the first day of the year of the date, which is the Sunday prior to the first Thursday of the year. This is nominally:
auto year_start = sys_days{Thursday[1]/January/y} - (Thursday - Sunday);
where y is the year in the week numbering system (usually, but not always the same as the gregorian year). When the date is very late in the year i.e. December 28 - 31, it may fall in the first week of the next year. To catch that possibility, first bump the date by 4 days (the difference between Sunday and Thursday), and then compute the current year.
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
After doing this, compute the start of the year. And if the start of the year happens to be after the date, then you are in the situation that your date belongs in the previous year. In this case, the week number year may be one less than the gregorian year. This can happen when Jan 1 is Friday or Saturday.
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
In summary, the dates 12/28 - 12/31 can have a week year number either equal to their gregorian year, or one greater. And the dates 01/01 and 01/02 can have a week year number either equal to their gregorian year, or one lesser. -- All depending on what day of the month the first Thursday of January falls on [1 - 7].
Once the week number year (y) is figured out, then the week number is simply the difference between the date and the first of the year divided by 7 days (1 week), plus one to bias the first week to 1 instead of 0.
This can be exercised like this:
int
main()
{
using namespace date;
auto [i, w] = outlook_weeknum(2019_y/9/1);
std::cout << i << "-W" << w << '\n';
}
which outputs:
2019-W36
To port this code to C++20:
- Drop the
#include "date/date.h"
- Change
namespace date to namespace std::chrono
- Change
2019_y to 2019y