C++20用std::time_zone::get_info()获取当前UTC偏移(分钟),需传入具体时间点;C++11兼容方案用localtime/gmtime+mktime计算差值,注意清零tm_isdst;各平台还有/etc/localtime解析、date+%z或Windows GetTimeZoneInformation等方法。

用 std::chrono 和 std::time_zone 获取本地时区偏移(C++20)
如果你用的是 C++20 且标准库支持时区(如 libc++ 或较新 MSVC),std::time_zone 是最直接的方式。它能准确返回当前时刻的 UTC 偏移,自动处理夏令时切换。
关键点是:偏移值以 std::minutes 为单位,需调用 get_info() 并读取 offset 成员:
auto now = std::chrono::system_clock::now(); auto tz = std::chrono::current_zone(); auto info = tz->get_info(now); int offset_minutes = info.offset.count(); // 正数表示东八区为 +480
- 必须传入具体时间点(不能只用时区对象本身),否则无法判断是否处于 DST
- 某些 libstdc++ 版本(GCC 13 之前)未实现
time_zone,会编译失败或链接报错 -
info.offset是std::chrono::seconds,.count()返回秒数,除以 60 才得分钟数 —— 别漏这步
用 std::localtime + std::gmtime 算差值(C++11 兼容)
这是最广泛兼容的方法,不依赖 C++20,但要注意它隐含一个假设:系统时钟是正确的,且 tm_isdst 被正确设置。
核心思路是:把当前时间转成本地 tm 和 UTC tm,再用 mktime 反解出秒差:
立即学习“C++免费学习笔记(深入)”;
auto now = std::time(nullptr); std::tm lt = *std::localtime(&now); std::tm gt = *std::gmtime(&now); lt.tm_isdst = gt.tm_isdst = 0; // 清除夏令时标志,避免 mktime 自动调整 auto local_secs = std::mktime(<); auto utc_secs = std::mktime(>); int offset_minutes = static_cast<int>((local_secs - utc_secs) / 60);
-
std::localtime和std::gmtime返回静态缓冲区指针,必须解引用赋值给局部tm对象 - 务必设
tm_isdst = 0,否则mktime可能根据本地规则强行修正时间,导致差值错误 - 该方法在跨年、跨月边界处可能因
mktime归一化行为引入 ±1 分钟误差(罕见但存在)
读取 /etc/localtime 符号链接(Linux/macOS)
Linux 和 macOS 下,/etc/localtime 通常是到 /usr/share/zoneinfo/ 下某个文件的软链,路径本身就能反映时区(如 /usr/share/zoneinfo/Asia/Shanghai)。但这不直接给出偏移分钟数,需查表或解析 TZif 文件。
更实用的做法是调用系统命令(不推荐生产环境,但调试快):
FILE* fp = popen("date +%z", "r"); // 输出类似 '+0800'
char buf[16];
if (fgets(buf, sizeof(buf), fp)) {
int h = std::stoi(std::string(buf).substr(0, 3));
int m = std::stoi(std::string(buf).substr(3, 2));
int offset_minutes = h * 60 + m;
}
pclose(fp);
-
%z格式输出是 ISO 8601 偏移(无冒号),%:z才带冒号,注意 shell 环境差异 - 该方式受
TZ环境变量影响,可能和系统默认时区不一致 - Windows 不支持
date +%z,此法不具备跨平台性
Windows 上用 GetTimeZoneInformation
Windows API 提供了明确的偏移字段:TIME_ZONE_INFORMATION.Bias 表示 UTC 偏移分钟数(西为正,东为负),但注意它的符号和常规习惯相反。
TIME_ZONE_INFORMATION tz;
DWORD result = GetTimeZoneInformation(&tz);
if (result != TIME_ZONE_ID_INVALID) {
int offset_minutes = -tz.Bias; // Bias 是西五区为 300,所以要取负
}
-
Bias值恒为标准时间偏移(不含夏令时),若需当前实际偏移,得结合result返回值判断是否启用 DST,并加减 60 分钟 - 该函数不依赖 C 运行时,线程安全,适合嵌入式或精简环境
- 返回值为
TIME_ZONE_ID_DAYLIGHT时,实际偏移 =-tz.Bias + 60
真正麻烦的不是获取偏移本身,而是“偏移是否随时间变化”——夏令时切换、系统时区被修改、甚至虚拟机时钟漂移,都会让一个静态读取的分钟数几小时后就失效。如果业务逻辑依赖精确时区信息(比如定时任务调度),别缓存结果,每次需要时都重新计算。


















