[44/59] Handle TZif time type 0 correctly
Checks
Context |
Check |
Description |
redhat-pt-bot/TryBot-apply_patch |
success
|
Patch applied to master at the time it was sent
|
Commit Message
* time/tzfile.c (__tzfile_compute): For time stamps before the
first transition, or for all transitions if no TZ string is
specified, use time type 0 as specified by Internet RFC 9636
section 3.2. Omit an unnecessary loop to set tzname, daylight,
and timezone as that behavior is undocumented, POSIX does not
require it, and it does not make sense in general. Instead, just
set tzname[isdst] as that is all that makes sense (particularly in
light of the time type 0 fix) and that might conceivably help
old-fashioned apps.
---
time/tzfile.c | 88 ++++++++++-----------------------------------------
1 file changed, 17 insertions(+), 71 deletions(-)
@@ -600,40 +600,16 @@ __tzfile_compute (__time64_t timer, int use_localtime,
if (use_localtime)
{
- __tzname[0] = NULL;
- __tzname[1] = NULL;
+ unsigned char ti;
- if (__glibc_unlikely (timecnt == 0 || timer < transitions[0]))
+ if (__glibc_unlikely (timecnt == 0 ? tzspec == NULL
+ : timer < transitions[0]))
{
- /* TIMER is before any transition (or there are no transitions).
- Choose the first non-DST type
- (or the first if they're all DST types). */
- i = 0;
- while (i < typecnt && types[i].dst)
- {
- if (__tzname[1] == NULL)
- __tzname[1] = __tzstring (&zone_names[types[i].idx]);
-
- ++i;
- }
-
- if (i == typecnt)
- i = 0;
- __tzname[0] = __tzstring (&zone_names[types[i].idx]);
- if (__tzname[1] == NULL)
- {
- tzidx j = i;
- while (j < typecnt)
- if (types[j].dst)
- {
- __tzname[1] = __tzstring (&zone_names[types[j].idx]);
- break;
- }
- else
- ++j;
- }
+ /* TIMER is before the first transition; or there are no
+ transitions and no TZ string. Use the first type. */
+ ti = 0;
}
- else if (timer >= transitions[timecnt - 1])
+ else if (timecnt == 0 || timer >= transitions[timecnt - 1])
{
if (__glibc_unlikely (tzspec == NULL))
{
@@ -710,49 +686,19 @@ __tzfile_compute (__time64_t timer, int use_localtime,
i = hi;
found:
- /* assert (timer >= transitions[i - 1]
- && (i == timecnt || timer < transitions[i])); */
- __tzname[types[type_idxs[i - 1]].dst]
- = __tzstring (&zone_names[types[type_idxs[i - 1]].idx]);
-
- for (tzidx j = i; j < timecnt; j++)
- {
- struct ttinfo *ttype = &types[type_idxs[j]];
- unsigned char dst = ttype->dst;
-
- if (__tzname[dst] == NULL)
- {
- __tzname[dst] = __tzstring (&zone_names[ttype->idx]);
-
- if (__tzname[1 - dst] != NULL)
- break;
- }
- }
-
- if (__glibc_unlikely (__tzname[0] == NULL))
- __tzname[0] = __tzname[1];
-
- i = type_idxs[i - 1];
+ ti = type_idxs[i - 1];
}
- struct ttinfo *info = &types[i];
- __daylight = daylight_saved;
- __timezone = -rule_stdoff;
-
- if (__tzname[0] == NULL)
- {
- /* This should only happen if there are no transition rules.
- In this case there should be only one single type. */
- assert (typecnt == 1);
- __tzname[0] = __tzstring (zone_names);
- }
- if (__tzname[1] == NULL)
- /* There is no daylight saving time. */
- __tzname[1] = __tzname[0];
- tp->tm_isdst = info->dst;
- assert (strcmp (&zone_names[info->idx], __tzname[tp->tm_isdst]) == 0);
- tp->tm_zone = __tzname[tp->tm_isdst];
+ struct ttinfo *info = &types[ti];
+ unsigned char dst = info->dst;
+ char *tm_zone = __tzstring (&zone_names[info->idx]);
+ tp->tm_isdst = dst;
tp->tm_gmtoff = info->utoff;
+ tp->tm_zone = tm_zone;
+
+ /* Set tzname[isdst] too; although not required by POSIX or documented,
+ this is closer to what proleptic TZ does. */
+ __tzname[dst] = tm_zone;
}
leap: