c++ mktime()函数的混淆行为:tm_hour计数递增1

lp0sw83n  于 2023-02-06  发布在  其他
关注(0)|答案(4)|浏览(141)

我正在执行下面的代码。

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
q35jwt9p

q35jwt9p1#

"会发生什么"
您指定的日期使用夏令时,但是当调用mktime时,storage.tm_isdst为零。mktime看到这一点并认为“嘿,他们给我的日期带有错误的夏令时标志,让我们来修正它”。然后它将tm_isdst设置为1并更改tm_hour
另请参见this答案。

去弥补

  • 使用timegm代替mktime
  • 在调用mktime之前将时区设置为UTC(另请参见timegm中的示例):
setenv("TZ", "", 1);
tzset();
mktime();
guykilcj

guykilcj2#

哇,这是没有办法的,这一定是系统实现mktime(3)中的一个bug,mktime(3)不应该改变传递给它的struct tm *
我建议检查storage.tm_isdst的值。尝试将其设置为0以确保它不会混淆DST。如果这不起作用,尝试将其设置为-1以让它自动确定正确的值。
mktime - convert broken-down time into time since the Epoch
tm_isdst的正值或0值会使mktime()最初分别假定夏令时在指定时间有效或无效。tm_isdst的负值会使mktime()尝试确定夏令时在指定时间是否有效。
关于mktime(3)没有修改struct tm *,我错了,规范化值是正确的行为。

ncecgwcz

ncecgwcz3#

你必须在tm结构体中设置tm_isdst,否则它是未初始化的,因此被设置为一个随机垃圾值。然后,当你根据tm_isdst变量中的随机垃圾调用mktime时,它要么应用夏令时,要么不应用,看起来不可预测。
但是,如果您将其设置为-1,则会告诉mktime您不知道夏令时是否生效,因此第一次调用mktime将修复它。
因此,解决此问题的最简单方法是添加:

storage.tm_isdst = -1;

然后调用mktime

ycggw6v2

ycggw6v24#

下面是修复代码的技巧:

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;

}

相关问题