Bug 297243 - America/Vancounter PDT change in tzdata breaks gmtime(3)
Summary: America/Vancounter PDT change in tzdata breaks gmtime(3)
Status: Closed Works As Intended
Alias: None
Product: Base System
Classification: Unclassified
Component: bin (show other bugs)
Version: 15.1-RELEASE
Hardware: Any Any
: --- Affects Only Me
Assignee: freebsd-bugs (Nobody)
URL:
Keywords: regression
Depends on:
Blocks:
 
Reported: 2026-08-03 05:06 UTC by Mason Loring Bliss
Modified: 2026-08-05 20:05 UTC (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Mason Loring Bliss freebsd_triage 2026-08-03 05:06:49 UTC
There's an issue with upstream tzdata 2026b that breaks date calculations
with America/Vancouver. Observed in mailx, but there are probably other
programs that do it. I haven't dug up just what's happening yet, but I'm
working on that. In the meantime, what I see is that gmtime(3) returns the
wrong data now if you're in America/Vancouver. As nothing should have
changed for now (July) gmtime(3) should return the same data for today -
the change takes effect in November:
  
/etc/localtime  Sun Mar  8 09:59:59 2026 UT = Sun Mar  8 01:59:59 2026 PST
isdst=0 gmtoff=-28800
 /etc/localtime  Sun Mar  8 10:00:00 2026 UT = Sun Mar  8 03:00:00 2026 PDT
isdst=1 gmtoff=-25200
 /etc/localtime  Sun Nov  1 08:59:59 2026 UT = Sun Nov  1 01:59:59 2026 PDT
isdst=1 gmtoff=-25200
-/etc/localtime  Sun Nov  1 09:00:00 2026 UT = Sun Nov  1 01:00:00 2026 PST
isdst=0 gmtoff=-28800
+/etc/localtime  Sun Nov  1 09:00:00 2026 UT = Sun Nov  1 02:00:00 2026 MST
isdst=0 gmtoff=-25200

As it stands, mailx will issue the wrong time offset, which can be
problematic for things. An observed example involved monitoring emails
discarded because they were assumed to be over an hour old. The following
short program models what mailx does to calculate the date offset:

---------------------------------------------------------------------------
#include <stdio.h>                                                              
#include <time.h>                                                               

int main(int argc, char *argv[])
{
    time_t t;
    struct tm *tmptr;
    int tzdiff, tzdiff_hour, tzdiff_min;

    time(&t);
    tmptr = localtime(&t);

    tzdiff = t - mktime(gmtime(&t));

    tzdiff_hour = (int)(tzdiff / 60);
    tzdiff_min = tzdiff_hour % 60;
    tzdiff_hour /= 60;

    if (tmptr->tm_isdst > 0)
        tzdiff_hour++;

    printf("t (epoch seconds) is %ld\n", t);
    printf("mktime(gmtime(&t)) is %ld\n", mktime(gmtime(&t)));
    printf("t - mktime(gmtime(&t)) is %d\n", tzdiff);
    printf("tzdiff_hour (that / 3600) is %d\n", tzdiff_hour);
    printf("tm_isdst is %d\n", tmptr->tm_isdst);
    printf("%+05d\n", tzdiff_hour * 100 + tzdiff_min);
}                                                                               
---------------------------------------------------------------------------

To reproduce the issue, set your timezone to America/Vancouver, and run the
program. With tzdata_2026b, it will show an offset of -0600, which is
incorrect. It should be -0600, and it showed -0700 with tzdata_2026a. This
shows that gmtime(3) cares about the change in some detrimental way.

This is evidently an upstream issue, as it also affects RHEL, Debian, and
Fedora. I need to find the upstream and note it there.
Comment 1 Philip Paeps freebsd_committer freebsd_triage 2026-08-04 00:50:20 UTC
Cc:ing des@ on this PR since he maintains our tzcode.

Note that tzdata is on 2026c on main and all supported branches and releases since FreeBSD-EN-26:18.tzdata (2026-07-29).  tzcode is on 2026c on main and the supported stable/x branches.  (Though I don't believe 2026b -> 2026c touched America/Vancouver or gmtime(3)).

I see you found the upstream tz@iana.org mailing list.
Comment 2 Dag-Erling Smørgrav freebsd_committer freebsd_triage 2026-08-04 18:40:46 UTC
What exactly do you mean by mailx?  There is nothing even remotely like what you describe in our implementation.
Comment 3 Mason Loring Bliss freebsd_triage 2026-08-05 18:39:52 UTC
> What exactly do you mean by mailx?  There is nothing even remotely like what
> you describe in our implementation.

I mean Heirloom mailx, which is indeed distinct from bsd-mailx. I
encountered a bug through my work, and then created a reproducer based on
the code from Heirloom mailx. I noticed that gmtime(3) appeared to be
returning different data based on the zonefile version, despite the
zonefile not effectively changing until November 1st, which puzzled me.
  
So, having verified that the issue existed on every version of RHEL with
the new timezone, but with nothing else changed, I also checked Fedora and
FreeBSD, and noted both showing the same symptoms with the newer zone data.
  
Given that if Heirloom mailx does this, it's conceivable that other stuff
does too, at least as modelled on this. But the odd bit remains - why does
this code, even if problematic, show one result under 2026a and another
under 2026b when the change isn't supposed to happen until November? That
makes me wonder if there's underlying badness. I haven't had the time to
dig though enough of the code to understand it, but I hope to do so.

FWIW, the glibc list doesn't think it's a bug:

    https://sourceware.org/bugzilla/show_bug.cgi?id=34480

I need to read the responses there in depth and I've not had a chance yet.