std::chrono::floor добавляет 3 часа

using TimePoint = std::chrono::system_clock::time_point;
TimePoint curTime = std::chrono::system_clock::now();
// Здесь время: 2021-03-02 13:37:31.122

using days = std::chrono::duration
        <int, std::ratio_multiply<std::ratio<(24 * 60 * 60)>, std::chrono::seconds::period>>;

curTime = std::chrono::floor<days>(curTime);
// Здесь время: 2021-03-02 03:00:00.000

Почему округление вниз происходит до +3 часа а не до нуля 2021-03-02 00:00:00.000 ? Предполагаю, что вмешивается часовой пояс. Каким образом округлить до нуля вне зависимости от часового пояса?

Ничего лучше не придумал, чем обнулить через структуру std::tm

auto timeT = std::chrono::system_clock::to_time_t(curTime);
std::tm tm = *std::localtime(&timeT);
tm.tm_min = 0;
tm.tm_sec = 0;
tm.tm_hour = 0;
curTime = std::chrono::system_clock::from_time_t(std::mktime(&tm));

Ответы (1 шт):

Автор решения: Stanislav Volodarskiy

Да, виноват часовой пояс. Нет, часовой пояс в округлении не участвует.

Тип time_point не хранит часовой пояс. Стандарт не указывает какое время там должно быть. Обычно это время по Гринвичу или GMT или UTC или Unix time.

Когда вы вызываете floor - время округляется по Гринвичу.

До сих пор часовой пояс никак не участвовал в процессе. Вы задействуете его когда вызываете std::localtime, который переводит гринвичское время в московское (вы ведь в Москве?) и добавляет три часа: когда в Гринвиче полночь, в Москве три часа ночи.

И так time_point не поддерживает часовые пояса, а вы хотите округлять время с участием текущего часового пояса, в Москве. Раз так, то решение предложенное вами правильное - вы перевели время из Гринвича в Москву и затем округлили.

→ Ссылка