display-time) are in real danger of missing timezone and DST
changes. Calling tzset before each localtime call fixes that. */
tzset ();
+ w32_fix_tzset ();
#endif
tm = localtime_rz (tz, t, tm);
if (!tm && errno == ENOMEM)
block_input ();
emacs_setenv_TZ (zone_string);
tzset ();
+#ifdef WINDOWSNT
+ w32_fix_tzset ();
+#endif
timezone_t old_tz = local_tz;
local_tz = new_tz;
tzfree (old_tz);
}
\f
+/* mingw.org's MinGW doesn't declare _dstbias. MinGW64 defines it as a
+ macro. */
+#ifndef _dstbias
+__MINGW_IMPORT int _dstbias;
+#endif
+
+/* Fix a bug in MS implementation of 'tzset'. This function should be
+ called immediately after 'tzset'. */
+void
+w32_fix_tzset (void)
+{
+ char *tz_env = getenv ("TZ");
+
+ /* When TZ is defined in the environment, '_tzset' updates _daylight,
+ but not _dstbias. Then if we are switching from a timezone without
+ DST to a timezone with DST, 'localtime' and friends will apply zero
+ DST bias, which is incorrect. (When TZ is not defined, '_tzset'
+ does update _dstbias using values obtained from Windows API
+ GetTimeZoneInformation.) Here we fix that blunder by detecting
+ this situation and forcing _dstbias to be 1 hour. */
+ if (tz_env && _daylight && !_dstbias)
+ _dstbias = -3600;
+}
+
/* The Windows CRT functions are "optimized for speed", so they don't
check for timezone and DST changes if they were last called less
than 1 minute ago (see http://support.microsoft.com/kb/821231). So
sys_localtime (const time_t *t)
{
tzset ();
+ w32_fix_tzset ();
return localtime (t);
}
extern int fchmodat (int, char const *, mode_t, int);
extern int lchmod (char const *, mode_t);
extern bool symlinks_supported (const char *);
+extern void w32_fix_tzset (void);
/* Return total and free memory info. */