changeset 29138:eacd1a3417c3

time: Get time zone offset on Windows (bug #53908). * liboctave/system/oct-time.cc (base_tm::init): Get time zone offset information on Windows.
author Markus Mützel <markus.muetzel@gmx.de>
date Tue, 01 Dec 2020 22:59:35 +0100
parents fd8e536d166e
children f5e89a80ba8c
files liboctave/system/oct-time.cc
diffstat 1 files changed, 41 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/liboctave/system/oct-time.cc	Wed Dec 02 20:00:49 2020 -0800
+++ b/liboctave/system/oct-time.cc	Tue Dec 01 22:59:35 2020 +0100
@@ -34,8 +34,13 @@
 #include <limits>
 #include <ostream>
 
+#if defined (OCTAVE_USE_WINDOWS_API)
+#  include <windows.h>
+#endif
+
 #include "lo-error.h"
 #include "lo-utils.h"
+#include "lo-sysdep.h"
 #include "oct-locbuf.h"
 #include "oct-time.h"
 #include "octave-preserve-stream-state.h"
@@ -238,11 +243,47 @@
 
 #if defined (HAVE_TM_GMTOFF)
       m_gmtoff = t->tm_gmtoff;
+#elif defined (OCTAVE_USE_WINDOWS_API)
+      TIME_ZONE_INFORMATION tzi;
+
+      // GetTimeZoneInformationForYear is in Windows Vista SP1 or later
+      typedef BOOL (WINAPI *gtzify_type) (USHORT year,
+                                          PDYNAMIC_TIME_ZONE_INFORMATION pdtzi,
+                                          LPTIME_ZONE_INFORMATION ptzi);
+      HMODULE h_kernel32 = LoadLibrary ("kernel32.dll");
+
+      gtzify_type p_gtzify = nullptr;
+      if (h_kernel32)
+        {
+          p_gtzify = reinterpret_cast<gtzify_type>
+                       (GetProcAddress (h_kernel32,
+                                        "GetTimeZoneInformationForYear"));
+
+          if (p_gtzify)
+            p_gtzify (m_year, nullptr, &tzi);
+
+          FreeLibrary (h_kernel32);
+        }
+
+      // Fall back to GetTimeZoneInformation, which might be wrong if a time
+      // zone switched the GMT offset.
+      if (! p_gtzify)
+        GetTimeZoneInformation (&tzi);
+
+      if (m_isdst)
+        m_gmtoff = -60 * (tzi.Bias + tzi.DaylightBias);
+      else
+        m_gmtoff = -60 * (tzi.Bias + tzi.StandardBias);
 #endif
 
 #if defined (HAVE_STRUCT_TM_TM_ZONE)
       if (t->tm_zone)
         m_zone = t->tm_zone;
+#elif defined (OCTAVE_USE_WINDOWS_API)
+      if (m_isdst)
+        m_zone = sys::u8_from_wstring (tzi.DaylightName);
+      else
+        m_zone = sys::u8_from_wstring (tzi.StandardName);
 #elif defined (HAVE_TZNAME)
       if (t->tm_isdst == 0 || t->tm_isdst == 1)
         m_zone = tzname[t->tm_isdst];