【问题标题】:getting utc timestamp using strftime()使用 strftime() 获取 UTC 时间戳
【发布时间】: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


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    我怀疑评论是正确的:strftime() 将时间解释为当地时间。请注意,tm_gmtoff 不是标准化字段;我想知道strftime() 是否在看它。但我找不到任何具体的东西来证实这一点。

    但是,回答您问题的第二部分,为什么不直接通过网络传输time(NULL) 的结果呢?或者,如果您已经有时间以struct tm 的形式使用mktime() 转换为time_t,然后再转移? printf("%lu", (unsigned long) time) 比尝试使用 strftime("%s") 简单得多,strftime("%s") 没有被 C99 或 POSIX 标准化。

    【讨论】:

      【解决方案3】:

      Q1:谁能解释这种行为?还是bug?

      是的,这是 tsFromLocal:"1337772448" != tsFromUtc: "1337768848" 中的一个错误。但错误在 tsFromUtc 中。它们应该是相同的,它们都应该是 1337772448。

      1337772448%(24*60*60) --> 41248 是一天中的 UTC 秒数或 11:27:28,它与您的 nowUtc 结构匹配并且是您认为的时间(以 UTC 为单位)

      Q2:……这个错误是否与strftime()的不同结果有关?

      我同意使用time_t 作为整数进行网络通信的一般想法。

      是的,看起来是这样。

      如果您想在这篇文章中更进一步:考虑在time(&now) 之后立即发布now 的数值,并明确说明您当时预计的时间。

      【讨论】:

        猜你喜欢
        • 2015-01-08
        • 2014-03-31
        • 2011-12-24
        • 2012-02-28
        • 2017-12-06
        • 2014-11-21
        • 2017-10-07
        • 2012-04-03
        • 2019-05-02
        相关资源
        最近更新 更多