Создайте time_point в секундах:: макс приводит к отрицательному значению

Я пытаюсь использовать time_point для эффективного представления навсегда, установив для него значение second::max, которое, я считаю, должно представлять столько времени с эпохи. Однако при этом я получаю -1 как время с начала эпохи в результирующей time_point. Что я не понимаю?

#include <iostream>
#include <chrono>
using namespace std;
using namespace std::chrono;

int main() {
    auto tp1 = system_clock::time_point( seconds::zero() );
    auto tp2 = system_clock::time_point( seconds::max() );
    cout << "tp1: " << duration_cast<seconds>(tp1.time_since_epoch()).count() << endl;
    cout << "tp2: " << duration_cast<seconds>(tp2.time_since_epoch()).count() << endl;
    return 0;
}

Вывод работает, это:

tp1: 0
tp2: -1

person ryan0270    schedule 28.09.2016    source источник


Ответы (2)


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

#include <chrono>
#include <iostream>

using days = std::chrono::duration
    <int, std::ratio_multiply<std::ratio<24>, std::chrono::hours::period>>;
using years = std::chrono::duration
    <double, std::ratio_multiply<std::ratio<146097, 400>, days::period>>;

template <class Rep, class Period>
void
max_limit(std::chrono::duration<Rep, Period> d)
{
    std::cout << "[" << Period::num << '/' << Period::den << "] ";
    std::cout << years{d.max()}.count() + 1970 << '\n';
}

int
main()
{
    using namespace std;
    using namespace std::chrono;
    max_limit(nanoseconds{});
    max_limit(microseconds{});
    max_limit(milliseconds{});
    max_limit(seconds{});
}

Это выведет год (в плавающей запятой), в котором time_point<system_clock, D> будет максимально для любой продолжительности D. Эта программа выводит:

[1/1000000000] 2262.28
[1/1000000] 294247
[1/1000] 2.92279e+08
[1/1] 2.92277e+11

Значение system_clock основано на переполнении в наносекундах в 2262 году. Если вы огрубите это до микросекунд, вы переполнитесь в 294 247 году. И так далее.

Как только вы укрупняетесь до секунд, максимум выходит в нелепый диапазон. Но когда вы конвертируете это обратно в system_clock::time_point, что по крайней мере так же точно, как микросекунды, и, возможно, так же точно, как наносекунды (в зависимости от вашей платформы), вы просто выбиваете его из воды.

Для решения вашей проблемы рекомендую:

auto M = system_clock::time_point::max();
person Howard Hinnant    schedule 28.09.2016
comment
дох, я должен был знать, что нужно искать time_point::max(). Спасибо и за тестовую программу; Я не стал думать, что time_point внутри будет использовать миллисекунды (или меньше). - person ryan0270; 28.09.2016

Добавление еще нескольких диагностических данных показывает проблему (в моей системе):

#include <iostream>
#include <chrono>
using namespace std;
using namespace std::chrono;

int main() {
    auto tp1 = system_clock::time_point( seconds::zero() );
    auto tp2 = system_clock::time_point( seconds::max() );

    using type = decltype(system_clock::time_point(seconds::zero()));
    cout << type::duration::max().count() << endl;
    cout << type::duration::period::den << endl;
    cout << type::duration::period::num << endl;

    cout << seconds::max().count() << endl;
    cout << milliseconds::max().count() << endl;
    cout << "tp1: " << duration_cast<seconds>(tp1.time_since_epoch()).count() << endl;
    cout << "tp2: " << duration_cast<seconds>(tp2.time_since_epoch()).count() << endl;
    return 0;
}

Для меня значение знаменателя составляет 1 000 000 для system_clock time_point. Таким образом, максимальное количество секунд будет переполняться при преобразовании.

person Richard Hodges    schedule 28.09.2016