mktime()与timegm()返回(time_t)-1的所有C语言原因探究
C语言里mktime()/timegm()返回(time_t)-1的所有原因
在C语言标准和实际平台实现中,这两个函数返回(time_t)-1(表示转换失败)的原因主要有这些:
- 目标时间超出time_t的存储范围:
time_t本质是存储时间戳的整数类型(通常是32位或64位),如果转换后的UTC秒数超出了该类型的最大值或最小值,就会返回错误。比如32位time_t最多支持到2038年1月19日,超过这个时间点的转换就会失败;同理,早于time_t最小值对应的时间(比如1970年之前很久的时间)也会失败。 - 输入的struct tm包含无效时间组合:虽然
mktime会尝试自动调整不合理的字段(比如把13月转为次年1月),但如果字段错误到无法修正,就会失败。比如2月30日、小时设为25、分钟61这种,或者日期和月份完全不匹配(比如4月31日),部分实现会直接判定为无效,返回错误。 - 时区相关的异常:
mktime依赖本地时区设置,如果系统时区配置无效、时区数据库损坏,或者遇到夏时制切换的歧义时间(比如夏令时结束时时钟回拨,同一个本地时间会出现两次),部分实现会返回错误。timegm是把struct tm当作UTC时间转换,但如果系统的UTC时间处理逻辑异常,也可能导致转换失败。
- tm_isdst字段无法正确判定:当
tm_isdst设为2时,表示让系统自动判断该时间是否处于夏时制,但如果系统无法确定(比如时区数据缺失),或者该时间点不存在(比如夏令时开始时时钟跳过的那段时间),就会返回错误。 - 平台特定的额外限制:有些平台会对
struct tm的年份范围做额外限制,比如不支持1970年之前的年份,或者某些极端遥远的未来年份,哪怕time_t能容纳,也会返回转换失败。 - 系统时间服务不可用:如果系统底层的时间计算服务(比如tzdata库)无法访问或损坏,依赖这些服务的
mktime和timegm会无法完成转换,返回错误。
附测试代码(用来调试这两个函数的转换情况):
void time_test(const char *s, time_t (*f)(struct tm *tm), const struct tm *ts) { struct tm ts1 = *ts; errno = 0; time_t t = f(&ts1); printf("%s %11lld/%02lld/%02d %2d:%02d:%02d " "-->%11lld/%02lld/%02d %2d:%02d:%02d errno:%3d time_t:%.19g %s\n", // f == mktime ? "mktime" : "timegm", // ts->tm_year + 1900LL, ts->tm_mon + 1LL, ts->tm_mday, // ts->tm_hour, ts->tm_min, ts->tm_sec, // ts1.tm_year + 1900LL, ts1.tm_mon + 1LL, ts1.tm_mday, // ts1.tm_hour, ts1.tm_min, ts1.tm_sec, // errno, (double) t, s); }
内容的提问来源于stack exchange,提问作者chux
相关产品推荐
相关产品推荐

