You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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),大概率是以下原因之一:

  1. 日期解析错误:比如tryParseString把输入的01/01/1970搞反了日/月,实际解析成了7月1日(伦敦7月处于夏令时)
  2. 时区设置异常:系统TZ环境变量没正确指向Europe/London,或者tzdata数据库存在问题
  3. 错误复用当前夏令时状态:虽然当前冬令时的tm_isdst=0和1970年1月的状态一致,但如果mktime检测到时区规则冲突,仍会自动修正该值

解决方法

  1. 不要手动设置tm_gmtoff和tm_zone:这两个字段对mktime无效,完全由mktime自行计算
  2. 让mktime自动判断夏令时:把tm_isdst设为-1,而非从当前时间复制状态
  3. 验证日期解析结果:检查tmStartDateTime的各个字段是否正确(比如tm_year是年份减1900,1970年对应70;tm_mon是0-11,1月对应0)
  4. 确保时区生效:可以在程序中手动设置时区并刷新,示例代码:
    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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 22:30:53