boost::posix_time::time_duration переполнен?

У меня есть следующий код, чтобы получить время UNIX от posix_time

boost::posix_time::ptime time1(boost::gregorian::date(9999,12,31));
boost::posix_time::ptime epoch(boost::gregorian::date(1970,1,1));

boost::posix_time::time_duration diff = time1-epoch;
cout<<"A: "<<time1<<endl;
cout<<"B: "<<epoch<<endl;
cout<<"C: "<<diff<<endl;

unix_time = diff.total_seconds()

дает мне этот вывод

9999-Dec-31 00:00:00
1970-Jan-01 00:00:00
-1347834:03:51.933722624

Сейчас diff не должно быть отрицательным числом. Как я могу рассчитать это право? Есть ли переполнение?

4 ответа

(кстати - я использовал coliru для вывода ниже, и мой локальный gcc 5.3.1 с boost 1.60 воспроизводит)

Проблема в том, что вы хотите получить это число в секундах, поэтому давайте попробуем некоторую базовую математику (и посмотрим, правильно ли я понял!):)

A: 9999-Dec-31 00:00:00
B: 1970-Jan-01 00:00:00
C: 70389504:00:00

Таким образом, разница (выраженная в часах) составляет 70389504 часа. Который в секундах:

70389504 * 60 * 60 => 253402214400 секунд

Теперь во внутренней части библиотеки есть тип def для sec_type который по умолчанию boost::int32_t, Так что, если это не установлено int64_tвышеуказанное значение будет переполнено.

Что касается того, как переопределить это, это невозможно, если вы не взломать date_time библиотека и изменить значение по умолчанию в time_resolution_traits.h от boost::int32_t в boost::int64_.. (может быть и другой способ, но я недостаточно подробно исследовал код, чтобы сказать вам, что это будет..)

Теперь для вашей реальной проблемы, кажется, у вас есть этот набор -DBOOST_DATE_TIME_POSIX_TIME_STD_CONFIG - Я подозреваю, что вы хотите наносекундную точность? Если это так, я думаю, вы должны уменьшить поддерживаемый диапазон дат.

Это известная проблема в boost:: date_time: https://svn.boost.org/trac/boost/ticket/3109

Time_duration может представлять большие интервалы, чем количество секунд, которое может представлять тип boost::time_duration::total_seconds().

Если вам нужно общее количество секунд, лучше использовать

time_duration td = ...
auto seconds = td.ticks() / time_duration::ticks_per_seconds();

Если у вас есть C++11, возможно, <chrono> плюс эта бесплатная библиотека дат с открытым исходным кодом, которая расширяет <chrono> может помочь?

#include "date.h"
#include <iostream>

int
main()
{
    using namespace date::literals;
    auto time1 = 9999_y/dec/31;
    auto epoch = 1970_y/jan/1;
    std::chrono::seconds diff = date::sys_days{time1} - date::sys_days{epoch};
    std::cout << "A: " << time1 << '\n';
    std::cout << "B: " << epoch << '\n';
    std::cout << "C: " << diff.count() << '\n';
}

Выход:

A: 9999-12-31
B: 1970-01-01
C: 253402214400

Вы всегда можете инвертировать положительное / отрицательное, вычитая его из нуля.

diff = 0 - diff; // if diff was negative it will be positive now.

Редактировать 1: дополнительная информация;

Также вы по формуле time1-epoch рассчитаете разницу между двумя точками во времени. Вы должны добавить diff к текущему времени, что, вероятно, приведет к вашему вкусу. (отрицательный результат - логическая разница).

Другие вопросы по тегам