bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: tzset: add native Windows workaround


From: Bruno Haible
Subject: Re: tzset: add native Windows workaround
Date: Tue, 02 May 2017 22:19:16 +0200
User-agent: KMail/5.1.3 (Linux/4.4.0-75-generic; KDE/5.18.0; x86_64; ; )

Hi Paul,

> On 05/01/2017 09:40 AM, Bruno Haible wrote:
> > +  /* If the environment variable TZ has been set by Cygwin, neutralize it.
> > +     The Microsoft CRT interprets TZ differently than Cygwin and produces
> > +     incorrect results if TZ has the syntax used by Cygwin.  */
> > +  const char *tz = getenv ("TZ");
> > +  if (tz != NULL && strchr (tz, '/') != NULL)
> > +    _putenv ("TZ=");
> 
> I'm puzzled why setting TZ="" is desirable here. Does this cause the 
> Microsoft CRT to use UTC?

No. An empty or absent TZ environment variable, for the Microsoft CRT, means
the time zone that the user has set in the Windows Control Panel.

Only for Cygwin, an empty or absent TZ environment variable means GMT.
I find this a poor choice, because
  - When the user changes the time zone through the Windows Control Panel
    (or even automatically, when he's travelling), he has to either terminate
    the Cygwin terminal window or change the TZ variable in there.
  - Cygwin programs run in Windows; it's not adequate to have a default
    the choices made in the Control Panel. (Gnulib's 'localename' module,
    for instance, makes sure to use the settings from the Control Panel on
    Windows or Mac OS.)

> Is TZ="" a good thing because switching to UTC 
> is better than the undefined behavior one would get with TZ set to a 
> value not documented by Microsoft?

No, setting TZ="" is a good thing because some developers use Cygwin
as a development environment for native Windows programs, and it is expected
that such a program produces identical results when run from a Cygwin terminal
window than from a cmd.exe window.

> Also, the test "strchr (tz, '/') != NULL" allows many Cygwin-compatible 
> TZ settings that Microsoft does not document support for, e.g., 
> TZ="PST8PDT,M3.2.0,M11.1.0" for Los Angeles. Admittedly most Cygwin 
> users in L.A. probably just use TZ="America/Los_Angeles" so fixing this 
> is not that important. Still, if the intent is to limit the TZ value to 
> what Microsoft documents, I suppose you could nuke the TZ value if it 
> does not match the C-locale ERE 
> "^[A-Za-z]{3}[-+]?[01]?[0-9](:[0-5][0-9](:[0-5][0-9])?)?([A-Za-z]{3})?$", 
> or maybe put in a FIXME comment to that effect.

The full set of TZ values understood by MSVC CRT is not documented. (Maybe
there are more valid strings than those that fit your regexp?)

The full set of TZ values understood by Cygwin is not documented either. But
what matters most to me are those that Cygwin sets without the user being
aware of. (*)

So the borderline between both sets is guesswork. I guessed that
"contains a slash" vs. "does not contain a slash" is a reasonable distinction.
Plus, it's easy to implement in less than 1 line of code.

(*) This happens by /etc/profile.d/tzset.sh, which uses the 'tzset' program
to determine the value. The 'tzset' program is implemented in Cygwin's
  winsup/utils/tzset.c
  winsup/utils/tzmap.h
and all the resulting values contain a slash, except for
  CST6CDT
  EST5EDT
  MST7MDT
  PST8PDT
which follow the syntax understood by Microsoft's CRT [1].

[1] https://msdn.microsoft.com/en-us/library/90s5c885.aspx


How about this revised comment?

diff --git a/lib/tzset.c b/lib/tzset.c
index ce854b9..90f633a 100644
--- a/lib/tzset.c
+++ b/lib/tzset.c
@@ -41,9 +41,18 @@ tzset (void)
 #endif
 
 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__
-  /* If the environment variable TZ has been set by Cygwin, neutralize it.
-     The Microsoft CRT interprets TZ differently than Cygwin and produces
-     incorrect results if TZ has the syntax used by Cygwin.  */
+  /* Rectify the value of the environment variable TZ.
+     There are two possible kinds of such values:
+       - Traditional US time zone names, e.g. "PST8PDT",
+       - tzdata time zone names, based on geography.  They contain one
+         or more slashes.
+     The Microsoft CRT understands only the first kind, see
+       <https://msdn.microsoft.com/en-us/library/90s5c885.aspx>.
+     It produces incorrect results if the value of TZ is of the second kind.
+     But in a Cygwin environment, /etc/profile.d/tzset.sh sets TZ to
+     a value of the second kind for most geographies.  If this is the case,
+     neutralize it.  For the Microsoft CRT, an absent of empty TZ means
+     the time zone that the user has set in the Windows Control Panel.  */
   const char *tz = getenv ("TZ");
   if (tz != NULL && strchr (tz, '/') != NULL)
     _putenv ("TZ=");




reply via email to

[Prev in Thread] Current Thread [Next in Thread]