LIBC的mktime函数对于相同的输入返回不同的值
mktime function of LIBC returns different values for the same input
我们知道时区UTC+8有一些时钟变化。例如,在1928年1月1日,00:00:00时钟倒转0:05:52小时到1927年12月31日,23:54:08。此外,在1940-1941年和1986-1991年使用日光节约时间。当我用这些日期在linux下测试函数mktime
时,我有不同的返回值。代码如下:
#include <stdio.h>
#include <string.h>
#include <time.h>
int main(int argc, char *argv[])
{
struct tm timeinfo;
memset(&timeinfo, 0, sizeof(timeinfo));
while(fscanf(stdin, "%d%d%d%d%d%d",
&timeinfo.tm_year, &timeinfo.tm_mon, &timeinfo.tm_mday,
&timeinfo.tm_hour, &timeinfo.tm_min, &timeinfo.tm_sec) != EOF)
{
timeinfo.tm_year -= 1900;
timeinfo.tm_mon -= 1;
fprintf(stdout, "%lldn", mktime(&timeinfo));
}
return 0;
}
以测试输入和输出为例,相同的输入"1940 6 2 23 59 59"answers"1940 6 31 1 0 0"将根据调用顺序有不同的返回值:
1940 6 2 23 59 59
-933494401
1940 6 3 1 0 0
-933490800
1940 6 3 1 0 0
-933494400
1940 6 2 23 59 59
-933498001
1940 6 2 23 59 59
-933494401
相同输入1940 6 31 1 0 0
为什么?为什么mktime
的返回值随调用顺序不同而不同?
我读了一些版本的mktime
的源代码,但没有发现任何部分的代码,可能会导致这个问题。
谁能解释一下为什么会发生这种情况?非常感谢。
新增案例:
1927 12 31 23 54 8
-1325491552
1927 12 31 23 54 7
-1325491905
1927 12 31 23 54 8
-1325491904
1928 1 1 0 0 0
-1325491200
1927 12 31 23 54 8
-1325491552
首先将timeinfo.tm_isdst
设置为0,这要求mktime
将时间视为非夏令时时间。
mktime
将对传入的struct tm
进行规范化,使字段处于适当的范围内;该过程的一部分将根据夏令时在指定时间是否实际生效来调整夏令时标志。(见文档。)如果DST生效,它会将该标志设置为正值,并相应地调整struct tm
的其他字段。
循环的后续迭代将覆盖传递给fscanf
的六个字段,但不覆盖DST字段。因此,如果循环的较早迭代导致设置了该标志,则稍后的迭代仍然会设置该标志。因此,您实际上没有将相同的时间传递给mktime
,并且它返回不同的结果。
从您打印的内容来看,场景似乎是:
1940 6 2 23 59 59 // tm_isdst == 0, asks mktime to consider this non-DST, and DST not in effect at this time
-933494401 // tm_isdst still 0
1940 6 3 1 0 0 // tm_isdst == 0, asks mktime to consider this non-DST, but at this time DST was in effect
-933490800 // tm_isdst now positive
1940 6 3 1 0 0 // tm_isdst > 0, asks mktime to consider this DST, and DST was actually in effect
-933494400 // tm_isdst still positive
1940 6 2 23 59 59 // tm_isdst > 0, asks mktime to consider this DST, but actually DST wasn't in effect
-933498001 // tm_isdst becomes 0
1940 6 2 23 59 59 // tm_isdst == 0, asks mktime to consider this non-DST
-933494401 // tm_isdst still 0
演示。
问题可能不是mktime
,而是sscanf
。我不能测试它,因为你的例子对我来说是有效的(好吧,我不确定它是正确的时间,但它是一致的),但很可能scanf
读取的数字比它应该少,这样前一行的输入就会与当前一行混合在一起。
fscanf
是已知的有行结束的问题,所以检查返回值(它应该是6
)值尝试一行一行地读取fgets
到缓冲区,然后使用sscanf
。
- 在 Arduino 上使用 sscanf 会导致与 const char * 不匹配,并且返回值始终相同,尽管输入值不同
- 从 cin 读取不会返回整个输入字符串
- 程序中的布尔函数返回输入的范围无论如何都是无效的
- 返回C++输入
- C++模板编程设计问题 - 根据输入文件返回不同的类型
- cpp 返回具有相同输入的不同输出
- 从子菜单返回后,正确的输入至少进入验证循环一次
- C++ CIN 值返回 0 而不是输入值
- 输出返回编号。等于输入字符串的单词的字符串数
- 函数重载并根据相同的输入返回不同的数据类型
- 如何根据输入C++更改返回类型?
- 函数返回包含输入容器的特定元素的容器
- C++输入为什么当我输入一个字母时会返回0
- 阶乘函数只返回C++中输入的答案
- 查找匹配的输入,并返回匹配的输入和不匹配的输入
- 实现一个函数,该函数将字符串作为输入并返回一个新字符串,辅音字母不替换为 "!"
- 当条件不满足时,必须返回输入
- 行号:使用 __LINE__ 返回输入文件的行号的任意方法
- 函数不返回输入到数组中的最高值和最低值
- 为什么 ifstream 返回输入文件的最后一个值两次