for other precedent, bionic [Android] has tzalloc()/tzfree(), mktime_z(), localtime_rz(), and the timezone_t type since API level 35:
https://android.googlesource.com/platform/bionic/+/main/libc/include/time.h On Wed, Jan 3, 2024 at 3:22 PM Steffen Nurpmeso via austin-group-l at The Open Group <[email protected]> wrote: > > Hello. > > A happy and healthy new year 2024 i wish. > > As stated in [1] the localtime() and mktime() series of functions > have the inherent problem of not being thread-safe regarding > possible changes to the time zone: in a pure POSIX environment > changes to TZ always affect global data. > > If my memory serves correctly, about a decade ago the NetBSD > project contacted the IANA TZ maintainer in order to upstream > a new, truly thread-safe interface that addresses this issue. > Since some time in 2014 (see [1]) the IANA TZ database, which > includes the Public Domain aka open source code as is used by many > projects to implement the time related programming interface, > includes a new series of functions: > > timezone_t tzalloc(char const *TZ); > void tzfree(timezone_t tz); > > struct tm *localtime_rz(timezone_t restrict zone, > time_t const *restrict clock, > struct tm *restrict result); > struct tm *restrict tm); > time_t mktime_z(timezone_t restrict zone, > struct tm *restrict tm); > > [1] https://austingroupbugs.net/view.php?id=1788 > > If POSIX would offer this interface, the open source (public > domain) code and manual of which are available via the IANA TZ, > truly "thread-safe" time programming becomes possible in POSIX. > > This is especially important if no CLOCK_TAI is available. > For an example, here is what the widely used NTP server chrony > performs in order to achieve its task: > > tm = gmtime(&when); > if (!tm) > return tz_leap; > > stm = *tm; > > /* Temporarily switch to the timezone containing leap seconds */ > tz_env = getenv("TZ"); > if (tz_env) { > if (strlen(tz_env) >= sizeof (tz_orig)) > return tz_leap; > strcpy(tz_orig, tz_env); > } > setenv("TZ", leap_tzname, 1); > tzset(); > > /* Get the TAI-UTC offset, which started at the epoch at 10 seconds */ > t = mktime(&stm); > if (t != -1) > tz_tai_offset = t - when + 10; > > /* Set the time to 23:59:60 and see how it overflows in mktime() */ > stm.tm_sec = 60; > stm.tm_min = 59; > stm.tm_hour = 23; > > t = mktime(&stm); > > if (tz_env) > setenv("TZ", tz_orig, 1); > else > unsetenv("TZ"); > tzset(); > > if (t == -1) > return tz_leap; > > if (stm.tm_sec == 60) > tz_leap = LEAP_InsertSecond; > else if (stm.tm_sec == 1) > tz_leap = LEAP_DeleteSecond; > > *tai_offset = tz_tai_offset; > > I want to point out that setting an environment variable can be > a costly operation, but moreover changing the timezone as such > may involve several file system operations, being a potentially > very expensive operation. (By the way the draft 4 uses "file > system" as well as "filesystem".) > > With the new interface two timezone objects can be preallocated, > and the operations are totally detached from global data and > multithread-safe. > > My question: against which standard should an issue be opened? > > --steffen > | > |Der Kragenbaer, The moon bear, > |der holt sich munter he cheerfully and one by one > |einen nach dem anderen runter wa.ks himself off > |(By Robert Gernhardt) >
