取以下代码:
static void printTime(const struct tm* t, const time_t stamp){
printf("%d-%d-%d, %d:%d:%d (DST %s) (stamp: %zu)\n",
1900 + t->tm_year, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, t->tm_isdst ? "Active" : "Inactive", stamp);
}
int main(){
time_t t = 1540633936;
struct tm tStruct;
localtime_r(&t, &tStruct);
printTime(&tStruct, t);
for (unsigned i = 0; i < 14; ++i){
tStruct.tm_sec += 7200;
//tStruct.tm_hour += 2;
tStruct.tm_isdst = -1;
t = mktime(&tStruct);
localtime_r(&t, &tStruct);
printTime(&tStruct, t);
}
return 0;
}它显示了两种增加日期的方法。mktime的文档告诉我:
mktime()函数将tm结构的字段修改如下: tm_wday和tm_yday设置为从其他字段的内容确定的值;如果结构成员超出了它们的有效间隔,它们将被规范化(例如,10月4日改为11月9日);tm_isdst分别被设置为正值或0,以指示在指定的时间内是否有效。
基于此,我期望正常化的工作方式是,增加7200秒相当于增加两个小时。但产出不同:
tStruct.tm_sec += 7200;给予:
2018-10-27,11:52:16 (DST活动)(邮票: 1540633936) 2018-10-27,13:52:16 (DST活动)(邮票: 1540641136) 2018-10-27,15:52:16 (DST活动)(邮票: 1540648336) 2018-10-27,17:52:16 (DST活动)(邮票: 1540655536) 2018-10-27,19:52:16 (DST活动)(邮票: 1540662736) 2018-10-27,21:52:16 (DST活动)(邮票: 1540669936) 2018-10-27,23:52:16 (邮票: 1540677136) 2018-10-28,1:52:16 (邮票: 1540684336) 2018-10-28,2:52:16 (DST活性)(邮票: 1540691536) 2018-10-28,3:52:16 (DST不活动)(邮票: 1540695136) 2018-10-28,5:52:16 (DST不活动)(邮票: 1540702336) 2018-10-28,7:52:16 (DST )(邮票: 1540709536) 2018-10-28,9:52:16 (邮票: 1540716736) 2018-10-28,11:52:16 (不活动)(邮票: 1540723936) 2018-10-28,13:52:16 (邮票: 1540731136)
(注意DST更改后直接跳错了时间)
tStruct.tm_hour += 2;给予:
2018-10-27,11:52:16 (DST活动)(邮票: 1540633936) 2018-10-27,13:52:16 (DST活动)(邮票: 1540641136) 2018-10-27,15:52:16 (DST活动)(邮票: 1540648336) 2018-10-27,17:52:16 (DST活动)(邮票: 1540655536) 2018-10-27,19:52:16 (DST活动)(邮票: 1540662736) 2018-10-27,21:52:16 (DST活动)(邮票: 1540669936) 2018-10-27,23:52:16 (邮票: 1540677136) 2018-10-28、1:52:16 (邮票: 1540684336) 2018-10-28、3:52:16 (DST活性)(邮票: 1540695136) 2018-10-28、5:52:16 (DST不活动)(邮票: 1540702336) 2018-10-28、7:52:16 (DST不活动)(邮票: 1540709536) 2018-10-28、9:52:16 (DST )(邮票: 1540716736) 2018-10-2811:52:16 (邮票: 1540723936) 2018-10-28,13:52:16 (不活动)(邮票: 1540731136) 2018-10-28,15:52:16 (邮票: 1540738336)
这就是我所期望的行为(至少对我来说)。
所以,我的问题是:真的有错误吗?或者这是记录在案的行为,在什么地方?
当tm_hour需要被mktime更改时,这种行为也会发生。以下列例子为例:
tStruct.tm_hour += 25;给予:
2018-10-27,11:52:16 (DST活动)(邮票: 1540633936) 2018-10-28,12:52:16 (DST非活动)(邮票: 1540727536) 2018-10-29,13:52:16 (DST非活动)(邮票: 1540817536) 2018-10-30,14:52:16 (DST非活动)(邮票: 1540907536) 2018-10-31,15:52:16 (DST非活动)(邮票: 1540997536) 2018-11-1,16:52:16 (DST )(DST)(邮票: 1541087536) 2018-11-2,17:52:16 (邮票: 1541177536) 2018-11-3、18:52:16 (不活动)(邮票: 1541267536) 2018-11-4、19:52:16 (不活动) 2018-11-5 (邮票: 1541357536) 2018-11-5、20:52:16 (不活动)(邮票: 1541447536) 2018-11-6、21:52:16 (不活动)(邮票: 1541537536) 2018-11-7、22:52:16 (不活动)(邮票: 1541627536) 2018-11-823:52:16 (邮票: 1541717536) 2018-11-10,0:52:16 (不活动)(邮票: 1541807536) 2018-11-11,1:52:16 (不活动)(邮票: 1541897536)
tStruct.tm_sec += 90000给予:
2018-10-27,11:52:16 (DST活动)(邮票: 1540633936) 2018-10-28,11:52:16 (DST非活动)(邮票: 1540723936) 2018-10-29,12:52:16 (DST非活动)(邮票: 1540813936) 2018-10-30,13:52:16 (DST非活动)(邮票: 1540903936) 2018-10-31,14:52:16 (DST非活动)(邮票: 1540993936) 2018-11-1,15:52:16 (DST )(DST)(邮票: 1541083936) 2018-11-2,16:52:16 (邮票: 1541173936) 2018-11-3、17:52:16 (不活动)(邮票: 1541263936) 2018-11-4、18:52:16 (不活动) 2018-11-5 (邮票: 1541353936) 2018-11-5、19:52:16 (不活动)(邮票: 1541443936) 2018-11-6、20:52:16 (不活动)(邮票: 1541533936) 2018-11-7、21:52:16 (不活动)(邮票: 1541623936) 2018-11-822:52:16 (邮票: 1541713936) 2018-11-9、23:52:16 (不活动)(邮票: 1541803936) 2018-11-11、0:52:16 (不活动)(邮票: 1541893936)
发布于 2018-09-03 11:04:24
根据您的确切时区(和管辖范围),在2018-10-28号清晨的某个时间,由于DST结束,时钟会移回1小时。从你的例子来看,这似乎发生在你的时区/管辖范围的3点。
在第一种情况下(添加7200秒到2018-10-28,1:52:16),tm_sec值超出正常范围(0 - 59),因此mktime可以确定您已经添加了2小时,并且由于它知道这是穿越DST边界,因此它相应地调整时间。2018-10-28,2:52:16,2018-10-28,1:52:16。
对于第一个例子中的下一个增量(添加7200秒到2018-10-28,2:52:16),同样的事情再次发生(因为您再次穿越DST边界--毕竟您已经将tm_isdst重置为-1 )。2018-10-28,3:52:16,2018-10-28,2:52:16。
在第二种情况下(添加2小时到2018-10-28,1:52:16),tm_hour值仍在正常范围内(0-23),因此mktime无法确定您是否增加了2小时,它只是将其视为本地时间。2018-10-28,3:52:16,2018-10-28,1:52:16。
为了避免这样的问题:
tm_isdst重置为-1 (而且您知道会发生什么)。https://stackoverflow.com/questions/52147683
复制相似问题