我正在执行以下代码。
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-2512:23:32"。请帮助,为什么它正在增加tm_hour值。如果我在程序中输入日期为"2012-02-25 12:23:32",这是正确的,这很令人困惑。
OUtput->
[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
发生了什么
您指定的日期具有夏令时,但当调用mktime
时,storage.tm_isdst
为零。mktime
看到了这一点,并认为"嘿,他们给了我一个带有错误夏令时标志的日期,让我们纠正它"。然后,它将tm_isdst
设置为1并改变tm_hour
。
另请参阅此答案。
修复
- 使用
timegm
而不是mktime
- 在调用
mktime
之前将时区设置为UTC(另请参阅timegm
中的示例):setenv("TZ",",1);tzset();mktime()
- 使用一个好的日期时间库(比如boost::locale::date_time/boost::date_time,但在选择之前请先阅读
boost::locale::date_time
页面上的问答部分)
哇,这是没有办法的。这一定是你的系统实现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 *
。规范化值是正确的行为。
您必须在tm
结构中设置tm_isdst
,否则它将被取消初始化,从而被设置为随机垃圾值。然后,当您根据tm_isdst
变量中的随机垃圾来调用mktime
时,它要么应用夏令时,要么不应用,这似乎是不可预测的。
但是,如果您将其设置为-1
,则会告诉mktime
您不知道夏令时是否有效,因此对mktime
的第一次调用将修复它。
因此,解决此问题的最简单方法是添加:
storage.tm_isdst = -1;
在调用CCD_ 21之前。
这里有一个修复代码的技巧:
int main()
{
// Need to know if daylight saving is on or off, use the following trick
// Get the current time in seconds since epoch, convert it to local time,
// tm_isdst(is daylight saving) value, in the tm variable returned by the localtime(), will be set accordingly
time_t now = time(0);
struct tm *tm2= localtime(&now);
struct tm storage={0,0,0,0,0,0,0,0,tm2->tm_isdst}; // Note: used the is daylight saving on flag fetched above
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;
}