在没有夏令时转换的情况下将纪元时间转换为人类日期时间字符串
Convert epoch time to human date time string without daylight saving conversion
我是 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。
这是一个演示程序(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()
。您可以尝试通过在函数调用前添加 #undef gmtime
来确保您调用了 gmtime()
函数。如果 gmtime()
函数仍然产生错误的时间信息,那么您机器上的 gmtime()
就坏了。然而,这似乎极不可能。
我是 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。
这是一个演示程序(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()
。您可以尝试通过在函数调用前添加 #undef gmtime
来确保您调用了 gmtime()
函数。如果 gmtime()
函数仍然产生错误的时间信息,那么您机器上的 gmtime()
就坏了。然而,这似乎极不可能。