Working on an Ubuntu 12.04.3 LTS box, I just noticed that localtime() and localtime_r() behave differently when the system's timezone changes during the lifetime of a process: localtime() picks up the timezone change immediately, whereas localtime_r() does not, it seems to stick to what was the timezone at the launch of the process. Is this expected behavior? I haven't seen this covered anywhere.
More precisely, when I use the following code ...
#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
",
tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900,
tm->tm_hour, tm->tm_min, tm->tm_sec);
sleep(1);
}
return 0;
}
... and change the timezone from UTC via ...
# echo 'Europe/Berlin' > /etc/timezone
# sudo dpkg-reconfigure --frontend noninteractive tzdata
... then the code produces the following, ...
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
... but if I use:
#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
",
tm->tm_mon + 1, tm->tm_mday, tm->tm_year + 1900,
tm->tm_hour, tm->tm_min, tm->tm_sec);
sleep(1);
}
return 0;
}
... then there's no change when doing a similar timezone change:
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
UPDATE: adding a call to tzset() before invoking localtime_r() produces the expected behavior. Whether that's clear from the spec/manpage or not (see discussion below) is a question for mentalhealth.stackexchange.com...
See Question&Answers more detail:
os