The tzset seems to be in effect only at the time of initialization, which is useless when tzset is called multiple times.
Today a little in-depth search for the implementation of the Tzset in glibc, found that this is not the case, its real implementation is every time will be to parse. Why is it that the tzset is not valid before, due to the environment variables and global environment variables of the local process.
The implementation of the specific tzset is tzset_internal, in this function, the basic idea is:
1, first check the environment variables in the TZ environment variables exist, valid
2. Get the path and file name of the specified time zone file according to the TZ environment variable
3, save the current use of the environment variable TZ
4, try to read the data file, here the data file Instant zone file Tzfile, note that the data is in a fixed format.
5, in the above step4, according to the Tzfile file, to refresh timezone and daylight. After determining the success of parsing the Tzfile file, a variable named __use_tzfile is also set to 1
6, according to the above analytic results, according to whether __use_tzfile to determine whether to continue, if not resolved tzfile success, then determine whether TZ is valid, invalid refresh Tzname value, think the default use UTC time.
7, if the above operation process, found Tzfile parsing failure, and TZ is valid, you need to finally parse the TZ environment variable, in this case the TZ environment variable is a time, its time is used to set the summer winter, that is, daylight saving times.
The above parsing process, can be seen in fact, and the man manual is consistent with the description.
The three formats for the TZ environment variable have been clearly explained in the manual
(1) When there is no summer winter in the local time zone, you can use the following format: STD offset
The name of the time zone that STD represents is three letters. The offset string indicates how much time to add (or subtract) to return to UTC, the hour is 0~24, and the minute is 0~59
(2) The second format is used as summer winter, and its format type is: STD offset DST [Offset].start[/time].end[/time]
Note that there are no spaces in the above format. The initial STD and offset indicate the standard time zone. DST and offset indicate the time zone name and offset of the corresponding summer winter season. If offset is ignored, he defaults to the first one hours of the standard time.
The Start field indicates when the summer season starts to work, and the end field shows when the modification is restored to the standard time.
These fields may have the following two formats:
Jn is marked by Julian days with N representing 1~365. February 29 days are not counted, even in leap years
n indicates that Julian days use N to denote 0~365. In leap years February 29 is counted in days.
MM.W.D indicates the D (0~6) Day of the Week (1~12) of the month of the M (s). 0 days means it's Sunday.
The Time field indicates when the local time begins to take effect and changes to another date. If omitted, the default is 02:00:00
For example, the standard New Zealand time is NZST, which is 12 hours before UTC, and the summer winter time is 13 hours before the NZDT,UTC time, the effective interval is from the first Sunday in October to three Sundays in March, and this modification takes place at the default 02:00:00
(3) The third format, which is used to give the file information of the read time zone file:: [filespec]
If the above file description information filespec is ignored, the file that reads the time zone information will be the localtime file in the system time zone directory, and this directory is now generally/usr/share/zoneinfo
. Its file format is tzfile format. Filespec does not start with/, and the file description information is relative to the system time zone directory, for example, still with New Zealand example:
tz= ":P Acific/auckland"
We now understand the settings of the TZ environment variable and the implementation principle of the Tzset file. So why did you use export to change the TZ environment variable before calling Tzset to refresh the time zone information?
(The test example that actually runs the tzset in GLIBC is valid!!!!! )
The reason is:
Export exports the environment variables, which are session-conversational environment variables.
The environment variable that putenv exports, however, is an environment variable that takes the process as its object.
According to the above example test, write the shell script (export call exports) and program (PUTENV) comparison, found that the results are not interfering with each other, even if the two environment variable names are the same!!!
The conclusion is:
1, if you want to set the time zone, according to the implementation of GLIBC, it is best to use time zone file changes, or to establish a link to the LocalTime time zone file method, or after the power loss before the modification will be lost!
2, Tzset call refresh to get timezone is actually valid, and in order to prevent other programs to change the time zone, if the running process is time zone sensitive, it is important to make uninterrupted refresh.
3, notice the environment variable TZ disturbance to the time zone information, the environment variable can specify the time zone, or it can be a specified time zone file.
Linux time zone setting and modification in C language (iii)