On Sat, Dec 23, 2023 at 11:56 AM Max Nikulin <maniku...@gmail.com> wrote: > > On 23/12/2023 02:41, Jeffrey Walton wrote: > > I've found lack of per-thread timezones and libc's inability to > > convert time between timezones a bigger problem than other issues, > > like explicitly setting a timezone for a process. > > From my point of view the TZ environment variable makes timezone > conversion a rather expensive operation. Some libc limitations are > highlighted in > https://data.iana.org/time-zones/theory.html#POSIX > > > The use case is, an appointment needs to be added to a database with > > UTC time, but the sender of the appointment uses localtime+timezone > > offset, like 1:00 PM PST or 1:00 PM EST. Trying to convert the > > localtime+timezone time to UTC (or other timezone) on a server in a > > thread is a real nightmare. Also see > > <https://sourceware.org/pipermail/libc-help/2021-January/005652.html>. > > From that message: > > * given: '15 Jan 2021 01:24:55 -0800 (PST) > > Time zone offset is given, so the timestamp can be unambiguously > converted to UTC or seconds since epoch. > > If the DB is Postgres then I would delegate timezone-related > computations to it. > > Posting code that can not be compiled may hide real issue. > > A couple of issues that may lead to undefined behavior: > > (info "(libc) Low-Level Time String Parsing") > https://www.gnu.org/software/libc/manual/html_node/Low_002dLevel-Time-String-Parsing.html#index-strptime > > • Before calling the ‘strptime’ function for a new input string, you > > should prepare the TM structure you pass. Normally this will mean > > initializing all values to zero. Alternatively, you can set all > > fields to values like ‘INT_MAX’, allowing you to determine which > > elements were set by the function call. Zero does not work here > > since it is a valid value for many of the fields. > > Before calling mktime set tm_isdst to negative value if you do not know > if DST is effective that moment. > > However being aware of tm_gmtoff GNU extension, I was not expected the > following: > > (info "(libc) Broken-down Time") > https://www.gnu.org/software/libc/manual/html_node/Broken_002ddown-Time.html#index-mktime > > The ‘mktime’ function ignores the specified contents of the > > ‘tm_wday’, ‘tm_yday’, ‘tm_gmtoff’, and ‘tm_zone’ members of the > > broken-down time structure. It uses the values of the other > > components to determine the calendar time; it’s permissible for > > these components to have unnormalized values outside their normal > > ranges. The last thing that ‘mktime’ does is adjust the components > > of the BROKENTIME structure, including the members that were > > initially ignored. > > So before calling mktime you need to set a timezone having offset of > -0800. I have not figured out if the following approach may give > incorrect results for some corner cases: > > - save tm_gmtoff from strptime results > - set UTC timezone > - call mktime > - adjust result by saved tm_gmtoff > > Besides performance penalty due to tzset() I would not call it "nightmare". > > Beware with real timezones having DST or other time transitions. GNU > libc implementation of mktime may give different results for the same > passed argument depending of argument used for previous call. > > I would consider using some other library instead of libc: > - std::chrono (I have heard of other C++ libraries created before chrono > was added to the standard) > - Qt > - timelib C library from PHP > > P.S. > https://stackoverflow.com/questions/11004273/what-is-stdpromise > > std::broken_promise is the best named identifier in the standard > > library. And there is no std::atomic_future. > > – Cubbi Jun 12, 2012 at 22:26 > struct tm is referred to as "Broken-down" time
Here's what someone on the libc mailing list suggested: <https://sourceware.org/pipermail/libc-help/2021-February/005657.html>. I'm not sure why threading broke in Mailman, so the thread could not be followed. I should have posted it with the original email I sent. The person offered some sample code, and stated there's no way to avoid the [thread-unsafe] putenv with TZ. Also note that it does not handle a source timezone string like '15 Jan 2021 01:24:55 -0800 (PST)'. You have to manually set TZ=America/California [?] first. It is not clear to me why the part of the timezone string "-0800 (PST)" is discarded when creating the time structure. The person also suggested using Gnulib. My project was not using Gnulib, so it was not an option. I think what C programmers need is a libtz that works as expected. And it needs to behave exactly like libc so there are no hard to track down bugs. Jeff