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

时间:2013-10-03 23:20:12

标签: 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;
}

...并通过......

更改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 个答案:

答案 0 :(得分:7)

请参阅以下文档:

  

localtime()函数将日历时间timep转换为   分解时间表示,相对于用户表示   指定的时区。该函数就像调用tzset(3)和   使用有关当前的信息设置外部变量tzname   时区,时区与Coordinated Universal的区别   时间(UTC)和本地标准时间(以秒为单位)和日光到a   如果夏令时规则适用于某些部分,则非零值   那一年。返回值指向静态分配的结构   可能会被后续调用任何日期和   时间功能。 localtime_r()函数执行相同操作,但存储   用户提供的结构中的数据。它不需要设置tzname,timezone,   和日光。

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

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

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

  

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