为何strptime()无法解析yyyymmddhhmmss格式无分隔符日期时间字符串?
问题分析与解决
你遇到的问题核心是AIX 5.3系统的strptime()实现不支持连续无分隔符的格式说明符,比如%Y%m%d%H%M%S这种写法无法被正确解析,导致strptime()返回NULL,此时struct tm结构的内容未被正确初始化,后续mktime()处理无效的时间结构就会返回-1(转换成unsigned long后就是4294967295),对应输出1970年的初始时间。
另外你代码里没有检查strptime()的返回值,这也是一个容易忽略的点——一旦解析失败,后续的时间处理都是无效的。
解决方法
方法1:用sscanf()直接解析固定长度字段
sscanf()可以精准匹配固定长度的数字段,刚好适合这种无分隔符的时间格式,代码修改如下:
#include <stdio.h> #include <time.h> #include <string.h> int main(int argc, char *argv[]) { struct tm stm; time_t utm; char strtime[] = "20221116082310"; // yyyymmddhhmmss int year, mon, day, hour, min, sec; // 用sscanf拆分固定长度的字段 if (sscanf(strtime, "%4d%2d%2d%2d%2d%2d", &year, &mon, &day, &hour, &min, &sec) == 6) { memset(&stm, 0, sizeof(stm)); stm.tm_year = year - 1900; // tm_year是从1900年开始的偏移量 stm.tm_mon = mon - 1; // tm_mon范围是0-11(对应1-12月) stm.tm_mday = day; stm.tm_hour = hour; stm.tm_min = min; stm.tm_sec = sec; // 设置时区为意大利时区(CET/CEST) setenv("TZ", "CET-1CEST,M3.5.0/2,M10.5.0/3", 1); tzset(); utm = mktime(&stm); if (utm != -1) { printf("%lu %s\n", (unsigned long)utm, ctime(&utm)); } else { printf("时间转换失败\n"); } } else { printf("字符串解析失败\n"); } return 0; }
方法2:手动拼接带分隔符的字符串再用strptime()解析
如果一定要用strptime(),可以把无分隔符字符串转换成带分隔符的格式,比如"2022-11-16 08:23:10",再用标准格式解析:
#include <stdio.h> #include <time.h> #include <string.h> int main(int argc, char *argv[]) { struct tm stm; time_t utm; char strtime[] = "20221116082310"; char formatted[20]; // 拼接成带分隔符的字符串 snprintf(formatted, sizeof(formatted), "%.*s-%.*s-%.*s %.*s:%.*s:%.*s", 4, strtime, 2, strtime+4, 2, strtime+6, 2, strtime+8, 2, strtime+10, 2, strtime+12); memset(&stm, 0, sizeof(stm)); // 设置时区 setenv("TZ", "CET-1CEST,M3.5.0/2,M10.5.0/3", 1); tzset(); if (strptime(formatted, "%Y-%m-%d %H:%M:%S", &stm) != NULL) { utm = mktime(&stm); printf("%lu %s\n", (unsigned long)utm, ctime(&utm)); } else { printf("解析失败\n"); } return 0; }
关键注意点
- AIX系统的
strptime()对格式的兼容性较差,老旧版本(比如5.3)不支持连续无分隔符的格式说明符,必须用分隔符分隔各个时间字段。 struct tm的字段有特殊要求:tm_year是年份减1900,tm_mon是月份减1(0代表1月),手动填充时必须注意。- 要正确输出意大利时区的时间,需要通过
setenv("TZ", ...)设置时区并调用tzset()生效。
内容的提问来源于stack exchange,提问作者ulix
相关产品推荐
相关产品推荐

