mktime 返回 -1 表示转换失败,根本原因是 struct tm 字段越界而非格式错误;需确保 tm_mon(0–11)、tm_mday(1–31)、tm_year(距1900偏移)等合法,初始化整个结构体,tm_isdst 设为 -1 交由系统判断,并仅通过 mktime 和 localtime_r/gmtime_r 进行时间转换。

mktime 返回 -1 是字段越界,不是格式错误
mktime 返回 -1 表示转换失败,根本原因几乎总是 struct tm 字段值超出合法范围,而非“字符串没解析对”这类外部问题。常见越界点包括:
-
tm_mon必须是0–11,填12或负数会失败 -
tm_mday必须是1–31,填0或32会失败 -
tm_year是距 1900 的偏移量,2024 年应填124,填2024直接溢出 -
tm_sec允许60(闰秒),但填61就越界
某些 libc(如 newlib)对越界更敏感,不自动修正字段,直接返回 -1;glibc 可能尝试归一化,但行为不可靠,不能依赖。
必须初始化整个 tm 结构体,别信栈上残留值
局部定义的 struct tm t 若未显式初始化,其 padding 区域和未赋值字段含随机值。哪怕只错一个 tm_wday 或 tm_yday,mktime 都可能拒绝转换或返回错误结果。
- 用
memset(&t, 0, sizeof(t))最稳妥 - 或 C++11 起可用
struct tm t{};值初始化 - 避免仅初始化部分字段,例如
t.tm_year = 124; t.tm_mon = 4;留下其余字段未定义
tm_isdst 设为 -1,让系统自动判断夏令时
tm_isdst 控制夏令时处理逻辑:
立即学习“C++免费学习笔记(深入)”;
- 设为
-1:交由mktime根据日期和本地时区规则自动推断,这是最安全的选择 - 设为
0或1:强制指定,可能导致某些边界日期(如春秋季切换日)无法解析,返回-1 - 嵌入式环境或自定义时区数据缺失时,
-1仍是最兼容的取值
注意:mktime 修改传入的 struct tm* 指针所指内容,调用后 tm_isdst 可能被重写为 0 或 1,但这不影响返回值正确性。
别 memcpy、别 reinterpret_cast,只走标准函数路径
time_t 和 struct tm 内存布局完全无关:
-
time_t通常是 4 或 8 字节整数(平台相关),无固定 ABI -
struct tm至少 9 个字段,大小通常 44–56 字节,含 padding 和字段对齐差异 - 直接
memcpy不仅得不到时间值,还可能读到 padding 中的垃圾值,触发未定义行为 - 任何基于类型假设的强转(如
reinterpret_cast<time_t&>(t))都违反标准,不可移植
唯一合规路径只有 mktime(tm → time_t)和 localtime_r/gmtime_r(time_t → tm)。跨平台代码里,连 sizeof(time_t) 都不该硬编码。


















