Now that DST in the USA is over, I see this unit test fail in the GitHub CI:

FAIL: test-localtime-w32
========================

Windows API 1: 2026-09-12 00:00:00
Windows API 2: 2026-09-12 01:00:00
FAIL test-localtime-w32.exe (exit status: 7)

And similarly on my Windows 10 and 11 machines:

FAIL: test-localtime-w32
========================

Windows API 1: 2026-09-12 09:00:00
Windows API 2: 2026-09-12 10:00:00
FAIL test-localtime-w32.exe (exit status: 7)

So, apparently, the two computations are not equivalent.
"Windows API 2" is the correct one, "Windows API 1" the wrong one.

Similarly for the test-mktime-w32 test.

This patch fixes the test failure.


2026-11-05  Bruno Haible  <[email protected]>

        localtime, time_r, mktime tests: Fix test failure on native Windows.
        * tests/test-localtime-w32.c (main): Swap conversion codes. Ignore the
        result of the older conversion code.
        * tests/test-localtime_r-w32.c (main): Likewise.
        * tests/test-mktime-w32.c (main): Likewise.

diff --git a/tests/test-localtime-w32.c b/tests/test-localtime-w32.c
index f746dd9289..4d84cbddd5 100644
--- a/tests/test-localtime-w32.c
+++ b/tests/test-localtime-w32.c
@@ -58,46 +58,42 @@ main (void)
       (DWORD) (hundrednanos_since_1601_01_01 >> 32)
     };
 
-  /* Convert like GNU clisp does.  */
+  /* Convert like
+     
<https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-filetimetolocalfiletime>
+     suggests.  */
   SYSTEMTIME lsystime1;
   {
-    FILETIME lfiletime;
+    SYSTEMTIME systime;
     /* Documentation:
-       
<https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-filetimetolocalfiletime>
  */
-    if (!FileTimeToLocalFileTime (&filetime, &lfiletime))
+       
<https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/nf-timezoneapi-filetimetosystemtime>
  */
+    if (!FileTimeToSystemTime (&filetime, &systime))
       return 3;
     /* Documentation:
-       
<https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/nf-timezoneapi-filetimetosystemtime>
  */
-    if (!FileTimeToSystemTime (&lfiletime, &lsystime1))
+       
<https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/nf-timezoneapi-systemtimetotzspecificlocaltime>
  */
+    if (!SystemTimeToTzSpecificLocalTime (NULL, &systime, &lsystime1))
       return 4;
   }
   printf ("Windows API 1: %04d-%02d-%02d %02d:%02d:%02d\n",
           lsystime1.wYear, lsystime1.wMonth, lsystime1.wDay,
           lsystime1.wHour, lsystime1.wMinute, lsystime1.wSecond);
 
-  /* Convert like
-     
<https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-filetimetolocalfiletime>
-     suggests.  */
+  /* Convert like GNU clisp does.  This is actually wrong.  */
   SYSTEMTIME lsystime2;
   {
-    SYSTEMTIME systime;
+    FILETIME lfiletime;
     /* Documentation:
-       
<https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/nf-timezoneapi-filetimetosystemtime>
  */
-    if (!FileTimeToSystemTime (&filetime, &systime))
+       
<https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-filetimetolocalfiletime>
  */
+    if (!FileTimeToLocalFileTime (&filetime, &lfiletime))
       return 5;
     /* Documentation:
-       
<https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/nf-timezoneapi-systemtimetotzspecificlocaltime>
  */
-    if (!SystemTimeToTzSpecificLocalTime (NULL, &systime, &lsystime2))
+       
<https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/nf-timezoneapi-filetimetosystemtime>
  */
+    if (!FileTimeToSystemTime (&lfiletime, &lsystime2))
       return 6;
   }
   printf ("Windows API 2: %04d-%02d-%02d %02d:%02d:%02d\n",
           lsystime2.wYear, lsystime2.wMonth, lsystime2.wDay,
           lsystime2.wHour, lsystime2.wMinute, lsystime2.wSecond);
 
-  /* Both methods should be equivalent.  */
-  if (lsystime1.wHour != lsystime2.wHour)
-    return 7;
-
   /* Now see whether localtime is consistent with that.  */
   /* Documentation:
      
<https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/localtime-localtime32-localtime64>
  */
diff --git a/tests/test-localtime_r-w32.c b/tests/test-localtime_r-w32.c
index d84a15a63b..ff54903157 100644
--- a/tests/test-localtime_r-w32.c
+++ b/tests/test-localtime_r-w32.c
@@ -58,46 +58,42 @@ main (void)
       (DWORD) (hundrednanos_since_1601_01_01 >> 32)
     };
 
-  /* Convert like GNU clisp does.  */
+  /* Convert like
+     
<https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-filetimetolocalfiletime>
+     suggests.  */
   SYSTEMTIME lsystime1;
   {
-    FILETIME lfiletime;
+    SYSTEMTIME systime;
     /* Documentation:
-       
<https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-filetimetolocalfiletime>
  */
-    if (!FileTimeToLocalFileTime (&filetime, &lfiletime))
+       
<https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/nf-timezoneapi-filetimetosystemtime>
  */
+    if (!FileTimeToSystemTime (&filetime, &systime))
       return 3;
     /* Documentation:
-       
<https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/nf-timezoneapi-filetimetosystemtime>
  */
-    if (!FileTimeToSystemTime (&lfiletime, &lsystime1))
+       
<https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/nf-timezoneapi-systemtimetotzspecificlocaltime>
  */
+    if (!SystemTimeToTzSpecificLocalTime (NULL, &systime, &lsystime1))
       return 4;
   }
   printf ("Windows API 1: %04d-%02d-%02d %02d:%02d:%02d\n",
           lsystime1.wYear, lsystime1.wMonth, lsystime1.wDay,
           lsystime1.wHour, lsystime1.wMinute, lsystime1.wSecond);
 
-  /* Convert like
-     
<https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-filetimetolocalfiletime>
-     suggests.  */
+  /* Convert like GNU clisp does.  This is actually wrong.  */
   SYSTEMTIME lsystime2;
   {
-    SYSTEMTIME systime;
+    FILETIME lfiletime;
     /* Documentation:
-       
<https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/nf-timezoneapi-filetimetosystemtime>
  */
-    if (!FileTimeToSystemTime (&filetime, &systime))
+       
<https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-filetimetolocalfiletime>
  */
+    if (!FileTimeToLocalFileTime (&filetime, &lfiletime))
       return 5;
     /* Documentation:
-       
<https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/nf-timezoneapi-systemtimetotzspecificlocaltime>
  */
-    if (!SystemTimeToTzSpecificLocalTime (NULL, &systime, &lsystime2))
+       
<https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/nf-timezoneapi-filetimetosystemtime>
  */
+    if (!FileTimeToSystemTime (&lfiletime, &lsystime2))
       return 6;
   }
   printf ("Windows API 2: %04d-%02d-%02d %02d:%02d:%02d\n",
           lsystime2.wYear, lsystime2.wMonth, lsystime2.wDay,
           lsystime2.wHour, lsystime2.wMinute, lsystime2.wSecond);
 
-  /* Both methods should be equivalent.  */
-  if (lsystime1.wHour != lsystime2.wHour)
-    return 7;
-
   /* Now see whether localtime_r is consistent with that.  */
   struct tm lm;
   if (localtime_r (&seconds_since_1970_01_01, &lm) == NULL)
diff --git a/tests/test-mktime-w32.c b/tests/test-mktime-w32.c
index 39cc7a769c..d32116b510 100644
--- a/tests/test-mktime-w32.c
+++ b/tests/test-mktime-w32.c
@@ -66,18 +66,20 @@ main (void)
   lsystime.wSecond = lm.tm_sec;
   lsystime.wMilliseconds = 0;
 
-  /* Convert like GNU clisp does.  */
+  /* Convert like
+     
<https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-filetimetolocalfiletime>
+     suggests.  */
   time_t utctime1;
   {
-    FILETIME lfiletime;
+    SYSTEMTIME systime;
     FILETIME filetime;
     /* Documentation:
-       
<https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/nf-timezoneapi-systemtimetofiletime>
  */
-    if (!SystemTimeToFileTime (&lsystime, &lfiletime))
+       
<https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/nf-timezoneapi-tzspecificlocaltimetosystemtime>
  */
+    if (!TzSpecificLocalTimeToSystemTime (NULL, &lsystime, &systime))
       return 3;
     /* Documentation:
-       
<https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-localfiletimetofiletime>
  */
-    if (!LocalFileTimeToFileTime (&lfiletime, &filetime))
+       
<https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/nf-timezoneapi-systemtimetofiletime>
  */
+    if (!SystemTimeToFileTime (&systime, &filetime))
       return 4;
     long long hundrednanos_since_1601_01_01 =
       ((unsigned long long) filetime.dwHighDateTime << 32)
@@ -86,20 +88,18 @@ main (void)
   }
   printf ("Windows API 1: %lld\n", (long long) utctime1);
 
-  /* Convert like
-     
<https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-filetimetolocalfiletime>
-     suggests.  */
+  /* Convert like GNU clisp does.  This is actually wrong.  */
   time_t utctime2;
   {
-    SYSTEMTIME systime;
+    FILETIME lfiletime;
     FILETIME filetime;
     /* Documentation:
-       
<https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/nf-timezoneapi-tzspecificlocaltimetosystemtime>
  */
-    if (!TzSpecificLocalTimeToSystemTime (NULL, &lsystime, &systime))
+       
<https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/nf-timezoneapi-systemtimetofiletime>
  */
+    if (!SystemTimeToFileTime (&lsystime, &lfiletime))
       return 5;
     /* Documentation:
-       
<https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/nf-timezoneapi-systemtimetofiletime>
  */
-    if (!SystemTimeToFileTime (&systime, &filetime))
+       
<https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-localfiletimetofiletime>
  */
+    if (!LocalFileTimeToFileTime (&lfiletime, &filetime))
       return 6;
     long long hundrednanos_since_1601_01_01 =
       ((unsigned long long) filetime.dwHighDateTime << 32)
@@ -108,10 +108,6 @@ main (void)
   }
   printf ("Windows API 2: %lld\n", (long long) utctime2);
 
-  /* Both methods should be equivalent.  */
-  if (utctime1 != utctime2)
-    return 7;
-
   /* Now see whether mktime (a.k.a. timelocal) is consistent with that.  */
   /* Documentation:
      
<https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/mktime-mktime32-mktime64>
  */




Reply via email to