将纪元时间转换为人类日期时间字符串,不进行夏令时转换

时间:2015-01-08 15:48:31

标签: c time epoch

我是C的新手,我目前正在开展一个项目,我需要将纪元时间转换为人类日期和时间字符串。

我有一个1411210794的UTC时间戳,用于20th September 2014 10:59:54

然后,我在UTC时间戳上运行以下函数,以转换为人类可读的时间戳:

void UTCoTimeDate(char** date, char** time, long UTC, BOOL includeSeconds)
{
     time_t epch = UTC;
     struct tm *timeptr =  gmtime(&epch);
     asprintf(date, "%d-%.2d-%.2d", 1900 + timeptr->tm_year, timeptr->tm_mon+1, timeptr->tm_mday);
     if (includeSeconds)
     {
        asprintf(time, "%.2d:%.2d:%.2d", timeptr->tm_hour, timeptr->tm_min, timeptr->tm_sec);
     }
     else
     {
        asprintf(time, "%.2d:%.2d", timeptr->tm_hour, timeptr->tm_min); 
     }
}

当我通过gdb运行并查看tm *timeptr内容时,小时变为11而不是停留在10.下面是tm结构的完整内容

{tm_sec = 54, tm_min = 59, tm_hour = 11, tm_mday = 20, tm_mon = 8, tm_year = 114, tm_wday = 6, tm_yday = 262, tm_isdst = 1, tm_gmtoff = 3600,
  tm_zone = 0x806c488 "BST"}

我期待人类的约会以10:59:54而不是11:59:54回来。

1 个答案:

答案 0 :(得分:1)

这是一个演示程序(ttt.c):

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

static void dump_tm(const char *tag, const struct tm *tm)
{
    printf("%s: {tm_sec = %.2d, tm_min = %.2d, tm_hour = %.2d, tm_mday = %.2d,"
           " tm_mon = %.2d, tm_year = %.3d, tm_wday = %d, tm_yday = %.3d,"
           " tm_isdst = %d, tm_gmtoff = %.5ld, tm_zone = \"%s\"}\n",
           tag, tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon,
           tm->tm_year, tm->tm_wday, tm->tm_yday, tm->tm_isdst, tm->tm_gmtoff,
           tm->tm_zone);
}

int main(void)
{
    time_t  t0 = 1411210794;
    struct tm *ut = gmtime(&t0);
    struct tm *lt = localtime(&t0);

    dump_tm("UTC", ut);
    dump_tm("Local", lt);
    return 0;
}

这是我Mac上的输出(Mac OS X 10.10.1,GCC 4.9.1 - 为SO添加的输出中的额外换行符):

$ ./ttt
UTC: {tm_sec = 54, tm_min = 59, tm_hour = 10, tm_mday = 20, tm_mon = 08, tm_year = 114,
tm_wday = 6, tm_yday = 262, tm_isdst = 0, tm_gmtoff = 00000, tm_zone = "UTC"}
Local: {tm_sec = 54, tm_min = 59, tm_hour = 03, tm_mday = 20, tm_mon = 08, tm_year = 114,
tm_wday = 6, tm_yday = 262, tm_isdst = 1, tm_gmtoff = -25200, tm_zone = "PDT"}
$ TZ="Europe/London" ./ttt
UTC: {tm_sec = 54, tm_min = 59, tm_hour = 10, tm_mday = 20, tm_mon = 08, tm_year = 114,
tm_wday = 6, tm_yday = 262, tm_isdst = 0, tm_gmtoff = 00000, tm_zone = "UTC"}
Local: {tm_sec = 54, tm_min = 59, tm_hour = 11, tm_mday = 20, tm_mon = 08, tm_year = 114,
tm_wday = 6, tm_yday = 262, tm_isdst = 1, tm_gmtoff = 03600, tm_zone = "BST"}
$

该机器的时区默认设置实际上是America / Los_Angeles(尽管TZ环境变量在第一次调用时正式未设置)。如您所见,UTC值是一致的,但本地时间值具有本地时区缩写。

如果没有相反的信息,我必须得出结论,尽管你不这么认为,但你实际上是在调用localtime()而不是gmtime()。您可以尝试通过在函数调用之前添加gmtime()来确保调用#undef gmtime函数。如果gmtime()函数仍然生成错误的时间信息,则计算机上的gmtime()会被破坏。然而,这似乎非常不可能。