localtime() 与 localtime_r() 中时区变化的实时感知
Posted
技术标签:
【中文标题】localtime() 与 localtime_r() 中时区变化的实时感知【英文标题】:Real-time awareness of timezone change in localtime() vs localtime_r() 【发布时间】:2013-10-10 19:58:05 【问题描述】:在 Ubuntu 12.04.3 LTS 机器上工作时,我注意到 localtime() 和 localtime_r() 在进程生命周期内系统的时区更改时表现不同:localtime() 立即获取时区更改,而 localtime_r () 没有,它似乎坚持进程启动时的时区。这是预期的行为吗?我在任何地方都没有看到这个。
更准确地说,当我使用以下代码时...
#include <stdio.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
int main()
while (1)
time_t t = time(NULL);
struct tm *tm = localtime(&t);
printf("localtime:%02d/%02d/%02d-%02d:%02d:%02d\n",
tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900,
tm->tm_hour, tm->tm_min, tm->tm_sec);
sleep(1);
return 0;
... 并通过 ...从 UTC 更改时区
# echo 'Europe/Berlin' > /etc/timezone
# sudo dpkg-reconfigure --frontend noninteractive tzdata
...然后代码产生以下内容,...
localtime:10/04/2013-01:11:33
localtime:10/04/2013-01:11:34
localtime:10/04/2013-01:11:35
localtime:10/03/2013-23:11:36
localtime:10/03/2013-23:11:37
localtime:10/03/2013-23:11:38
...但如果我使用:
#include <stdio.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
int main()
while (1)
time_t t = time(NULL);
struct tm local_tm;
struct tm *tm = localtime_r(&t, &local_tm);
printf("localtime_r:%02d/%02d/%02d-%02d:%02d:%02d\n",
tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900,
tm->tm_hour, tm->tm_min, tm->tm_sec);
sleep(1);
return 0;
...那么在进行类似的时区更改时没有任何变化:
localtime_r:10/04/2013-01:15:37
localtime_r:10/04/2013-01:15:38
localtime_r:10/04/2013-01:15:39
localtime_r:10/04/2013-01:15:40
localtime_r:10/04/2013-01:15:41
localtime_r:10/04/2013-01:15:42
更新:在调用 localtime_r() 之前添加对 tzset() 的调用会产生预期的行为。从规范/手册页是否清楚(参见下面的讨论)是 mentalhealth.stackexchange.com 的一个问题......
【问题讨论】:
【参考方案1】:请参阅以下文档:
localtime() 函数将日历时间 timep 转换为 分解的时间表示,相对于用户的表示 指定的时区。该函数的行为就像它调用了 tzset(3) 和 使用有关当前的信息设置外部变量 tzname timezone, timezone 与 Coordinated Universal 的区别 时间 (UTC) 和当地标准时间(以秒为单位)和日光 如果夏令时规则在某些部分适用,则非零值 那一年。返回值指向一个静态分配的结构 这可能会被后续调用任何日期和 时间函数。 localtime_r() 函数做同样的事情,但存储 用户提供的结构中的数据。它不需要设置 tzname, timezone, 和日光。
发件人:http://linux.die.net/man/3/localtime_r
据我所知,代码似乎按我的预期工作。
已编辑以从同一文档中添加更多内容:
根据 POSIX.1-2004,localtime() 必须表现得像 tzset(3) 被调用,而 localtime_r() 没有这个 要求。对于可移植代码 tzset(3) 应该在之前调用 localtime_r()。
【讨论】:
谢谢皮特,我看到了。对我来说,“它没有设置 tzname、时区和日光”这句话传达了一些非常不同的东西——这些是外部价值。我的代码没有使用这些,我的问题是关于 localtime()/localtime_r() 的返回值,而你发布的 sn-p 说“做同样的事情”。 “函数的行为就像它在 localtime() 中调用了 tzset(3)”,而不是 localtime_r()。调用 localtime_r() 时永远不会设置时区。所以基本上,正如文档所示,localtime_r() 从不设置时区,因此您将始终获得 UTC 时间。尝试在 localtime_r 之前调用 tzset() ,它们的行为应该完全相同。 我明白你的意思——但是文本不应该说明这两个函数在多大程度上依赖 tzname/timezone/daylight 全局变量的值,而不是关于他们设置的程度吗?我觉得这真的很令人困惑,因为 我的 代码根本不关心这些全局变量的值。 另外,作为记录,规范是正确的——添加 tzset() 会产生一致的行为。 是的,Linux 手册页很隐晦。我发现在尝试阅读它们之前喝一杯浓啤酒会有所帮助。干杯!以上是关于localtime() 与 localtime_r() 中时区变化的实时感知的主要内容,如果未能解决你的问题,请参考以下文章
MinGW localtime_r 在一个时区工作,在另一个时区失败
vs2013写c++程序,其中localtime_s函数不接受一个参数怎么解决?!