aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorEli Zaretskii2025-05-26 19:53:21 +0300
committerEli Zaretskii2025-05-26 19:53:21 +0300
commit3b5226af3f737c82f9bbedd8fbe067bab4b4b67a (patch)
tree23706a4021735bea57c426b80982ed79652dc6a9 /src
parent53371c959462a677a29ee869b3b6627facf3ed79 (diff)
downloademacs-3b5226af3f737c82f9bbedd8fbe067bab4b4b67a.tar.gz
emacs-3b5226af3f737c82f9bbedd8fbe067bab4b4b67a.zip
Fix DST time calculations on MS-Windows
* src/w32.c (w32_fix_tzset): New function. * src/timefns.c (emacs_localtime_rz, tzlookup): * src/w32.c (sys_localtime): Call 'w32_fix_tzset'. (Bug#11281)
Diffstat (limited to 'src')
-rw-r--r--src/timefns.c4
-rw-r--r--src/w32.c25
-rw-r--r--src/w32.h1
3 files changed, 30 insertions, 0 deletions
diff --git a/src/timefns.c b/src/timefns.c
index 4d296ff8dcd..8cf424bbe7e 100644
--- a/src/timefns.c
+++ b/src/timefns.c
@@ -189,6 +189,7 @@ emacs_localtime_rz (timezone_t tz, time_t const *t, struct tm *tm)
189 display-time) are in real danger of missing timezone and DST 189 display-time) are in real danger of missing timezone and DST
190 changes. Calling tzset before each localtime call fixes that. */ 190 changes. Calling tzset before each localtime call fixes that. */
191 tzset (); 191 tzset ();
192 w32_fix_tzset ();
192#endif 193#endif
193 tm = localtime_rz (tz, t, tm); 194 tm = localtime_rz (tz, t, tm);
194 if (!tm && errno == ENOMEM) 195 if (!tm && errno == ENOMEM)
@@ -306,6 +307,9 @@ tzlookup (Lisp_Object zone, bool settz)
306 block_input (); 307 block_input ();
307 emacs_setenv_TZ (zone_string); 308 emacs_setenv_TZ (zone_string);
308 tzset (); 309 tzset ();
310#ifdef WINDOWSNT
311 w32_fix_tzset ();
312#endif
309 timezone_t old_tz = local_tz; 313 timezone_t old_tz = local_tz;
310 local_tz = new_tz; 314 local_tz = new_tz;
311 tzfree (old_tz); 315 tzfree (old_tz);
diff --git a/src/w32.c b/src/w32.c
index 5de721ad71f..9e17c2e5fbb 100644
--- a/src/w32.c
+++ b/src/w32.c
@@ -10289,6 +10289,30 @@ w32_read_registry (HKEY rootkey, Lisp_Object lkey, Lisp_Object lname)
10289} 10289}
10290 10290
10291 10291
10292/* mingw.org's MinGW doesn't declare _dstbias. MinGW64 defines it as a
10293 macro. */
10294#ifndef _dstbias
10295__MINGW_IMPORT int _dstbias;
10296#endif
10297
10298/* Fix a bug in MS implementation of 'tzset'. This function should be
10299 called immediately after 'tzset'. */
10300void
10301w32_fix_tzset (void)
10302{
10303 char *tz_env = getenv ("TZ");
10304
10305 /* When TZ is defined in the environment, '_tzset' updates _daylight,
10306 but not _dstbias. Then if we are switching from a timezone without
10307 DST to a timezone with DST, 'localtime' and friends will apply zero
10308 DST bias, which is incorrect. (When TZ is not defined, '_tzset'
10309 does update _dstbias using values obtained from Windows API
10310 GetTimeZoneInformation.) Here we fix that blunder by detecting
10311 this situation and forcing _dstbias to be 1 hour. */
10312 if (tz_env && _daylight && !_dstbias)
10313 _dstbias = -3600;
10314}
10315
10292/* The Windows CRT functions are "optimized for speed", so they don't 10316/* The Windows CRT functions are "optimized for speed", so they don't
10293 check for timezone and DST changes if they were last called less 10317 check for timezone and DST changes if they were last called less
10294 than 1 minute ago (see http://support.microsoft.com/kb/821231). So 10318 than 1 minute ago (see http://support.microsoft.com/kb/821231). So
@@ -10299,6 +10323,7 @@ struct tm *
10299sys_localtime (const time_t *t) 10323sys_localtime (const time_t *t)
10300{ 10324{
10301 tzset (); 10325 tzset ();
10326 w32_fix_tzset ();
10302 return localtime (t); 10327 return localtime (t);
10303} 10328}
10304 10329
diff --git a/src/w32.h b/src/w32.h
index ae3999ffcfd..9d9887ec782 100644
--- a/src/w32.h
+++ b/src/w32.h
@@ -234,6 +234,7 @@ extern int openat (int, const char *, int, int);
234extern int fchmodat (int, char const *, mode_t, int); 234extern int fchmodat (int, char const *, mode_t, int);
235extern int lchmod (char const *, mode_t); 235extern int lchmod (char const *, mode_t);
236extern bool symlinks_supported (const char *); 236extern bool symlinks_supported (const char *);
237extern void w32_fix_tzset (void);
237 238
238 239
239/* Return total and free memory info. */ 240/* Return total and free memory info. */