获取C中的时区GMT偏移量

我正在使用标准的mktime函数将struct tm转换为纪元时间值。 tm字段在本地填充,我需要将纪元时间作为GMT。 tm有一个gmtoff字段,允许您为此目的设置本地GMT偏移量(以秒为单位)。

但我无法弄清楚如何获取这些信息。 当然必须有某个标准函数返回偏移量? localtime如何做到这一点?

只需执行以下操作:

 #define _GNU_SOURCE /* for tm_gmtoff and tm_zone */ #include  #include  /* Checking errors returned by system calls was omitted for the sake of readability. */ int main(void) { time_t t = time(NULL); struct tm lt = {0}; localtime_r(&t, &lt); printf("Offset to GMT is %lds.\n", lt.tm_gmtoff); printf("The time zone is '%s'.\n", lt.tm_zone); return 0; } 

注意: time()返回的纪元之后的秒数就像在格林威治一样。

我想在问之前我应该​​多做一些搜索。 事实certificate,有一个鲜为人知的timegm函数与gmtime相反。 它支持GNU和BSD,这对我的目的来说已经足够了。 更便携的解决方案是暂时将TZ环境变量的值设置为“UTC”,然后使用mktime ,然后再设置TZ

但是timegm适合我。

本地时间如何做到这一点?

根据localtime手册页

localtime()函数就像调用tzset(3)一样,并将外部变量tzname设置为当前时区的信息, 时区与协调世界时(UTC)和本地标准时间之间的差值(以秒为单位)

所以你可以调用localtime() ,你会有timezone差异或调用tzset()

 extern long timezone; .... tzset(); printf("%ld\n", timezone); 

注意:如果您选择使用localtime_r()请注意,不需要设置这些变量,您需要首先调用tzset()来设置timezone

根据POSIX.1-2004,localtime()需要表现得就像调用tzset()一样, 而localtime_r()则没有这个要求。 对于可移植代码,应在localtime_r()之前调用tzset()

获取本地时间偏移function的通用版本在这里。
我从statckoverflow中的答案中借用了一些代码。

 int time_offset() { time_t gmt, rawtime = time(NULL); struct tm *ptm; #if !defined(WIN32) struct tm gbuf; ptm = gmtime_r(&rawtime, &gbuf); #else ptm = gmtime(&rawtime); #endif // Request that mktime() looksup dst in timezone database ptm->tm_isdst = -1; gmt = mktime(ptm); return (int)difftime(rawtime, gmt); } 

我相信至少在Linux中有以下情况:时区信息来自/ usr / share / zoneinfo /。 localtime读取/ etc / localtime,它应该是zoneinfo中相应文件的副本。 您可以通过在时区文件上执行zdump -v来查看内部情况(zdump可能位于sbin中,但您不需要提升权限来读取时区文件)。 这是一个剪辑:

 / usr / share / zoneinfo / EST5EDT Sun Nov 6 05:59:59 2033 UTC = Sun Nov 6 01:59:59 2033 EDT isdst = 1 gmtoff = -14400
 / usr / share / zoneinfo / EST5EDT Sun Nov 6 06:00:00 2033 UTC = Sun Nov 6 01:00:00 2033 EST isdst = 0 gmtoff = -18000
 / usr / share / zoneinfo / EST5EDT Sun Mar 12 06:59:59 2034 UTC = Sun Mar 12 01:59:59 2034 EST isdst = 0 gmtoff = -18000
 / usr / share / zoneinfo / EST5EDT Sun Mar 12 07:00:00 2034 UTC = Sun Mar 12 03:00:00 2034 EDT isdst = 1 gmtoff = -14400
 / usr / share / zoneinfo / EST5EDT Sun Nov 5 05:59:59 2034 UTC = Sun Nov 5 01:59:59 2034 EDT 

我猜你可以自己解析这个问题。 我不确定是否有一个stdlib函数只返回gmtoff(可能会有,但我不知道……)

edit: man tzfile描述了zoneinfo文件的格式。 您应该能够简单地映射到适当类型的结构。 它似乎是zdump基于其所做的事情。