The following issue has been SUBMITTED.
======================================================================
https://austingroupbugs.net/view.php?id=1533
======================================================================
Reported By: steffen
Assigned To:
======================================================================
Project: 1003.1(2016/18)/Issue7+TC2
Issue ID: 1533
Category: Base Definitions and Headers
Type: Enhancement Request
Severity: Editorial
Priority: normal
Status: New
Name: steffen
Organization:
User Reference:
Section: time.h
Page Number: 425
Line Number: 14451
Interp Status: ---
Final Accepted Text:
======================================================================
Date Submitted: 2021-11-08 22:04 UTC
Last Modified: 2021-11-08 22:04 UTC
======================================================================
Summary: struct tm: add tm_gmtoff (and tm_zone) field(s)
Description:
Hello.
Regarding the MUA i maintain i was pinged by a user who needs to
use the timezone Europe/Dublin. He wrote
In 2018, the tzdata maintainers (IANA) corrected a historical
mistake
with the Europe/Dublin timezone. The mistake was rooted in a
misunderstanding of whether IST meant "Irish Summer Time" or "Irish
Standard Time".
The problem was discussed at great length
(http://mm.icann.org/pipermail/tz/2018-January/thread.html) and it
was
concluded that IST really meant Irish *Standard* Time (in constrast
with, say, British *Summer* Time), and that this standard time is
defined as UTC+0100.
[.]
Once the question was settled, the only possible solution for
keeping
the Irish local time in sync with the rest of the world (for
example,
Belfast & London) was for IANA to _reverse_ the functioning of the
DST
flag for Ireland. The result is that in the current IANA timezone
database (2021e), Europe/Dublin has DST applied in *winter*, with an
adjustment of -1h (that is, negative).
[.]
It turns out that the introduction of a negative DST adjustment
caused
all sorts of bugs back in 2018; in the source distribution of IANA's
tzdata, one can spot this inside ./europe:
# In January 2018 we discovered that the negative SAVE values in
the
# Eire rules cause problems with tests for ICU [...] and with
tests
# for OpenJDK [...]
# To work around this problem, the build procedure can translate
the
# following data into two forms, one with negative SAVE values and
the
# other form with a traditional approximation for Irish timestamps
# after 1971-10-31 02:00 UTC; although this approximation has
tm_isdst
# flags that are reversed, its UTC offsets are correct and this
often
# suffices. This source file currently uses only nonnegative SAVE
# values, but this is intended to change and downstream code
should
# not rely on it.
So, a temporary hack was put in place in order to allow distro
maintainers to retain the old broken convention of IST and support
buggy software, but it is clear that the current (and technically,
and
politically, correct) implementation of a negative DST adjustment
for
Ireland is there to stay.
As a matter of fact, the distro maintainer can choose to compile
tzdata to keep buggy software happy ("make DATAFORM=rearguard"),
which replicates the behaviour of tzdata prior to 2018. Many distros
seem to be doing that for one reason or another, while some have
passed
the upstream change down to their users (probably, without knowing).
Anyhow, all the simple minded software, including the MUA
i maintain, used to do something like
if((t2 = mktime(gmtime(&t))) == (time_t)-1){
t = 0;
goto jredo;
}
tzdiff = t - t2;
if((tmp = localtime(&t)) == NULL){
t = 0;
goto jredo;
}
tzdiff_hour = (int)(tzdiff / 60);
tzdiff_min = tzdiff_hour % 60;
tzdiff_hour /= 60;
if (tmp->tm_isdst > 0)
tzdiff_hour++;
Note the .tm_isdst plus positive summer time adjustment.
This was overly primitive, and i recognize that POSIX supports the
%z (and %Z) formats for strftime(3), and in general code as below
is used by projects, so doing it right is very expensive but
doable with POSIX as of today.
However, all BSDs and Linux with either of GNU and musl C library
support the .tm_gmtoff (and .tm_zone) members of "struct tm", in
general all users of the public domain (and standardized) IANA TZ
project can bake it in upon their own desire.. With .tm_gmtoff
being available, code gets as simple as
s64
time_tzdiff(s64 secsepoch, struct tm const *utcp_or_nil,
struct tm const *localp_or_nil){
struct tm tmbuf[2], *tmx;
time_t t;
s64 rv;
UNUSED(utcp_or_nil);
rv = 0;
if(localp_or_nil == NIL){
t = S(time_t,secsepoch);
while((tmx = localtime(&t)) == NIL){
if(t == 0)
goto jleave;
t = 0;
}
tmbuf[0] = *tmx;
localp_or_nil = &tmbuf[0];
}
#ifdef HAVE_TM_GMTOFF
rv = localp_or_nil->tm_gmtoff;
#else
if(utcp_or_nil == NIL){
t = S(time_t,secsepoch);
while((tmx = gmtime(&t)) == NIL){
if(t == 0)
goto jleave;
t = 0;
}
tmbuf[1] = *tmx;
utcp_or_nil = &tmbuf[1];
}
rv = ((((localp_or_nil->tm_hour - utcp_or_nil->tm_hour) * 60) +
(localp_or_nil->tm_min - utcp_or_nil->tm_min)) * 60) +
(localp_or_nil->tm_sec - utcp_or_nil->tm_sec);
if((t = (localp_or_nil->tm_yday - utcp_or_nil->tm_yday)) != 0){
s64 const ds = 24 * 60 * 60;
rv += (t == 1) ? ds : -S(s64,ds);
}
#endif
jleave:
return rv;
}
Desired Action:
Insert at the given location
<code>
int tm_gmtoff Seconds east of UTC
const char *tm_zone Timezone abbreviation
</code>
Maybe cross-reference with strftime(3) and note relationship to the %z and
%Z formats.
======================================================================
Issue History
Date Modified Username Field Change
======================================================================
2021-11-08 22:04 steffen New Issue
2021-11-08 22:04 steffen Name => steffen
2021-11-08 22:04 steffen Section => time.h
2021-11-08 22:04 steffen Page Number => 425
2021-11-08 22:04 steffen Line Number => 14451
======================================================================