Ключом к пониманию того, как сделать это проще, является знание этого факта о библиотеке дат Говарда Хиннанта :
weekday
разница круговая (или по модулю 7, если вы предпочитаете). То есть любое weekday
, вычитаемое из любого weekday
, приводит к числу days
в диапазоне [0, 6]. Это эффективно скрывает основную кодировку weekday
.
Таким образом, нет необходимости переводить [понедельник, воскресенье] в [0, 6] (или любую другую кодировку):
#include "date/date.h"
#include <iostream>
int
main()
{
auto todays_date = date::floor<date::days>(std::chrono::system_clock::now());
date::year_month_day lastMonday = todays_date -
(date::weekday{todays_date} - date::Monday);
std::cout << lastMonday << '\n';
}
Вместо этого вам просто нужно решить, сколько дней вам нужно вычесть из sys_days
(todays_date
в этом примере). Это число дней сегодня weekday
минус Monday
. Если сегодня Monday
, результат days{0}
. Если сегодня Sunday
, результат days{6}
. С тем же успехом мы могли бы говорить о поиске предыдущей пятницы. Логика не изменится.
Также можно напрямую конвертировать sys_days
в weekday
. Не нужно идти, хотя year_month_weekday
.
Код в вопросе OP считает «предыдущий понедельник» сегодняшним днем, если сегодня понедельник. И это нормально. Это то, что желательно во многих алгоритмах «предыдущего дня недели». И это логика, которую я кодировал выше.
Но также часто требуется, чтобы алгоритм предыдущего дня недели приводил к результату на прошлой неделе, если день недели, который вы ищете, сегодня. То есть если сегодня понедельник, вычислите неделю назад вместо сегодняшнего дня. Это тоже легко выполнимо, и почти по тому же алгоритму. Нужно только вычесть день в начале алгоритма, если вы хотите такое поведение:
auto todays_date = ...
todays_date -= date::days{1};
date::year_month_day lastMonday = ...