如何导致std :: mktime失败?

时间:2018-04-19 12:40:55

标签: c++ gcc 64-bit

我使用std::mktime在我的程序中设置/获取时间。手册页告诉:

  

允许时间值超出正常范围。

并且如果它不能将结果表示为std :: time_t

,则返回-1

我在单元测试中尝试了所有内容以使此功能失败,但没有成功。 These只是一些尝试:

#include <iostream>
#include <iomanip>
#include <ctime>
#include <stdlib.h>

int main()
{
    setenv("TZ", "/usr/share/zoneinfo/America/New_York", 1); // POSIX-specific

    std::time_t t = std::time(nullptr);
    std::tm tm = *std::localtime(&t);
    std::cout << "Today is           " << std::put_time(&tm, "%c %Z")
              << " and DST is " << (tm.tm_isdst ? "in effect" : "not in effect") << '\n';
    tm.tm_year = 550;
    tm.tm_year = 123456789;
    tm.tm_mon = 88;
    tm.tm_mday = 200;
    //tm.tm_mon -= 100;  // tm_mon is now outside its normal range
    std::mktime(&tm);  // tm_dst is not set to -1; today's DST status is used
    std::cout << "100 months ago was " << std::put_time(&tm, "%c %Z")
              << " and DST was " << (tm.tm_isdst ? "in effect" : "not in effect") << '\n';
}

那么,如何设置参数以使此功能失效?

正如评论中所建议的,I tried INT_MAX并且它仍然没有失败。所以,这个:

tm.tm_year = std::numeric_limits< decltype( tm.tm_year ) >::max();

    if ( -1 == std::mktime(&tm) )
        std::cout << "std::mktime() failed)" << '\n'; 

仍然不会让它失败。

$CXX --version
aarch64-pdm3-linux-g++ (GCC) 6.4.0

2 个答案:

答案 0 :(得分:2)

您的示例确实因建议的输入std::numeric_limits< decltype( tm.tm_year ) >::max()而失败。您的示例不检查-1返回值。如果你添加

auto err = std::mktime(&tm);  // tm_dst is not set to -1, err is.
此输入的

err设置为-1。

您可以在https://ideone.com/GUcM3N

看到失败

您还可以在http://coliru.stacked-crooked.com/a/8288579ec8924d7e

看到失败

两项服务的输出相同:

Today is           Thu Apr 19 09:07:40 2018 EDT and DST is in effect
100 months ago was Thu ? 200 09:07:40 -2147481749 EDT and DST was in effect
-1

答案 1 :(得分:1)

发生溢出时,

mktime将无法更新tm结构,例如当年份设置为INT_MAX并且添加超过12个月(超过一年)。像这样:

std::tm tm;
tm.tm_year = INT_MAX;
tm.tm_mon = 13;
std::time_t rc = std::mktime(&tm);

如果您将年份设置为tm,将月份设置为零并减去一天(将INT_MIN设置为0并tm_mon,则也无法更新tm_mday结构到-1):

std::tm tm;
tm.tm_year = INT_MIN;
tm.tm_mon = 0;
tm.tm_mday = -1;

std::time_t rc = std::mktime(&tm);

如果月份和tm_mday的组合仍然少于一年,那么当年份设置为INT_MAX不会失败,因为这仍然是可表示的!

然而,正如MSalters所提到的,这并不总是导致-1作为返回值。有时mktime将无法将时间戳标准化为有效的tm结构时返回-1。但是,根据实现mktime,只有在time_t中无法表达时间时才返回-1(自从time_t未指定时可能永远不会)。在后一种情况下,假设将tm结构规范化为有效值实际上是危险的。