实时了解localtime()与localtime_r()的时区变化

Chr*_*ian 8 c linux ubuntu time localtime

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

...并通过UTC更改UTC的时区

# echo 'Europe/Berlin' > /etc/timezone 
# sudo dpkg-reconfigure --frontend noninteractive tzdata
Run Code Online (Sandbox Code Playgroud)

...然后代码生成以下内容,...

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

......但如果我使用:

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

...然后在进行类似的时区更改时没有变化:

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

更新:在调用localtime_r()之前添加对tzset()的调用会产生预期的行为.对于mentalhealth.stackexchange.com来说,是否从规范/联机帮助中清楚(见下面的讨论)是一个问题...

It'*_*ete 7

请参阅以下文档:

localtime()函数将日历时间timep转换为细分时间表示,相对于用户指定的时区表示.该函数就像调用tzset(3)一样,并将外部变量tzname设置为当前时区的信息,时区以协调世界时(UTC)和本地标准时间(以秒为单位)之间的差异,并将日光设置为非零值(如果是日光)储蓄时间规则适用于一年中的某些时段.返回值指向静态分配的结构,该结构可能被后续调用任何日期和时间函数覆盖.localtime_r()函数执行相同操作,但将数据存储在用户提供的结构中.它不需要设置tzname,timezone和daylight.

来自:http://linux.die.net/man/3/localtime_r

据我所知,似乎代码正如我所期望的那样工作.

编辑从同一文档中添加更多内容:

根据POSIX.1-2004,localtime()需要表现得就像调用tzset(3)一样,而localtime_r()则没有这个要求.对于可移植代码,应在localtime_r()之前调用tzset(3).

  • 我明白你的观点——但是文本不应该说明这两个函数*依赖* tzname/timezone/daylight 全局变量的值的程度,而不是它们*设置*它的程度吗?我发现这真的很令人困惑,因为*我的*代码不以任何方式关心这些全局变量的值。 (2认同)