【发布时间】:2012-05-29 23:08:09
【问题描述】:
我正在尝试使用 strftimefunction 将当前 utc 时间编码为字符串:
time_t now;
struct tm nowLocal;
struct tm nowUtc;
now = time(NULL);
localtime_r(&now, &nowLocal);
gmtime_r(&now, &nowUtc);
到目前为止一切顺利:nowLocal 包含我的时区 (CET) 中的当前时间,nowUtc 包含 UTC 时间,差异完全取决于 tm_gmtoff 值:
nowLocal: {tm_sec = 28, tm_min = 27, tm_hour = 13, tm_mday = 23, tm_mon = 4, tm_year = 112, tm_wday = 3, tm_yday = 143, tm_isdst = 1, tm_gmtoff = 7200, tm_zone = 0x8127a38 "CEST"}
nowUtc: {tm_sec = 28, tm_min = 27, tm_hour = 11, tm_mday = 23, tm_mon = 4, tm_year = 112, tm_wday = 3, tm_yday = 143, tm_isdst = 0, tm_gmtoff = 0, tm_zone = 0x3e9907 "GMT"}
然后我以"%s" 格式调用strftime() 以获取自纪元以来的秒数:
char tsFromLocal[32];
char tsFromUtc[32];
strftime(tsFromLocal, sizeof(tsFromLocal), "%s", &nowLocal);
strftime(tsFromUtc, sizeof(tsFromUtc), "%s", &nowUtc);
结果对我来说似乎很奇怪。我希望从两个strftime() 调用中得到完全相同的字符串,因为%s 格式描述为:
自纪元以来的秒数,即自 1970-01-01 00:00:00 UTC 以来。除非闰秒支持可用,否则闰秒不计算在内。
但我得到了两个不同的值:
tsFromLocal:"1337772448"
tsFromUtc: "1337768848"
而且区别不是 7200 (tm_gmtoff) 而是 3600。谁能解释这种行为?还是bug?
我这样做的原因是我需要通过网络传输时间值并将其与可以在不同时区的目标机器上的当前时间进行比较。在目标机器上我想:
struct tm restoredUtc;
time_t restored;
strptime(tsFromUtc, "%s", &restoredUtc);
restored = timegm(&restoredUtc);
但我得到了:
restoredUtc:{tm_sec = 28, tm_min = 27, tm_hour = 12, tm_mday = 23, tm_mon = 4, tm_year = 112, tm_wday = 3, tm_yday = 143, tm_isdst = 1, tm_gmtoff = 7200, tm_zone = 0x8127a38 "CEST"}
所以strptime() 无论如何都会根据当前时区设置tm_zone。但即使我使用 timelocal() 而不是 timegm() 我也不会得到正确的值,因为它应该是 11:27:28 CEST 而不是 12:27:28 CEST。这个错误是否与strftime()的不同结果有关?
后面的部分有什么相关的吗?
【问题讨论】:
-
据我所知,
strftime()将传递的时间结构解释为 LOCAL TIME。因为原始nowLocal结构具有tm_isdst = 1(由先前对localtime_r() 的调用设置),您将得到1 小时的差异。如果在调用 strftime 之前将此字段设置为 0,您可能会得到预期的 2 小时的差异。 -
鉴于您在
time()的结果中拥有以秒为单位的时间,您可以将其与strftime()返回的内容进行比较,以找出哪个答案是正确的(如果有的话)。我的猜测是当地时间是正确的,而 UTC 是错误的。是否可以让strftime()工作,而不是将 TZ 变量设置为UTC0,然后调用tzset()有待讨论。
标签: c datetime glibc strftime time-t