14

我正在执行下面的代码。

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;
}

如果执行上述程序,它会打印“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]$

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

[user@rtpkvm55-vm2 root]$ date
Sat Aug 25 08:28:26 EDT 2012
4

3 回答 3

19

怎么了

您指定的日期具有夏令时有效,但在调用 时mktimestorage.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
于 2012-08-25T14:02:18.230 回答
5

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

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

mktime - 将分解时间转换为纪元以来的时间

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


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

于 2012-08-25T13:27:15.140 回答
0

您必须tm_isdsttm结构中设置,否则它未初始化,因此被设置为随机垃圾值。然后,当您mktime根据tm_isdst变量中的随机垃圾进行调用时,它要么应用夏令时,要么不应用,这似乎是不可预测的。

但是,如果将其设置为-1,则mktime表明您不知道夏令时是否有效,因此第一次调用 tomktime将修复它。

因此,解决此问题的最简单方法是添加:

storage.tm_isdst = -1;

打电话之前mktime

于 2021-02-04T01:37:58.657 回答