为何strptime与mktime对第三个日期生成异常时间戳?
问题:strptime与mktime转换第三个日期时结果异常
我用以下C代码从文本文件解析日期时间:
#define DATETIME_FORMAT "%Y-%m-%d %H:%M:%S"
if (!strptime(datetimestr, DATETIME_FORMAT, &record->datetime)) { return 0; } else { record->message_size = strlen(messagestr) - 1; messagestr[record->message_size] = '\0'; strcpy(record->message, messagestr); printf("parsed '%s' '%s' %ld\n", messagestr, datetimestr, mktime(&record->datetime)); return 1; }
执行后得到打印结果:
parsed 'ETC' '2023-04-03 09:00:19' 1680508819 parsed 'StandUp' '2023-04-03 09:00:47' 1680508847 parsed 'Stop' '2023-04-03 09:11:55' 1680505915
将这些时间戳转换为GMT时间后发现:
- 1680508819 → 2023年4月3日 08:00:19
- 1680508847 → 2023年4月3日 08:00:47
- 1680505915 → 2023年4月3日 07:11:55
前两个时间的本地时间(09:xx)与GMT差1小时,符合夏令时的时区偏移,但第三个时间差了2小时,完全不符合预期,这是为什么?
问题原因与解决方法
核心问题是**strptime不会初始化struct tm中未被解析的字段**,包括tm_isdst(夏令时标识)。
strptime只会填充格式字符串中对应的字段(比如年、月、日、时、分、秒),而tm_isdst、tm_yday、tm_wday这些字段会保留内存里的原始垃圾值。当你调用mktime时,它会根据tm_isdst的值来判断是否应用夏令时:
- 如果
tm_isdst = -1:mktime会自动检测当前时间是否处于夏令时区间,计算正确的UTC时间戳 - 如果
tm_isdst = 0或1:mktime会强制使用非夏令时/夏令时规则,不管实际日期是否符合
你的前两次调用中,栈上的tm_isdst碰巧是-1,mktime自动检测到4月3日处于夏令时,所以计算出的时间戳对应GMT+1的本地时间(09:xx → GMT 08:xx)。但第三次调用时,tm_isdst的垃圾值是0,mktime强制按非夏令时处理,导致时区偏移变成了GMT+2(09:xx → GMT 07:xx),最终得到错误的时间戳。
解决方法很简单:在调用strptime前,手动初始化整个struct tm结构体,尤其是把tm_isdst设为-1,让mktime自动处理夏令时:
// 初始化struct tm为0,再设置tm_isdst为-1 memset(&record->datetime, 0, sizeof(struct tm)); record->datetime.tm_isdst = -1; if (!strptime(datetimestr, DATETIME_FORMAT, &record->datetime)) { // ... 原有逻辑 }
这样就能保证每次mktime都自动检测夏令时,不会出现随机错误。
内容的提问来源于stack exchange,提问作者tino415
相关产品推荐
相关产品推荐

