提问者:小点点

time_t增强日期转换,结果不正确


我有一个unix时间戳集合,我正在转换为boost(1.65.1)日期,但是当它们在将来太远时,转换似乎会中断。2040年前后的任何事情似乎都以某种方式回到了1900年后。

给出以下代码。。。

        {
            std::time_t t = 1558220400;
            boost::gregorian::date date = boost::posix_time::from_time_t(t).date();
            std::cout << "Date: " << date << std::endl;
        }

        {
            std::time_t t = 2145500000;
            boost::gregorian::date date = boost::posix_time::from_time_t(t).date();
            std::cout << "Date: " << date << std::endl;
        }

        {
            std::time_t t = 2500000000;
            boost::gregorian::date date = boost::posix_time::from_time_t(t).date();
            std::cout << "Date: " << date << std::endl;
        }

。。。我得到以下输出。。。

    Date: 2019-May-18
    Date: 2037-Dec-27
    Date: 1913-Feb-13

。。。然而,我期待着以下的产出。。。

Expected output:
    Date: 2019-May-18
    Date: 2037-Dec-27
    Date: 2049-Mar-22

我是不是做错了什么?


共2个答案

匿名用户

看来你正在经历2038年的问题。

32位带符号整数可表示的最大数字是2'147'483'647。1970年1月1日00:00:00 UTC(UNIX epoch)之后的2'147'483'647秒是2038年1月19日03:14:07 UTC。之后的任何UNIX时间都不能使用32位有符号整数表示。

系统上的是32位,或者在boost库中转换为32位。您可以从源代码中看到,boost使用将输入转换为(在版本1.70中仍然如此)。是32位(例如在windows上),甚至在64位体系结构上也是如此。它在许多其他系统上是64位的,例如64位Linux。

匿名用户

正如eerorika所指出的,这是由整数溢出引起的,因为BOOST::POSIX_TIME::FROM_TIME_T正在将64位的time_t值强制转换为32位长(在Windows上)。

如果您处于紧要关头,发现自己处于相同的位置,则可以使用以下函数执行转换:

boost::gregorian::datetimet_to_date(time_t t)
{
    auto time = boost::posix_time::ptime(boost::gregorian::date(1970,1,1));

    int64_t current_t = t;
    long long_max = std::numeric_limits<long>::max();
    while(current_t > 0)
    {
        long seconds_to_add = 0;
        if(current_t >= long_max)
            seconds_to_add = long_max;
        else
            seconds_to_add = static_cast<long>(current_t);

        current_t -= seconds_to_add;
        time += boost::posix_time::seconds(seconds_to_add);
    }

    return time.date();
}