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 к текущему времени, что, вероятно, приведет к вашему вкусу. (отрицательный результат - логическая разница).