使用 strftime() 获取 utc 时间戳

Pet*_*etr 5 c datetime glibc time-t strftime

我正在尝试使用以下strftime函数将当前 UTC 时间编码为字符串:

time_t now;
struct tm nowLocal;
struct tm nowUtc;

now = time(NULL);
localtime_r(&now, &nowLocal);
gmtime_r(&now, &nowUtc);
Run Code Online (Sandbox Code Playgroud)

到目前为止一切顺利: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"}
Run Code Online (Sandbox Code Playgroud)

然后我strftime()"%s"format 调用来获取自纪元以来的秒数:

char tsFromLocal[32];
char tsFromUtc[32];

strftime(tsFromLocal, sizeof(tsFromLocal), "%s", &nowLocal);
strftime(tsFromUtc, sizeof(tsFromUtc), "%s", &nowUtc);
Run Code Online (Sandbox Code Playgroud)

结果对我来说似乎很奇怪。strftime()我希望从两次调用中获得完全相同的字符串,%s格式描述如下:

自纪元以来的秒数,即自 以来1970-01-01 00:00:00 UTC。除非有闰秒支持,否则不会计算闰秒。

但我得到了两个不同的值:

tsFromLocal: "1337772448"

tsFromUtc:   "1337768848"
Run Code Online (Sandbox Code Playgroud)

而且差别不是7200 ( tm_gmtoff)而是3600。谁能解释这种行为?或者这是一个错误?

我这样做的原因是我需要通过网络传输时间值并将其与目标计算机上可能位于不同时区的当前时间进行比较。在目标机器上,我想:

struct tm restoredUtc;
time_t restored;

strptime(tsFromUtc, "%s", &restoredUtc);
restored = timegm(&restoredUtc);
Run Code Online (Sandbox Code Playgroud)

但我得到了:

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"}
Run Code Online (Sandbox Code Playgroud)

因此无论如何都要根据当前时区strptime()进行设置。tm_zone但即使我使用timelocal()而不是timegm()我也不会得到正确的值,因为它应该是11:27:28 CEST而不是12:27:28 CEST。这个错误与不同的结果有关吗strftime()

对后面的部分有什么评论吗?

Tom*_*ilt 4

您可能最好只使用 GMT,因为它gmtime_r总是会在任何地方给您相同的答案。如果一台机器想要以当地时间显示,可以稍后完成,但坚持一个时区进行存储和网络传输是一个好主意,而且 GMT 值很容易获取。