2012-07-15 48 views
2

std::gmtime当我通过它时最大可能为std::time_t。请参见下面的测试:什么是std :: tm或std :: gmtime的限制?

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是蹩脚的? 作品有什么替代方案?

回答

2

VS2012是不是被糟糕。算一算。

如果time_t是一个64位的整数,在其为2 -1,如果它是一个无符号的整数或2 -1,如果它是一个带符号的整数的秒,然后最大数目。

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

time_ttm_year是一个32位的int,其最大值为2 -1≈2.1×10 9

显然,您不能在32位有符号整数中存储〜2.9 * 10 。当你提出要求时,gmtime()正确地失败。

您或许可以修改我的gmtime()的实现this answer以处理非常大的值。您需要解决SecondsSinceEpoch + 11644473600ULL中的溢出问题,并将intsuints更改为uint64s

+0

谢谢,这确实解释了非常高的数字。但是'(std :: numeric_limits :: max()-1)/ 10000000'也失败了,这只会是29247年的范围,2924年的范围也是如此,最后是292年的范围。我不知道它到底停在哪里,但是这个事情在大约300到3000年之间就失败了。我想我必须像你所建议的那样写我自己的 – David 2012-07-15 13:08:26

+0

你可以做一个二进制搜索来确定截止日期/时间。我很想知道它是什么。它可能会揭示逻辑。 – 2012-07-15 19:44:07

+0

〜300到〜3000年将需要33到37位。我怀疑这个实现是否基本上是32位,尽管'time_t'是64位(注意你可以选择'time_t'的大小)。 – 2012-07-16 00:53:06

1

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

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

ERRORS

的gmtime的()和gmtime_r()函数应失败,如果:

[EOVERFLOW] 结果不能表示。

它不直接说的极限是什么,虽然它说,如果自纪元秒是否定的,他们的实际时间关系undefined

作为替代方案,尝试推动

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

(虽然在我的Linux安装,from_time_t()似乎碰到天花板早于gmtime的)

相关问题