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

Reply via email to