C++中mktime()函数无法正确识别时区问题问询
关于mktime修改tm时区与gmtoff值的问题解答
为什么mktime会修改你的tm字段?
核心原因是mktime完全不依赖你传入的tm_gmtoff和tm_zone字段——这两个字段是localtime()/gmtime()这类函数的输出字段,并非mktime的输入参数。
mktime的设计逻辑是:根据你传入的tm_year/tm_mon/tm_mday等日期时间字段,结合当前系统时区(或TZ环境变量指定的时区),自动计算该时间点对应的夏令时状态、时区偏移和时区名称,随后覆盖你之前设置的tm_isdst、tm_gmtoff、tm_zone值。
另外你传入的tm_isdst只是一个提示:
- 设为-1:mktime自动判断该时间点是否处于夏令时(推荐用法)
- 设为0或1:mktime会尝试按该值计算,但如果该时间点在时区规则中不可能出现该状态(比如冬天强制设为夏令时),mktime会自动修正它。
你的例子问题分析
你输入1970年1月1日00:00:00(伦敦当时处于GMT,偏移0),但mktime返回BST(偏移3600),大概率是以下原因之一:
- 日期解析错误:比如
tryParseString把输入的01/01/1970搞反了日/月,实际解析成了7月1日(伦敦7月处于夏令时) - 时区设置异常:系统TZ环境变量没正确指向Europe/London,或者tzdata数据库存在问题
- 错误复用当前夏令时状态:虽然当前冬令时的
tm_isdst=0和1970年1月的状态一致,但如果mktime检测到时区规则冲突,仍会自动修正该值
解决方法
- 不要手动设置
tm_gmtoff和tm_zone:这两个字段对mktime无效,完全由mktime自行计算 - 让mktime自动判断夏令时:把
tm_isdst设为-1,而非从当前时间复制状态 - 验证日期解析结果:检查
tmStartDateTime的各个字段是否正确(比如tm_year是年份减1900,1970年对应70;tm_mon是0-11,1月对应0) - 确保时区生效:可以在程序中手动设置时区并刷新,示例代码:
setenv("TZ", "Europe/London", 1); tzset(); // 刷新时区设置
修正后的代码示例
tm tmStartDateTime = {}; string dateString = inputDate; if (myclass::tryParseString(inputDate, "%Y/%m/%d %H:%M:%S", tmStartDateTime)) { // 让mktime自动判断该时间点的夏令时状态 tmStartDateTime.tm_isdst = -1; tm bmStartDate = tmStartDateTime; StartDateTimeEpoch = mktime(&bmStartDate); // 此时bmStartDate的tm_isdst、tm_gmtoff、tm_zone是该时间点对应的正确值 }
内容的提问来源于stack exchange,提问作者Hussey
相关产品推荐
相关产品推荐

