Mac系统中strftime处理UTC时间返回本地时区的问题排查
问题原因
这是macOS与Linux的strftime实现行为差异导致的:
- Linux下的glibc版本
strftime,处理%z时会参考传入的struct tm结构体里的时区属性(比如gmtime_r设置的tm_gmtoff=0),所以能正确输出UTC对应的+0000。 - 但macOS的libc实现中,
strftime的%z格式符完全不读取传入的struct tm里的时区相关字段,只会直接使用当前进程的本地时区设置生成偏移值——哪怕你传的是gmtime_r生成的UTC时间结构体,它也不管,照样输出本地时区的偏移。
你看到tm_gmtoff确实是0,说明gmtime_r工作正常,问题就出在macOS的strftime不尊重传入结构体的时区信息。
解决办法
既然你要的是UTC的时区偏移,最直接的方式是跳过strftime,直接构造字符串:
// UTC时区偏移固定为+0000,直接赋值即可 snprintf(timestr, 7, "+0000");
如果一定要用strftime实现,可以临时修改进程的时区环境变量(仅对当前进程生效):
#include <stdio.h> #include <time.h> #include <stdlib.h> int main() { char timestr[10]; struct timespec ts; char tmz[6]; struct tm tm, *tmp = &tm; char* old_tz = getenv("TZ"); // 临时切换到UTC时区并生效 setenv("TZ", "UTC", 1); tzset(); clock_gettime(CLOCK_REALTIME, &ts); gmtime_r(&ts.tv_sec, tmp); strftime(tmz, 6, "%z", tmp); snprintf(timestr, 7, "%s", tmz); printf("Time: %s", timestr); // 恢复原时区 if (old_tz) { setenv("TZ", old_tz, 1); } else { unsetenv("TZ"); } tzset(); return 0; }
显然第一种方法更简洁,毕竟UTC的时区偏移是固定值,没必要依赖有平台差异的函数。
内容的提问来源于stack exchange,提问作者viral_mutant
相关产品推荐
相关产品推荐

