2016-06-07 6 views
1

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

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 Теперь не должно быть отрицательным числом. Как я могу рассчитать это право? Есть переполнение?

+0

'долго long', но' diff' уже является отрицательным – user2071938

+0

Это, вероятно, то, что вы ищете: https: //en.wikipedia .org/wiki/Year_2038_problem – stefaanv

+0

Я не работаю с исходным 32-разрядным для unix-времени – user2071938

ответ

-1

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

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

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

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

+0

да, но я хочу время unix, который составляет (секунды sinces '1970-1-1'). Отрицательное число не должно быть неправильным результатом, но в этом случае '9999-12-31' является способом позже, чем' 1970-1-1', поэтому, если нет переполнения, на мой взгляд, результат должен быть положительным. – user2071938

+0

Из [Время в WikI Unix] (https://en.wikipedia.org/wiki/Unix_time): «Максимальное представимое время - вторник 2038-01-19». У вас есть millenniumbug ;-) –

+0

Я не работаю с исходным 32-разрядным для unix-времени – user2071938

-1

Если у вас есть C++ 11, возможно, <chrono> плюс этот free open source date library, который расширяет <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 
+0

Может ли эта библиотека обрабатывать наносекундную прецессию? – user2071938

+0

@ user2071938: Да и нет. '' имеет тип «наносекунды», который хранится в 'int64_t'. Это дает нам диапазон +/- 292 года, для этого примера недостаточно диапазона. Если у вас есть 128-битный тип, вы можете создать свой собственный тип наносекунд: 'using nanoseconds = std :: chrono :: duration <__ int128_t, std :: nano>;'. Это будет достаточным для вашего примера. –

+0

С моей системой '__int128_t' сложно работать. Например, вы не можете передать его в 'cout'. –

0

(кстати - я использовал coliru для следующей продукции, и мой местный НКУ 5.3.1 с повышением 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 секунды

Теперь, в внутренностей библиотеки, есть тип Защита для 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 - Я подозреваю, что вы хотите наносекундную точность? Если это так, я думаю, вам нужно уменьшить диапазон дат.

+0

thx! yes Я установил 'DBOOST_DATE_TIME_POSIX_TIME_STD_CONFIG'. Есть ли возможность обнаружить переполнение? – user2071938

+0

Erm, за исключением взлома библиотеки, чтобы установить размер 'sec_type' (действительно' var_type') в 64-битный, если флаг установлен, нет никакого способа обойти это ... Вы можете отправить отчет об ошибке и посмотреть, они исправит его для следующего выпуска? – Nim

+0

... или альтернативно использовать библиотеку выше, поскольку Говард выделил - он, похоже, способен обрабатывать такие диапазоны, которые вы после ... – Nim

0

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

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

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

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