Daily bit(e) C++. std::chrono – относительные «псевдодаты»

Добавлено 15 августа 2026 в 06:39

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

Daily bit(e) C++

Одной из очень полезных функций расширения 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
    ...
    */
}

Пример на Compiler Explorer

Теги

C++ / CppchronoDaily bit(e) C++Программирование