3

std::gmtime当我尽可能地通过它时,对我来说失败了std::time_t。请参阅以下测试:

std::cout   << "sizeof(std::time_t): " << sizeof(std::time_t) << '\n'
            << "sizeof(long long): " << sizeof(long long) << '\n'
            << "sizeof(unsigned int): " << sizeof(unsigned int) << "\n\n";

auto testgmtime = [](std::time_t time)
{
    std::tm* ptm = std::gmtime(&time);
    std::cout << (ptm ? "succeeded\n" : "failed\n");
};

testgmtime(std::numeric_limits<std::time_t>::max());
testgmtime(std::numeric_limits<long long>::max());
testgmtime(std::numeric_limits<long long>::max()-1);
testgmtime(static_cast<std::time_t>(std::numeric_limits<unsigned int>::max())*2);
testgmtime(std::numeric_limits<int>::max());

输出:

sizeof(std::time_t): 8
sizeof(long long): 8
sizeof(unsigned int): 4

failed
failed
failed
succeeded
succeeded

我正在使用VS2012。是否有我没有看到的标准限制或者这个 VS 很糟糕?我可以使用什么替代方案

4

2 回答 2

2

VS2012 并不糟糕。算一算。

如果time_t是 64 位整数,则其中的最大秒数是 2 64 -1(如果是无符号整数)或 2 63 -1(如果是有符号整数)。

粗略地说,2 63秒对应于 2 63 /(60*60*24*365) ≈ 2.9*10 11年。

time_t'stm_year是一个 32 位int的 ,其最大值为 2 31 -1 ≈ 2.1*10 9

显然,您不能将 ~2.9*10 11存储在 32 位有符号整数中。当你gmtime()要求它时,它理所当然地失败了。

您可以修改我gmtime()此答案中的实现以处理非常大的值。您需要解决溢出问题SecondsSinceEpoch + 11644473600ULL并将一些ints和更改uintsuint64s.

于 2012-07-15T08:35:17.747 回答
1

C++ 只说gmtime可能会失败。指定gmtime大输入行为的标准是POSIX

如果检测到错误,gmtime() 将返回一个空指针并设置 errno 以指示错误。

错误

如果出现以下情况,gmtime() 和 gmtime_r() 函数将失败:

[EOVERFLOW] 结果无法表示。

它没有直接说明限制是什么,尽管它确实说如果自 Epoch 以来的秒数为负数,则它们与实际时间的关系是undefined

作为替代方案,请尝试提升

auto testgmtime = [](std::time_t time)
{
    std::cout << boost::posix_time::from_time_t(time) << '\n';
};

(尽管在我的 linux 设置中,from_time_t() 似乎比 gmtime 更早达到了上限)

于 2012-07-15T07:16:57.400 回答