Alright, this is ridiculous. Running the same program with non-sensual TZ=A-91 
prints:

```
A-9, 3600, , -3600.
```

Running it with TZ=PST8Whatever prints:

```
PST, Wha, 28800, -3600
```

Running it with TZ=Whatever8Whatever prints:

```
Wha, tev, 0, -3600
```

So, CRT really does not care what timezone names you supply. It simply copies 
three characters to _tzname[] array.

Also, it seems that when it uses value of TZ variable, it also always sets 
_dstbias to -3600 (one hour).
________________________________
From: Pali Rohár <[email protected]>
Sent: Thursday, November 20, 2025 1:02 AM
To: Kirill Makurin <[email protected]>
Cc: [email protected] 
<[email protected]>
Subject: Re: [Mingw-w64-public] [PATCH 7/7] crt: Extend t_time test for 
_localtime64 and _mktime64

I did not think about it. I just set UTC and I was happy that it is working as 
I wanted.

Anyway, do you know of the correct way how to set timezone to UTC?
It would be good to adjust test to not use this "unexpected" behavior.

On Wednesday 19 November 2025 16:00:02 Kirill Makurin wrote:
> Running simple program:
>
> ```
> #include <stdio.h>
> #include <time.h>
>
> int main (void) {
>         _tzset ();
>         printf ("%s, %s, %d\n", _tzname[0], _tzname[1], _timezone);
>         return 0;
> }
> ```
>
> With TZ=UTC prints
>
> ```
> UTC, , 0
> ```
>
> And with TZ=PST
>
> ```
> PST, , 0
> ```
>
> So it seems your guess is correct.
> ________________________________
> From: Pali Rohár <[email protected]>
> Sent: Thursday, November 20, 2025 12:53 AM
> To: Kirill Makurin <[email protected]>
> Cc: [email protected] 
> <[email protected]>
> Subject: Re: [Mingw-w64-public] [PATCH 7/7] crt: Extend t_time test for 
> _localtime64 and _mktime64
>
> Seems that TZ=UTC is working, at least test is passing for me.
>
> Maybe it parsed "UTC" as a number (like atoi) and it returned that
> offset 0, which is UTC?
>
> On Wednesday 19 November 2025 15:42:56 Kirill Makurin wrote:
> > Does CRT really support well-known timezones, like TZ=UTC? I have a feeling 
> > that it accepts value of TZ variable as long as it can parse it according 
> > to format documented for _tzset[1].
> >
> > Format for TZ supported by CRT is subset of what POSIX[2] describes. In 
> > particular, CRT does not support specifying exact time when the switch 
> > happens, but only offset from UTC. Microsoft docs say that CRT always uses 
> > US rules for this, which is very unfortunate.
> >
> > Another thing that I think worth mentioning - it seems that CRT functions 
> > _ftime and localtime will always try to reparse value of TZ and update 
> > timezone information (variables _daylight, _dstbias, _timezone and 
> > _tzname). If two functions (any of _tzset, _ftime or localtime) are called 
> > from different threads at the same time, and value of TZ was different upon 
> > entry, this may result in inconsistent result. I don't think there's much 
> > we can do about.
> >
> > [1] https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/tzset
> > [2] https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap08.html
> > ________________________________
> > From: Martin Storsjö <[email protected]>
> > Sent: Monday, November 17, 2025 11:18 PM
> > To: Pali Rohár <[email protected]>
> > Cc: [email protected] 
> > <[email protected]>
> > Subject: Re: [Mingw-w64-public] [PATCH 7/7] crt: Extend t_time test for 
> > _localtime64 and _mktime64
> >
> > On Sat, 25 Oct 2025, Pali Rohár wrote:
> >
> > > ---
> > > mingw-w64-crt/testcases/t_time.c | 96 ++++++++++++++++++++++++++++++--
> > > 1 file changed, 92 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/mingw-w64-crt/testcases/t_time.c 
> > > b/mingw-w64-crt/testcases/t_time.c
> > > index 50b07d0083a7..75a15d816d31 100644
> > > --- a/mingw-w64-crt/testcases/t_time.c
> > > +++ b/mingw-w64-crt/testcases/t_time.c
> > > @@ -10,14 +10,17 @@ int __cdecl ftime64(struct __timeb64 *tb64);
> > >
> > > int main()
> > > {
> > > -  time_t t;
> > > -  __time32_t t32;
> > > -  __time64_t t64;
> > > +  time_t t, t_;
> > > +  __time32_t t32, t32_;
> > > +  __time64_t t64, t64_;
> > >   struct timeb tb;
> > >   struct _timeb tb_;
> > >   struct __timeb32 tb32;
> > >   struct __timeb64 tb64;
> > >   struct tm *htm;
> > > +  struct tm tm1;
> > > +  struct tm tm2;
> > > +  struct tm tm3;
> > >   int ret1, ret2, ret3;
> > >   const char *str;
> > >   const wchar_t *wstr;
> > > @@ -95,7 +98,49 @@ int main()
> > >   assert (htm->tm_yday == 74);
> > >   assert (htm->tm_isdst == 0);
> > >
> > > -  /* ctime returns time string in local timezone, so set local timezone 
> > > to UTC to have test timezone independent */
> > > +  time_t times[] = {
> > > +    1700000000 /* Tue Nov 14 22:13:20 UTC 2023 */,
> > > +    1600000000 /* Sun Sep 13 12:26:40 UTC 2020 */,
> > > +  };
> > > +  for (size_t i = 0; i < sizeof(times)/sizeof(*times); i++) {
> > > +    t = times[i];
> > > +    htm = localtime (&t);
> > > +    tm1 = *htm;
> > > +    printf ("localtime(%lld):    sec=%d min=%d hour=%d mday=%d mon=%d 
> > > year=%d wday=%d yday=%d isdst=%d\n",
> > > +        (long long)t, htm->tm_sec, htm->tm_min, htm->tm_hour, 
> > > htm->tm_mday, htm->tm_mon, htm->tm_year, htm->tm_wday, htm->tm_yday, 
> > > htm->tm_isdst);
> > > +    t_ = mktime (htm);
> > > +    printf ("mktime(): %lld      sec=%d min=%d hour=%d mday=%d mon=%d 
> > > year=%d wday=%d yday=%d isdst=%d\n",
> > > +        (long long)t_, htm->tm_sec, htm->tm_min, htm->tm_hour, 
> > > htm->tm_mday, htm->tm_mon, htm->tm_year, htm->tm_wday, htm->tm_yday, 
> > > htm->tm_isdst);
> > > +    assert (t_ == t);
> > > +    assert (memcmp (htm, &tm1, sizeof(tm1)) == 0);
> > > +
> > > +    t32 = t;
> > > +    htm = _localtime32 (&t32);
> > > +    tm2 = *htm;
> > > +    printf ("_localtime32(%d): sec=%d min=%d hour=%d mday=%d mon=%d 
> > > year=%d wday=%d yday=%d isdst=%d\n",
> > > +        t32, htm->tm_sec, htm->tm_min, htm->tm_hour, htm->tm_mday, 
> > > htm->tm_mon, htm->tm_year, htm->tm_wday, htm->tm_yday, htm->tm_isdst);
> > > +    t32_ = _mktime32 (htm);
> > > +    printf ("_mktime32(): %d   sec=%d min=%d hour=%d mday=%d mon=%d 
> > > year=%d wday=%d yday=%d isdst=%d\n",
> > > +        t32_, htm->tm_sec, htm->tm_min, htm->tm_hour, htm->tm_mday, 
> > > htm->tm_mon, htm->tm_year, htm->tm_wday, htm->tm_yday, htm->tm_isdst);
> > > +    assert (t32_ == t32);
> > > +    assert (memcmp (htm, &tm2, sizeof(tm2)) == 0);
> > > +
> > > +    t64 = t;
> > > +    htm = _localtime64 (&t64);
> > > +    tm3 = *htm;
> > > +    printf ("_localtime64(%lld): sec=%d min=%d hour=%d mday=%d mon=%d 
> > > year=%d wday=%d yday=%d isdst=%d\n",
> > > +        t64, htm->tm_sec, htm->tm_min, htm->tm_hour, htm->tm_mday, 
> > > htm->tm_mon, htm->tm_year, htm->tm_wday, htm->tm_yday, htm->tm_isdst);
> > > +    t64_ = _mktime64 (htm);
> > > +    printf ("_mktime64(): %lld   sec=%d min=%d hour=%d mday=%d mon=%d 
> > > year=%d wday=%d yday=%d isdst=%d\n",
> > > +        t64_, htm->tm_sec, htm->tm_min, htm->tm_hour, htm->tm_mday, 
> > > htm->tm_mon, htm->tm_year, htm->tm_wday, htm->tm_yday, htm->tm_isdst);
> > > +    assert (t64_ == t64);
> > > +    assert (memcmp (htm, &tm3, sizeof(tm3)) == 0);
> > > +
> > > +    assert (memcmp (&tm1, &tm2, sizeof(tm1)) == 0);
> > > +    assert (memcmp (&tm2, &tm3, sizeof(tm2)) == 0);
> > > +  }
> > > +
> > > +  /* ctime, localtime and mktime returns time string in local timezone, 
> > > so set local timezone to UTC to have test timezone independent */
> > >   putenv ("TZ=UTC");
> >
> > In addition to setting TZ=UTC here, is it possible to set some other
> > well-known timezone that would be available everywhere, which we could use
> > for some testcases for cases closer to the DST switchover time? We could
> > do that for both mktime and localtime IMO.
> >
> > In itself, these test additions probably are fine though - the above would
> > be nice extras. But given that corner case handling close to DST
> > switchovers, I think it would be good to actually check such a case.
> >
> > So this patchset in itself looks ok, except for the one issue I found in
> > 2/7.
> >
> > // Martin
> >
> > _______________________________________________
> > Mingw-w64-public mailing list
> > [email protected]
> > https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

_______________________________________________
Mingw-w64-public mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mingw-w64-public

Reply via email to