На веб-сайте, на который вы ссылаетесь, похоже, используется очень уникальная система нумерации недель. Его определение номера недели похоже на определение ISO, за исключением того, что первым днем недели является воскресенье, а не понедельник. Это означает, что первый день года - это воскресенье перед первым четвергом года.
Нет флага strftime для указания номера недели с этим определением. Но вы можете легко вычислить это с помощью инструментов C ++ 20 <chrono>
. К сожалению, они еще не отправлены, но вы можете использовать эту бесплатную библиотеку предварительного просмотра хронографов C ++ 20 с открытым исходным кодом, который работает с C ++ 11/14/17.
Помимо вычисления номера недели, вам также необходимо вычислить год, поскольку иногда грегорианский год не совпадает с годом, связанным с неделей. Например, согласно https://www.calendar-365.com/2019-calendar.html, 31 декабря 2018 г. приходится на первую неделю 2019 г.
Итак, вот функция, которая вычисляет год и номер недели по дате:
#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};
}
Логика немного хитрая. Сложнее всего найти первый день года, то есть воскресенье, предшествующее первому четвергу года. Это номинально:
auto year_start = sys_days{Thursday[1]/January/y} - (Thursday - Sunday);
где y
- год в системе нумерации недель (обычно, но не всегда совпадает с грегорианским годом). Когда дата наступает очень поздно, то есть с 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
После этого вычислите начало года. А если начало года наступает позже даты, значит, ваша дата принадлежит предыдущему году. В этом случае номер недели year может быть на единицу меньше, чем грегорианский год. Это может произойти, когда 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 вместо 0. .
Это можно сделать так:
int
main()
{
using namespace date;
auto [i, w] = outlook_weeknum(2019_y/9/1);
std::cout << i << "-W" << w << '\n';
}
который выводит:
2019-W36
Чтобы перенести этот код на C ++ 20:
- Бросьте
#include "date/date.h"
- Измените
namespace date
на namespace std::chrono
- Измените
2019_y
на 2019y
person
Howard Hinnant
schedule
28.07.2020