Add code to be able to match the timezone name on localized Windows
authorTom Lane
Wed, 1 Sep 2004 16:21:50 +0000 (16:21 +0000)
committerTom Lane
Wed, 1 Sep 2004 16:21:50 +0000 (16:21 +0000)
systems.  Magnus Hagander.

src/timezone/pgtz.c

index 94ef44a633e27a061236ba7479e70a340d1cc97d..6bc0a10821bc96cf674ff039cec076dc879f0d56 100644 (file)
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/timezone/pgtz.c,v 1.24 2004/08/30 02:54:42 momjian Exp $
+ *   $PostgreSQL: pgsql/src/timezone/pgtz.c,v 1.25 2004/09/01 16:21:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -822,8 +822,11 @@ identify_system_timezone(void)
 {
    int         i;
    char        tzname[128];
+   char        localtzname[256];
    time_t      t = time(NULL);
    struct tm  *tm = localtime(&t);
+   HKEY        rootKey;
+   int         idx;
 
    if (!tm)
    {
@@ -846,6 +849,110 @@ identify_system_timezone(void)
        }
    }
 
+   /*
+    * Localized Windows versions return localized names for the
+    * timezone. Scan the registry to find the English name,
+    * and then try matching against our table again.
+    */
+   memset(localtzname, 0, sizeof(localtzname));
+   if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+                    "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
+                    0,
+                    KEY_READ,
+                    &rootKey) != ERROR_SUCCESS)
+   {
+       ereport(WARNING,
+               (errmsg_internal("could not open registry key to identify Windows timezone: %i", (int)GetLastError())));
+       return NULL;
+   }
+   
+   for (idx = 0; ; idx++) 
+   {
+       char keyname[256];
+       char zonename[256];
+       DWORD namesize;
+       FILETIME lastwrite;
+       HKEY key;
+       LONG r;
+       
+       memset(keyname, 0, sizeof(keyname));
+       namesize = sizeof(keyname);
+       if ((r=RegEnumKeyEx(rootKey,
+                           idx,
+                           keyname,
+                           &namesize,
+                           NULL,
+                           NULL,
+                           NULL,
+                           &lastwrite)) != ERROR_SUCCESS)
+       {
+           if (r == ERROR_NO_MORE_ITEMS)
+               break;
+           ereport(WARNING,
+                   (errmsg_internal("could not enumerate registry subkeys to identify Windows timezone: %i", (int)r)));
+           break;
+       }
+
+       if ((r=RegOpenKeyEx(rootKey,keyname,0,KEY_READ,&key)) != ERROR_SUCCESS)
+       {
+           ereport(WARNING,
+                   (errmsg_internal("could not open registry subkey to identify Windows timezone: %i", (int)r)));
+           break;
+       }
+       
+       memset(zonename, 0, sizeof(zonename));
+       namesize = sizeof(zonename);
+       if ((r=RegQueryValueEx(key, "Std", NULL, NULL, zonename, &namesize)) != ERROR_SUCCESS)
+       {
+           ereport(WARNING,
+                   (errmsg_internal("could not query value for 'std' to identify Windows timezone: %i", (int)r)));
+           RegCloseKey(key);
+           break;
+       }
+       if (strcmp(tzname, zonename) == 0)
+       {
+           /* Matched zone */
+           strcpy(localtzname, keyname);
+           RegCloseKey(key);
+           break;
+       }
+       memset(zonename, 0, sizeof(zonename));
+       namesize = sizeof(zonename);
+       if ((r=RegQueryValueEx(key, "Dlt", NULL, NULL, zonename, &namesize)) != ERROR_SUCCESS)
+       {
+           ereport(WARNING,
+                   (errmsg_internal("could not query value for 'dlt' to identify Windows timezone: %i", (int)r)));
+           RegCloseKey(key);
+           break;
+       }
+       if (strcmp(tzname, zonename) == 0)
+       {
+           /* Matched DST zone */
+           strcpy(localtzname, keyname);
+           RegCloseKey(key);
+           break;
+       }
+
+       RegCloseKey(key);
+   }
+
+   RegCloseKey(rootKey);
+
+   if (localtzname[0])
+   {
+       /* Found a localized name, so scan for that one too */
+       for (i = 0; win32_tzmap[i].stdname != NULL; i++)
+       {
+           if (strcmp(localtzname, win32_tzmap[i].stdname) == 0 ||
+               strcmp(localtzname, win32_tzmap[i].dstname) == 0)
+           {
+               elog(DEBUG4, "TZ \"%s\" matches localized Windows timezone \"%s\" (\"%s\")",
+                    win32_tzmap[i].pgtzname, tzname, localtzname);
+               return win32_tzmap[i].pgtzname;
+           }
+       }
+   }
+
    ereport(WARNING,
            (errmsg("could not find a match for Windows timezone \"%s\"",
                    tzname)));