Index: timezone/pgtz.c =================================================================== RCS file: /projects/cvsroot/pgsql-server/src/timezone/pgtz.c,v retrieving revision 1.20 diff -c -r1.20 pgtz.c *** timezone/pgtz.c 30 Jul 2004 17:31:24 -0000 1.20 --- timezone/pgtz.c 30 Jul 2004 20:43:08 -0000 *************** *** 43,52 **** static char tzdir[MAXPGPATH]; static int done_tzdir = 0; static void scan_available_timezones(char *tzdir, char *tzdirsub, struct tztry *tt, int *bestscore, char *bestzonename); ! /* * Return full pathname of timezone data directory --- 43,54 ---- static char tzdir[MAXPGPATH]; static int done_tzdir = 0; + #ifndef WIN32 + static void scan_available_timezones(char *tzdir, char *tzdirsub, struct tztry *tt, int *bestscore, char *bestzonename); ! #endif /* * Return full pathname of timezone data directory *************** *** 64,69 **** --- 66,73 ---- return tzdir; } + #ifndef WIN32 + /* * Get GMT offset from a system struct tm */ *************** *** 84,115 **** } /* - * Grotty kluge for win32 ... do we really need this? - */ - #ifdef WIN32 - #define TZABBREV(tz) win32_get_timezone_abbrev(tz) - - static char * - win32_get_timezone_abbrev(const char *tz) - { - static char w32tzabbr[TZ_STRLEN_MAX + 1]; - int l = 0; - const char *c; - - for (c = tz; *c; c++) - { - if (isupper((unsigned char) *c)) - w32tzabbr[l++] = *c; - } - w32tzabbr[l] = '\0'; - return w32tzabbr; - } - - #else - #define TZABBREV(tz) (tz) - #endif - - /* * Convenience subroutine to convert y/m/d to time_t (NOT pg_time_t) */ static time_t --- 88,93 ---- *************** *** 210,216 **** return -1; /* probably shouldn't happen */ memset(cbuf, 0, sizeof(cbuf)); strftime(cbuf, sizeof(cbuf) - 1, "%Z", systm); /* zone abbr */ ! if (strcmp(TZABBREV(cbuf), pgtm->tm_zone) != 0) { elog(DEBUG4, "TZ \"%s\" scores %d: at %ld \"%s\" versus \"%s\"", tzname, i, (long) pgtt, --- 188,194 ---- return -1; /* probably shouldn't happen */ memset(cbuf, 0, sizeof(cbuf)); strftime(cbuf, sizeof(cbuf) - 1, "%Z", systm); /* zone abbr */ ! if (strcmp(cbuf, pgtm->tm_zone) != 0) { elog(DEBUG4, "TZ \"%s\" scores %d: at %ld \"%s\" versus \"%s\"", tzname, i, (long) pgtt, *************** *** 320,326 **** /* found STD zone */ memset(cbuf, 0, sizeof(cbuf)); strftime(cbuf, sizeof(cbuf) - 1, "%Z", tm); /* zone abbr */ ! strcpy(std_zone_name, TZABBREV(cbuf)); std_ofs = get_timezone_offset(tm); } if (tm->tm_isdst > 0 && dst_zone_name[0] == '\0') --- 298,304 ---- /* found STD zone */ memset(cbuf, 0, sizeof(cbuf)); strftime(cbuf, sizeof(cbuf) - 1, "%Z", tm); /* zone abbr */ ! strcpy(std_zone_name, cbuf); std_ofs = get_timezone_offset(tm); } if (tm->tm_isdst > 0 && dst_zone_name[0] == '\0') *************** *** 328,334 **** /* found DST zone */ memset(cbuf, 0, sizeof(cbuf)); strftime(cbuf, sizeof(cbuf) - 1, "%Z", tm); /* zone abbr */ ! strcpy(dst_zone_name, TZABBREV(cbuf)); } /* Done if found both */ if (std_zone_name[0] && dst_zone_name[0]) --- 306,312 ---- /* found DST zone */ memset(cbuf, 0, sizeof(cbuf)); strftime(cbuf, sizeof(cbuf) - 1, "%Z", tm); /* zone abbr */ ! strcpy(dst_zone_name, cbuf); } /* Done if found both */ if (std_zone_name[0] && dst_zone_name[0]) *************** *** 424,436 **** direntry = readdir(dirdesc); if (!direntry) { - #ifdef WIN32 - /* This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), - * but not in released version - */ - if (GetLastError() == ERROR_NO_MORE_FILES) - errno = 0; - #endif if (errno) ereport(LOG, (errcode_for_file_access(), --- 402,407 ---- *************** *** 478,483 **** --- 449,585 ---- tzdir[tzdir_orig_len] = '\0'; } + #else + /* + * Win32 native knowledge about timezones appear to be too incomplete + * and too different from our TZ library to be of any use. But there is + * a limited number of timezones available, so we create a mapping + * table instead. + */ + const struct { + const char *stdname; /* Windows name of standard timezone */ + const char *dstname; /* Windows name of daylight timezone */ + const char *pgtzname; /* Name of pgsql timezone to map to */ + } win32_tzmap[] = { + /* + * This list is built from the contents of the registry at + * HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones + * on a Windows XP Professional SP1 + * The zones have been matched to pg timezones by looking at the cities listed + * in the win32 display name (in the comment here) in most cases. + */ + {"Afghanistan Standard Time","Afghanistan Daylight Time","Asia/Kabul"}, /* (GMT+04:30) Kabul */ + {"Alaskan Standard Time","Alaskan Daylight Time","US/Alaska"}, /* (GMT-09:00) Alaska */ + {"Arab Standard Time","Arab Daylight Time","Asia/Kuwait"}, /* (GMT+03:00) Kuwait, Riyadh */ + {"Arabian Standard Time","Arabian Daylight Time","Asia/Muscat"}, /* (GMT+04:00) Abu Dhabi, Muscat */ + {"Arabic Standard Time","Arabic Daylight Time","Asia/Baghdad"}, /* (GMT+03:00) Baghdad */ + {"Atlantic Standard Time","Atlantic Daylight Time","Canada/Atlantic"}, /* (GMT-04:00) Atlantic Time (Canada) */ + {"AUS Central Standard Time","AUS Central Daylight Time","Australia/Darwin"}, /* (GMT+09:30) Darwin */ + {"AUS Eastern Standard Time","AUS Eastern Daylight Time","Australia/Canberra"}, /* (GMT+10:00) Canberra, Melbourne, Sydney */ + {"Azores Standard Time","Azores Daylight Time","Atlantic/Azores"}, /* (GMT-01:00) Azores */ + {"Canada Central Standard Time","Canada Central Daylight Time","Canada/Saskatchewan"}, /* (GMT-06:00) Saskatchewan */ + {"Cape Verde Standard Time","Cape Verde Daylight Time","Atlantic/Cape_Verde"}, /* (GMT-01:00) Cape Verde Is. */ + {"Caucasus Standard Time","Caucasus Daylight Time","Asia/Baku"}, /* (GMT+04:00) Baku, Tbilisi, Yerevan */ + {"Cen. Australia Standard Time","Cen. Australia Daylight Time","Australia/Adelaide"}, /* (GMT+09:30) Adelaide */ + {"Central America Standard Time","Central America Daylight Time","CST6CDT"}, /* (GMT-06:00) Central America */ + {"Central Asia Standard Time","Central Asia Daylight Time","Asia/Dhaka"}, /* (GMT+06:00) Astana, Dhaka */ + {"Central Europe Standard Time","Central Europe Daylight Time","Europe/Belgrade"}, /* (GMT+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague */ + {"Central European Standard Time","Central European Daylight Time","Europe/Sarajevo"}, /* (GMT+01:00) Sarajevo, Skopje, Warsaw, Zagreb */ + {"Central Pacific Standard Time","Central Pacific Daylight Time","Pacific/Noumea"}, /* (GMT+11:00) Magadan, Solomon Is., New Caledonia */ + {"Central Standard Time","Central Daylight Time","US/Central"}, /* (GMT-06:00) Central Time (US & Canada) */ + {"China Standard Time","China Daylight Time","Asia/Hong_Kong"}, /* (GMT+08:00) Beijing, Chongqing, Hong Kong, Urumqi */ + {"Dateline Standard Time","Dateline Daylight Time","Etc/GMT+12"}, /* (GMT-12:00) International Date Line West */ + {"E. Africa Standard Time","E. Africa Daylight Time","Africa/Nairobi"}, /* (GMT+03:00) Nairobi */ + {"E. Australia Standard Time","E. Australia Daylight Time","Australia/Brisbane"}, /* (GMT+10:00) Brisbane */ + {"E. Europe Standard Time","E. Europe Daylight Time","Europe/Bucharest"}, /* (GMT+02:00) Bucharest */ + {"E. South America Standard Time","E. South America Daylight Time","America/Araguaina"}, /* (GMT-03:00) Brasilia */ + {"Eastern Standard Time","Eastern Daylight Time","US/Eastern"}, /* (GMT-05:00) Eastern Time (US & Canada) */ + {"Egypt Standard Time","Egypt Daylight Time","Africa/Cairo"}, /* (GMT+02:00) Cairo */ + {"Ekaterinburg Standard Time","Ekaterinburg Daylight Time","Asia/Yekaterinburg"}, /* (GMT+05:00) Ekaterinburg */ + {"Fiji Standard Time","Fiji Daylight Time","Pacific/Fiji"}, /* (GMT+12:00) Fiji, Kamchatka, Marshall Is. */ + {"FLE Standard Time","FLE Daylight Time","Europe/Helsinki"}, /* (GMT+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius */ + {"GMT Standard Time","GMT Daylight Time","Europe/Dublin"}, /* (GMT) Greenwich Mean Time : Dublin, Edinburgh, Lisbon, London */ + {"Greenland Standard Time","Greenland Daylight Time","America/Godthab"}, /* (GMT-03:00) Greenland */ + {"Greenwich Standard Time","Greenwich Daylight Time","Africa/Casablanca"}, /* (GMT) Casablanca, Monrovia */ + {"GTB Standard Time","GTB Daylight Time","Europe/Athens"}, /* (GMT+02:00) Athens, Istanbul, Minsk */ + {"Hawaiian Standard Time","Hawaiian Daylight Time","US/Hawaii"}, /* (GMT-10:00) Hawaii */ + {"India Standard Time","India Daylight Time","Asia/Calcutta"}, /* (GMT+05:30) Chennai, Kolkata, Mumbai, New Delhi */ + {"Iran Standard Time","Iran Daylight Time","Asia/Tehran"}, /* (GMT+03:30) Tehran */ + {"Jerusalem Standard Time","Jerusalem Daylight Time","Asia/Jerusalem"}, /* (GMT+02:00) Jerusalem */ + {"Korea Standard Time","Korea Daylight Time","Asia/Seoul"}, /* (GMT+09:00) Seoul */ + {"Mexico Standard Time","Mexico Daylight Time","America/Mexico_City"}, /* (GMT-06:00) Guadalajara, Mexico City, Monterrey */ + {"Mexico Standard Time","Mexico Daylight Time","America/La_Paz"}, /* (GMT-07:00) Chihuahua, La Paz, Mazatlan */ + {"Mid-Atlantic Standard Time","Mid-Atlantic Daylight Time","Atlantic/South_Georgia"}, /* (GMT-02:00) Mid-Atlantic */ + {"Mountain Standard Time","Mountain Daylight Time","US/Mountain"}, /* (GMT-07:00) Mountain Time (US & Canada) */ + {"Myanmar Standard Time","Myanmar Daylight Time","Asia/Rangoon"}, /* (GMT+06:30) Rangoon */ + {"N. Central Asia Standard Time","N. Central Asia Daylight Time","Asia/Almaty"}, /* (GMT+06:00) Almaty, Novosibirsk */ + {"Nepal Standard Time","Nepal Daylight Time","Asia/Katmandu"}, /* (GMT+05:45) Kathmandu */ + {"New Zealand Standard Time","New Zealand Daylight Time","Pacific/Auckland"}, /* (GMT+12:00) Auckland, Wellington */ + {"Newfoundland Standard Time","Newfoundland Daylight Time","Canada/Newfoundland"}, /* (GMT-03:30) Newfoundland */ + {"North Asia East Standard Time","North Asia East Daylight Time","Asia/Irkutsk"}, /* (GMT+08:00) Irkutsk, Ulaan Bataar */ + {"North Asia Standard Time","North Asia Daylight Time","Asia/Krasnoyarsk"}, /* (GMT+07:00) Krasnoyarsk */ + {"Pacific SA Standard Time","Pacific SA Daylight Time","America/Santiago"}, /* (GMT-04:00) Santiago */ + {"Pacific Standard Time","Pacific Daylight Time","US/Pacific"}, /* (GMT-08:00) Pacific Time (US & Canada); Tijuana */ + {"Romance Standard Time","Romance Daylight Time","Europe/Brussels"}, /* (GMT+01:00) Brussels, Copenhagen, Madrid, Paris */ + {"Russian Standard Time","Russian Daylight Time","Europe/Moscow"}, /* (GMT+03:00) Moscow, St. Petersburg, Volgograd */ + {"SA Eastern Standard Time","SA Eastern Daylight Time","America/Buenos_Aires"}, /* (GMT-03:00) Buenos Aires, Georgetown */ + {"SA Pacific Standard Time","SA Pacific Daylight Time","America/Bogota"}, /* (GMT-05:00) Bogota, Lima, Quito */ + {"SA Western Standard Time","SA Western Daylight Time","America/Caracas"}, /* (GMT-04:00) Caracas, La Paz */ + {"Samoa Standard Time","Samoa Daylight Time","Pacific/Midway"}, /* (GMT-11:00) Midway Island, Samoa */ + {"SE Asia Standard Time","SE Asia Daylight Time","Asia/Bangkok"}, /* (GMT+07:00) Bangkok, Hanoi, Jakarta */ + {"Malay Peninsula Standard Time","Malay Peninsula Daylight Time","Asia/Kuala_Lumpur"}, /* (GMT+08:00) Kuala Lumpur, Singapore */ + {"South Africa Standard Time","South Africa Daylight Time","Africa/Harare"}, /* (GMT+02:00) Harare, Pretoria */ + {"Sri Lanka Standard Time","Sri Lanka Daylight Time","Asia/Colombo"}, /* (GMT+06:00) Sri Jayawardenepura */ + {"Taipei Standard Time","Taipei Daylight Time","Asia/Taipei"}, /* (GMT+08:00) Taipei */ + {"Tasmania Standard Time","Tasmania Daylight Time","Australia/Hobart"}, /* (GMT+10:00) Hobart */ + {"Tokyo Standard Time","Tokyo Daylight Time","Asia/Tokyo"}, /* (GMT+09:00) Osaka, Sapporo, Tokyo */ + {"Tonga Standard Time","Tonga Daylight Time","Pacific/Tongatapu"}, /* (GMT+13:00) Nuku'alofa */ + {"US Eastern Standard Time","US Eastern Daylight Time","US/Eastern"}, /* (GMT-05:00) Indiana (East) */ + {"US Mountain Standard Time","US Mountain Daylight Time","US/Arizona"}, /* (GMT-07:00) Arizona */ + {"Vladivostok Standard Time","Vladivostok Daylight Time","Asia/Vladivostok"}, /* (GMT+10:00) Vladivostok */ + {"W. Australia Standard Time","W. Australia Daylight Time","Australia/Perth"}, /* (GMT+08:00) Perth */ + /* {"W. Central Africa Standard Time","W. Central Africa Daylight Time",""}, Could not find a match for this one. Excluded for now. */ /* (GMT+01:00) West Central Africa */ + {"W. Europe Standard Time","W. Europe Daylight Time","CET"}, /* (GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna */ + {"West Asia Standard Time","West Asia Daylight Time","Asia/Karachi"}, /* (GMT+05:00) Islamabad, Karachi, Tashkent */ + {"West Pacific Standard Time","West Pacific Daylight Time","Pacific/Guam"}, /* (GMT+10:00) Guam, Port Moresby */ + {"Yakutsk Standard Time","Yakutsk Daylight Time","Asia/Yakutsk"}, /* (GMT+09:00) Yakutsk */ + {NULL, NULL, NULL }}; + + static char * + identify_system_timezone(void) + { + int i; + char tzname[128]; + time_t t = time(NULL); + struct tm *tm = localtime(&t); + + if (!tm) + { + ereport(WARNING, + (errmsg_internal("Unable to determine current date/time!"))); + return NULL; + } + + ZeroMemory(tzname,sizeof(tzname)); + strftime(tzname, sizeof(tzname)-1, "%Z", tm); + + for (i=0; win32_tzmap[i].stdname != NULL; i++) + { + if (!strcmp(tzname, win32_tzmap[i].stdname) || + !strcmp(tzname, win32_tzmap[i].dstname)) + { + elog(DEBUG4, "TZ \"%s\" matches win32 timezone \"%s\"", win32_tzmap[i].pgtzname, tzname); + return (char *)win32_tzmap[i].pgtzname; + } + } + + ereport(WARNING, + (errmsg_internal("Unable to locate system timezone in the win32 system timeszone map!"))); + + return NULL; + } + + #endif /* WIN32 */ /* * Check whether timezone is acceptable.