获取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, <); 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基于其所做的事情。