C语言 获取 C 中的时区 GMT 偏移量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13804095/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 04:43:04  来源:igfitidea点击:

Get the time zone GMT offset in C

cdatetimetimezonelibc

提问by friedo

I'm using the standard mktimefunction to turn a struct tminto an epoch time value. The tmfields are populated locally, and I need to get the epoch time as GMT. tmhas a gmtofffield to allow you to set the local GMT offset in seconds for just this purpose.

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

But I can't figure out how to getthat information. Surely there must be a standard function somewhere that will return the offset? How does localtimedo it?

但我不知道如何获得这些信息。当然一定有一个标准函数可以返回偏移量吗?怎么localtime做?

采纳答案by friedo

I guess I should have done a bit more searching before asking. It turns out there's a little known timegmfunction which does the opposite of gmtime. It's supported on GNU and BSD which is good enough for my purposes. A more portable solution is to temporarily set the value of the TZenvironment variable to "UTC" and then use mktime, then set TZback.

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

But timegmworks for me.

timegm对我有用。

回答by alk

Just do the following:

只需执行以下操作:

#define _GNU_SOURCE /* for tm_gmtoff and tm_zone */

#include <stdio.h>
#include <time.h>

/* 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;
}

Note: The seconds since epoch returned by time()are measured as if in Greenwich.

注意:自纪元返回以来的秒数time()与格林威治一样。

回答by iabdalkader

How does localtime do it?

本地时间是如何做到的?

According to localtimeman page

根据localtime手册页

The localtime() function acts as if it called tzset(3) and sets the external variables tzname with information about the current timezone, timezonewith the difference between Coordinated Universal Time (UTC) and local standard time in seconds

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

So you could either call localtime()and you will have the difference in timezoneor call tzset():

所以你可以打电话localtime(),你会在timezone或打电话有区别tzset()

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

Note: if you choose to go with localtime_r()note that it is not required to set those variables you will need to call tzset()first to set timezone:

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

According to POSIX.1-2004, localtime() is required to behave as though tzset() was called, while localtime_r() does not have this requirement. For portable code tzset() should be called before localtime_r()

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

回答by Hill

The universal version of obtaining local time offset function is here.
I borrowed pieces of code from the answerin statckoverflow.

获取本地时间偏移函数的通用版本在这里。
我从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);
}

回答by frankc

I believe the following is true in linux at least: timezone info comes from /usr/share/zoneinfo/. localtime reads /etc/localtime which should be a copy of the appropriate file from zoneinfo. You can see whats inside by doing zdump -von the timezone file (zdump may be in sbin but you don't need elevated permissions to read timezone files with it). Here is a snipped of one:

我相信以下至少在 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 

I guess you could parse this yourself if you want. I'm not sure if there is a stdlib function that just returns the gmtoff (there may well be but I don't know...)

如果你愿意,我想你可以自己解析这个。我不确定是否有一个只返回 gmtoff 的 stdlib 函数(可能有,但我不知道......)

edit:man tzfile describes the format of the zoneinfo file. You should be able to simply mmap into a structure of the appropriate type. It appears to be what zdump is doing based on an strace of it.

编辑:man tzfile 描述了 zoneinfo 文件的格式。您应该能够简单地将 mmap 映射到适当类型的结构中。这似乎是 zdump 基于它的一条线索正在做的事情。

回答by Duke Nukem

Here's a two-liner inspired by @Hill's and @friedo's answers:

这是受@Hill 和@friedo 的回答启发的两行:

#include <time.h>
...
time_t rawtime = time(0);
timeofs = timegm(localtime(&rawtime)) - rawtime;

Returns offset from UTC in seconds.

以秒为单位返回与 UTC 的偏移量。

Doesn't need _GNU_SOURCEdefined, but note that timegmis not a POSIX standard and may not be available outside of GNU and BSD.

不需要_GNU_SOURCE定义,但请注意,这timegm不是 POSIX 标准,可能无法在 GNU 和 BSD 之外使用。