Ошибка при сравнении двух экземпляров std :: chrono :: time_point - PullRequest
1 голос
/ 29 мая 2020

У меня есть два экземпляра std :: chrono :: time_point в переменных exp и time. exp имеет время в будущем, а time - текущее время. Но когда я сравниваю их, как в этом фрагменте:

std::time_t t_exp = std::chrono::system_clock::to_time_t(exp);
std::time_t t_time = std::chrono::system_clock::to_time_t(time);
std::cout << std::ctime(&t_exp) << std::ctime(&t_time) << (time > exp) << std::endl;

, я получаю результат:

Sat Apr 26 01:39:43 4758
Fri May 29 18:11:59 2020
1

Что неверно, потому что exp находится в 4758 году, а time - в 2020 год.

Где я ошибаюсь?

1 Ответ

1 голос
/ 30 мая 2020

t_exp равно -4243023785

Это значение time_t соответствует 1835-07-18 22:16:55 (при условии Unix эпохи и точности секунд, ни одна из которых не указана в стандарте, но является обычным явлением).

Очевидно, реализация ctime на вашей платформе не может обрабатывать даты так далеко в прошлом, что немного удивительно, поскольку 1835 не так уж и далеко в прошлом.

Значение exp равно -4243023785 миллионам или миллиардам (в зависимости от точности system_clock на вашей платформе) и сохраняется со знаком 64-битное целое число (переполнения нет). Таким образом, time > exp == 1 является правильным (time - это 1590775919s, преобразованное в system_clock).

Сб 26 апреля 01:39:43 4758 соответствует time_t из 87990716383.

Я не вижу ничего плохого в использовании вами библиотеки chrono в приведенном выше коде.

Обновление

Значение 87990716383 преобразуется на time_point с использованием from_time_t()

Ах, это в сочетании со знанием того, что на вашей платформе точность system_clock равна nanoseconds, говорит мне, что вы испытываете переполнение при построении exp.

Это не тот код, который у вас есть:

std::time_t t_exp = std::chrono::system_clock::to_time_t(exp);
std::time_t t_time = std::chrono::system_clock::to_time_t(time);
std::cout << std::ctime(&t_exp) << std::ctime(&t_time) << (time > exp) << std::endl;

Имеющийся у вас код выглядит примерно так:

// ...
std::time_t t_exp = 87990716383;
auto exp = std::chrono::system_clock::from_time_t(t_exp);
std::cout << std::ctime(&t_exp) << std::ctime(&t_time) << (time > exp) << std::endl;

На вашей платформе system_clock сохраняет nanoseconds с 1970-01-01 00:00:00 UT C в виде 64-битного целого числа со знаком. Максимальная дата хранения (system_clock::time_point::max()) на вашей платформе:

2262-04-11 23:47:16.854775807

Помимо этого, происходит переполнение базового хранилища nanoseconds.

Когда 87990716383 (секунды) преобразуется в from_time_t, он умножается на миллиард, который выходит за пределы. Значение переполнения равно -4243003985547758080, что соответствует дате 1835-07-19 03: 46: 54.452241920.

Вы можете получить больший диапазон, используя более грубую точность, например:

std::time_t t_exp = 87990716383;
time_point<system_clock, microseconds> exp{seconds{t_exp}};
// exp == 4758-04-26 01:39:43.000000
...