如何在C中的Windows上获得GMT中的time_t

时间:2012-08-02 20:31:31

标签: c time gmt time-t

我正在编写一些可在多个互通系统上运行的代码。我使用time()来获取time_t,但这导致了系统之间时区差异的问题,所以我想在GMT中得到time_t。我一直在查看time.h函数,但我不清楚如何确定我能得到正确的时间。这是我到目前为止所提出的:

time_t t = time();
struct tm *gtm = gmtime(&t);
time_t gt = mktime(gtm);

现在,这似乎在我的机器上得到了正确的答案,但我想知道它是否会在推出之前普遍起作用,即使其他机器的时钟设置为当地时间或GMT或在不同的时间区域或其他什么。我担心的原因是因为mktime。在描述中,它表示它将tm结构解释为“以本地时间表示的日历时间”。听起来我觉得它不会返回GMT时间,虽然它似乎在我的机器上。此外,当我打印出gt时,它比t早4个小时,这似乎是正确的。但如果我运行以下内容:

time_t t = time();
struct tm *gtm = gmtime(&t);
struct tm *ltm = localtime(&t);
printf("%d, %d\n", gtm->tm_hour, ltm->tm_hour);

小时数是相同的,是当地时间,这不是我的预期。

为了记录,在另一个答案中,我看到了timegm()的引用,听起来很完美,但它在我的系统中不存在。

简而言之,我如何在C中的任何Windows机器上获得GMT中的time_t?

编辑:删除了已添加的msvcrt标记,因为我没有使用msvcrt。

4 个答案:

答案 0 :(得分:7)

根据定义,

time_t始终为UTC。所以time()做你想要的。只有在time_t和故障时间表示之间进行转换时,时区才会发挥作用。

如果您有时间以UTC表示故障时间表示,则需要暂时​​将时区切换为UTC,使用mktime()转换为time_t,然后将时区切换回来,如下所示:

time_t convert_utc_tm_to_time_t (struct tm *tm)
{
    char *tz;
    time_t result;

    /* temporarily set timezone to UTC for conversion */
    tz = getenv("TZ");
    if (tz) {
      tz = strdup (tz);
      if (!tz) {
        // out of memory
        return -1;
      }
    }
    setenv("TZ", "", 1);
    tzset();

    result = mktime (tm);

    /* restore timezone */
    if (tz) {
      setenv("TZ", tz, 1);
      free (tz);
    }
    else {
      unsetenv("TZ");
    }
    tzset();

    return result;
}

答案 1 :(得分:2)

使用gmtime(),因为您希望在GMT中获得时间。 localtime将在当地时区报告时间,并且只有当地时区也是GMT时才会报GMT。

Windows有自己的代码和数据结构来处理时区和时区。要使用特定于Windows的c代码获取GMT,您可以使用GetSystemTime()。您可以通过以下网址找到有关它的更多信息:http://msdn.microsoft.com/en-us/library/windows/desktop/ms724390(v=vs.85).aspx

请注意,Windows使用自己的日期/时间结构,但GetSystemTime()及其相关页面也详细说明了这一点。简而言之,GetSystemTime()检索当前系统日期和时间,以协调世界时(UTC)(也称为GMT)表示。它使用Windows结构SYSTEMTIME,这是一个具有许多时间元素的结构。

答案 2 :(得分:1)

查看代码的第一部分:

time_t t = time();
struct tm *gtm = gmtime(&t);
time_t gt = mktime(gtm);

您将gt设置为虚假值。致电mktime时,您需要传入当地时间的struct tm*time_t定义为自1970年1月1日00:00 UTC以来的秒数。除非您目前位于+0000时区,否则从mktime调用的返回值将代表过去或将来几个小时的时间。

至于第二部分:

time_t t = time();
struct tm *gtm = gmtime(&t);
struct tm *ltm = localtime(&t);
printf("%d, %d\n", gtm->tm_hour, ltm->tm_hour);

我认为gmtimelocaltime在内存中返回相同的缓冲区,这可能就是为什么你在输出中得到相同的两个小时。第二个调用是覆盖第一个的输出。试试这个:

struct tm gtm, ltm;
struct tm *tm_buf;
time_t t = time();
tm_buf = gmtime(&t);
memcpy(&gtm, tm_buf, sizeof(struct tm));
tm_buf = localtime(&t);
memcpy(&ltm, tm_buf, sizeof(struct tm));
printf("%d, %d\n", gtm.tm_hour, ltm.tm_hour);

答案 3 :(得分:0)

请注意,对于这种简单的转换,您可以使用自己的功能。这里有mkgmtime()

的副本

https://github.com/m2osw/snapcpp/blob/master/snapwebsites/libsnapwebsites/src/snapwebsites/mkgmtime.c

这允许您将struct tm转换为time_t值,忽略任何时区信息。不包括注释,这可能少于100行代码,因此很容易将其添加到您的项目中。