Real-time understanding of timezone changes in localtime () vs localtime_r ()

While working on the Ubuntu 12.04.3 LTS box, I just noticed that localtime () and localtime_r () behave differently when the system time zone changes throughout the entire life cycle of the process: localtime () immediately changes the time zone change, whereas localtime_r () does not seem to adhere to what was the time zone when starting the process. Is this expected behavior? I have not seen this 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\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; } 

... and change the time zone from UTC through ...

 # echo 'Europe/Berlin' > /etc/timezone # sudo dpkg-reconfigure --frontend noninteractive tzdata 

... then the code creates 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\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; } 

... then there are no changes when making a similar change in time zone:

 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 calling localtime_r () causes the expected behavior. Whether this is clear from the spec / manpage or not (see the discussion below) is a question for mentalhealth.stackexchange.com ...

+6
source share
1 answer

See the following documentation:

The localtime () function converts the calendar timep time to the displayed stakeout time, expressed relative to the user specified time zone. The function acts as if it were called tzset (3) and sets the external variables tzname with information about the current time zone, the time zone with the difference between coordinated universal time (UTC) and local standard time in seconds, and daylight is a non-zero value, if daylight saving time rules apply for some part of the year. The return value indicates a statically allocated structure that can be overwritten by subsequent calls of any date and time. The localtime_r () function does the same, but stores the data in a user-provided structure. No need to set tzname, time zone, and daylight.

From: http://linux.die.net/man/3/localtime_r

So, as far as I can tell, it seems that the code works as I expected.

Edited to add more from the same documentation:

According to POSIX.1-2004, localtime () is required to behave as if tzset (3), and localtime_r () does not have this requirement. For portable code, tzset (3) should be called before localtime_r ().

+7
source

Source: https://habr.com/ru/post/955219/


All Articles