Daily bit(e) C++. std::chrono – относительные «псевдодаты»
Добавлено 15 августа 2026 в 06:39
Daily bit(e) C++ 75, выражение относительных «псевдодат» с помощью поддержки дат в std::chrono из C++20.

Одной из очень полезных функций расширения C++20 для std::chrono является поддержка относительных «псевдодат».
В частности, при работе с реальными событиями мы часто описываем даты в относительных терминах, например, последний день мая или вторая пятница июня.
Выражение таких дат в коде без явной поддержки будет громоздким, поскольку обычно требует написания логики вручную.
Библиотека std::chrono напрямую поддерживает выражение последнего дня и дня недели в месяце, а также поддерживает выражения для n-го дня недели месяца (например, 2-е воскресенье июня).
#include <chrono>
#include <cassert>
using namespace std::chrono;
// Последний день месяца
auto last_day_in_feb = February/last;
// decltype(last_day_in_feb) == std::chrono::month_day_last
// Найти високосные годы в промежутке 2024..2104
for (auto year = 2024y; year <= 2104y; ++year)
{
auto maybe_leap = year/last_day_in_feb;
// то же самое, что и: year/Februrary/last
// decltype(maybe_leap) == std::chrono::year_month_day_last
assert(maybe_leap.ok());
if (maybe_leap.day() == 29d) // требует maybe_leap.ok()
{
// 2024, 2028, 2032, ..., 2096, 2104
}
}
// Последний день недели в месяце
auto last_sunday = December/Sunday[last];
// decltype(last_sunday) == std::chrono::month_weekday_last
// Пройтись по всем последним воскресеньям в периоде 2024..2030
for (auto year = 2024y; year <= 2030y; ++year)
{
auto pseudo = year/last_sunday;
// то же самое, что и: year/December/Sunday[last];
// decltype(pseudo) == std::chrono::year_month_weekday_last
// Преобразовать в реальную дату year_month_day
std::chrono::year_month_day actual{pseudo};
/*
2024-12-29
2025-12-28
2026-12-27
...
*/
}
// n-ый день недели в месяце
// Дата Дня благодарения в США, 4-ый четверг ноября
auto thanksgiving = November/Thursday[4]; // порядковый номер, не индекс
// decltype(thanksgiving) == std::chrono::month_weekday
for (auto year = 2024y; year <= 2030y; year++)
{
// Пока выражение не содержит двусмысленности,
// порядок не имеет значения.
year_month_day date{thanksgiving/year};
/*
2024-11-28
2025-11-27
2026-11-26
...
*/
}
