令人困惑的mktime()函数行为:将tm_hour计数增加1

Dhi*_*eve 12 c++ mktime dst

我正在执行下面的代码.

int main()
{
struct tm storage={0,0,0,0,0,0,0,0,0};
char *p = NULL; 
p = (char *)strptime("2012-08-25 12:23:12","%Y-%m-%d %H:%M:%S",&storage);
char buff[1024]={0};
strftime(buff,1024,"%Y-%m-%d %H:%M:%S",&storage);
cout << buff << endl;
storage.tm_sec += 20;
strftime(buff,1024,"%Y-%m-%d %H:%M:%S",&storage);
cout << buff << endl;
mktime(&storage);
strftime(buff,1024,"%Y-%m-%d %H:%M:%S",&storage);
cout << buff << endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)

如果以上程序执行,则打印'2012-08-25 13:23:32'而不是'2012-08-25 12:23:32'.请帮助,为什么它增加了tm_hour值.如果我在程序中输入日期为"2012-02-25 12:23:32",这可以正常工作,这很令人困惑.

输出 - >

[user@rtpkvm55-vm2 root]$ ./a.out
2012-08-25 12:23:12
2012-08-25 12:23:32
2012-08-25 13:23:32
[user@rtpkvm55-vm2 root]$
Run Code Online (Sandbox Code Playgroud)

我系统上的日期信息, - >

[user@rtpkvm55-vm2 root]$ date
Sat Aug 25 08:28:26 EDT 2012
Run Code Online (Sandbox Code Playgroud)

rve*_*rve 15

怎么了

您指定的日期有效,但在调用时mktime,夏令时storage.tm_isdst为零.mktime看到这个,并认为"嘿,他们给了我一个日期不正确的夏令时标志,让我们解决它".然后它设置tm_isdst为1并更改tm_hour.

另见这个答案.

要解决这个问题

  • timegm而不是mktime
  • 在调用之前将时区设置为UTC mktime(另请参见示例timegm):
    setenv("TZ", "", 1);
    tzset();
    mktime();
  • 使用一个好的日期时间库(比如boost :: locale :: date_time/boost :: date_time,但boost::locale::date_time在选择之前阅读页面上的Q&A部分)


Jef*_*mas 5

哇,没有办法解决它。它一定是您系统的 mktime(3) 实现中的一个错误。mktime(3) 不应该改变struct tm *传递给它的。

我建议检查storage.tm_isdst. 尝试将其设置为 0 以确保它不会与 DST 混淆。如果这不起作用,请尝试将其设置为 -1 以使其自动确定正确的值。

mktime - 将故障时间转换为自 Epoch 以来的时间

tm_isdst 的正值或 0 值会导致 mktime() 最初分别假定夏令时在指定时间有效或无效。tm_isdst 的负值会导致 mktime() 尝试确定夏令时是否在指定时间生效。


我错了 mktime(3) 没有修改struct tm *. 将值标准化是正确的行为。