Subject: Re: 25.1.50; encode-time returns wrong result

From: Paul Eggert <[email-masked]>
Date: Wed, 1 Jun 2016 01:19:50 -0700

Thanks for the bug report. This appears to be due to an incompatibility between 
MS-Windows and POSIX that I didn't know about. Please try the attached patch. I 
have not tested or installed this (I don't use MS-Windows).
From fef3119fc136889673a1a032ee0a5a47584a03fe Mon Sep 17 00:00:00 2001
From: Paul Eggert <[email-masked]>
Date: Wed, 1 Jun 2016 01:09:42 -0700
Subject: [PATCH] Port angle-bracket TZ settings to MS-Windows

* doc/lispref/os.texi (Time Zone Rules): Document MS-Windows
lack of support for numeric time zone abbreviations.
* src/w32.c (sys_putenv): Convert angle-bracket TZ syntax
to MS-compatible syntax if possible, and to "ZZZ" otherwise.
Problem reported by Kazuhiro Ito (Bug#23600).
---
 doc/lispref/os.texi |  3 ++-
 src/w32.c           | 29 +++++++++++++++++++++++++++++
 2 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/doc/lispref/os.texi b/doc/lispref/os.texi
index becb691..38dde26 100644
--- a/doc/lispref/os.texi
+++ b/doc/lispref/os.texi
@@ -1327,7 +1327,8 @@ Time Zone Rules
 a string, the conversion uses the time zone rule equivalent to setting
 @env{TZ} to that string.  If it is an integer @var{offset}, the
 conversion uses a fixed time zone with the given offset and a numeric
-abbreviation.  If it is a list (@var{offset} @var{abbr}), where
+abbreviation on POSIX-compatible platforms and an unspecified abbreviation
+on MS-Windows.  If it is a list (@var{offset} @var{abbr}), where
 @var{offset} is an integer number of seconds east of Universal Time
 and @var{abbr} is a string, the conversion uses a fixed time zone with
 the given offset and abbreviation.
diff --git a/src/w32.c b/src/w32.c
index 442ce79..71a38b9 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -2505,6 +2505,35 @@ sys_putenv (char *str)
       return unsetenv (str);
     }
 
+  if (strncmp (str, "TZ=<", 4) == 0)
+    {
+      /* MS-Windows does not support POSIX.1-2001 angle-bracket TZ
+	 abbreviation syntax.  Convert to POSIX.1-1988 syntax if possible,
+	 and to the undocumented placeholder "ZZZ" otherwise.  */
+      bool supported_abbr = true;
+      for (char *p = str + 4; *p; p++)
+	{
+	  if (('0' <= *p && *p <= '9') || *p == '-' || *p == '+')
+	    supported_abbr = false;
+	  else if (*p == '>')
+	    {
+	      ptrdiff_t abbrlen;
+	      if (supported_abbr)
+		{
+		  abbrlen = p - (str + 4);
+		  memmove (str + 3, str + 4, abbrlen);
+		}
+	      else
+		{
+		  abbrlen = 3;
+		  memset (str + 3, 'Z', abbrlen);
+		}
+	      memmove (str + 3 + abbrlen, p + 1, strlen (p));
+	      break;
+	    }
+	}
+    }
+
   return _putenv (str);
 }
 
-- 
2.7.4