ICU-9752 Update Windows time zone detection to use CLDR data
X-SVN-Rev: 32860
diff --git a/source/common/wintz.c b/source/common/wintz.c
index f64a4ad..c9bb15a 100644
--- a/source/common/wintz.c
+++ b/source/common/wintz.c
@@ -1,6 +1,6 @@
/*
********************************************************************************
-* Copyright (C) 2005-2007, International Business Machines
+* Copyright (C) 2005-2012, International Business Machines
* Corporation and others. All Rights Reserved.
********************************************************************************
*
@@ -14,11 +14,11 @@
#ifdef U_WINDOWS
#include "wintz.h"
-
#include "cmemory.h"
#include "cstring.h"
#include "unicode/ustring.h"
+#include "unicode/ures.h"
# define WIN32_LEAN_AND_MEAN
# define VC_EXTRALEAN
@@ -28,11 +28,7 @@
# define NOMCX
#include <windows.h>
-#define ARRAY_SIZE(array) (sizeof array / sizeof array[0])
-#define NEW_ARRAY(type,count) (type *) uprv_malloc((count) * sizeof(type))
-#define DELETE_ARRAY(array) uprv_free((void *) (array))
-
-#define ICUID_STACK_BUFFER_SIZE 32
+#define MAX_LENGTH_ID 40
/* The layout of the Tzi value in the registry */
typedef struct
@@ -44,17 +40,6 @@
SYSTEMTIME daylightDate;
} TZI;
-typedef struct
-{
- const char *icuid;
- const char *winid;
-} WindowsICUMap;
-
-typedef struct {
- const char* winid;
- const char* altwinid;
-} WindowsZoneRemap;
-
/**
* Various registry keys and key fragments.
*/
@@ -98,252 +83,12 @@
* the registry.
*/
enum {
- WIN_9X_ME_TYPE = 0,
- WIN_NT_TYPE = 1,
- WIN_2K_XP_TYPE = 2
+ WIN_9X_ME_TYPE = 1,
+ WIN_NT_TYPE = 2,
+ WIN_2K_XP_TYPE = 3
};
-# if 0
-/*
- * ZONE_MAP from supplementalData.txt
- */
-static const WindowsICUMap NEW_ZONE_MAP[] = {
- {"Africa/Cairo", "Egypt"},
- {"Africa/Casablanca", "Greenwich"},
- {"Africa/Johannesburg", "South Africa"},
- {"Africa/Lagos", "W. Central Africa"},
- {"Africa/Nairobi", "E. Africa"},
- {"Africa/Windhoek", "Namibia"},
- {"America/Anchorage", "Alaskan"},
- {"America/Bogota", "SA Pacific"},
- {"America/Buenos_Aires", "SA Eastern"},
- {"America/Caracas", "SA Western"},
- {"America/Chicago", "Central"},
- {"America/Chihuahua", "Mountain Standard Time (Mexico)"},
- {"America/Denver", "Mountain"},
- {"America/Godthab", "Greenland"},
- {"America/Guatemala", "Central America"},
- {"America/Halifax", "Atlantic"},
- {"America/Indianapolis", "US Eastern"},
- {"America/Los_Angeles", "Pacific"},
- {"America/Manaus", "Central Brazilian"},
- {"America/Mexico_City", "Central Standard Time (Mexico)"},
- {"America/Montevideo", "Montevideo"},
- {"America/New_York", "Eastern"},
- {"America/Noronha", "Mid-Atlantic"},
- {"America/Phoenix", "US Mountain"},
- {"America/Regina", "Canada Central"},
- {"America/Santiago", "Pacific SA"},
- {"America/Sao_Paulo", "E. South America"},
- {"America/St_Johns", "Newfoundland"},
- {"America/Tijuana", "Pacific Standard Time (Mexico)"},
- {"Asia/Amman", "Jordan"},
- {"Asia/Baghdad", "Arabic"},
- {"Asia/Baku", "Azerbaijan"},
- {"Asia/Bangkok", "SE Asia"},
- {"Asia/Beirut", "Middle East"},
- {"Asia/Calcutta", "India"},
- {"Asia/Colombo", "Sri Lanka"},
- {"Asia/Dhaka", "Central Asia"},
- {"Asia/Jerusalem", "Israel"},
- {"Asia/Kabul", "Afghanistan"},
- {"Asia/Karachi", "West Asia"},
- {"Asia/Katmandu", "Nepal"},
- {"Asia/Krasnoyarsk", "North Asia"},
- {"Asia/Muscat", "Arabian"},
- {"Asia/Novosibirsk", "N. Central Asia"},
- {"Asia/Rangoon", "Myanmar"},
- {"Asia/Riyadh", "Arab"},
- {"Asia/Seoul", "Korea"},
- {"Asia/Shanghai", "China"},
- {"Asia/Singapore", "Singapore"},
- {"Asia/Taipei", "Taipei"},
- {"Asia/Tbilisi", "Georgian"},
- {"Asia/Tehran", "Iran"},
- {"Asia/Tokyo", "Tokyo"},
- {"Asia/Ulaanbaatar", "North Asia East"},
- {"Asia/Vladivostok", "Vladivostok"},
- {"Asia/Yakutsk", "Yakutsk"},
- {"Asia/Yekaterinburg", "Ekaterinburg"},
- {"Asia/Yerevan", "Caucasus"},
- {"Atlantic/Azores", "Azores"},
- {"Atlantic/Cape_Verde", "Cape Verde"},
- {"Australia/Adelaide", "Cen. Australia"},
- {"Australia/Brisbane", "E. Australia"},
- {"Australia/Darwin", "AUS Central"},
- {"Australia/Hobart", "Tasmania"},
- {"Australia/Perth", "W. Australia"},
- {"Australia/Sydney", "AUS Eastern"},
- {"Europe/Berlin", "W. Europe"},
- {"Europe/Helsinki", "FLE"},
- {"Europe/Istanbul", "GTB"},
- {"Europe/London", "GMT"},
- {"Europe/Minsk", "E. Europe"},
- {"Europe/Moscow", "Russian"},
- {"Europe/Paris", "Romance"},
- {"Europe/Prague", "Central Europe"},
- {"Europe/Warsaw", "Central European"},
- {"Pacific/Apia", "Samoa"},
- {"Pacific/Auckland", "New Zealand"},
- {"Pacific/Fiji", "Fiji"},
- {"Pacific/Guadalcanal", "Central Pacific"},
- {"Pacific/Guam", "West Pacific"},
- {"Pacific/Honolulu", "Hawaiian"},
- {"Pacific/Kwajalein", "Dateline"},
- {"Pacific/Tongatapu", "Tonga"}
-};
-#endif
-
-/* NOTE: Some Windows zone ids appear more than once. In such cases the
- * ICU zone id from the first one is the preferred match.
- */
-static const WindowsICUMap ZONE_MAP[] = {
- {"Pacific/Kwajalein", "Dateline"}, /* S (GMT-12:00) International Date Line West */
- {"Etc/GMT+12", "Dateline"}, /* S (GMT-12:00) International Date Line West */
-
- {"Pacific/Apia", "Samoa"}, /* S (GMT-11:00) Midway Island, Samoa */
-
- {"Pacific/Honolulu", "Hawaiian"}, /* S (GMT-10:00) Hawaii */
-
- {"America/Anchorage", "Alaskan"}, /* D (GMT-09:00) Alaska */
-
- {"America/Los_Angeles", "Pacific"}, /* D (GMT-08:00) Pacific Time (US & Canada) */
- {"America/Tijuana", "Pacific Standard Time (Mexico)"}, /* S (GMT-08:00) Tijuana, Baja California */
-
- {"America/Phoenix", "US Mountain"}, /* S (GMT-07:00) Arizona */
- {"America/Denver", "Mountain"}, /* D (GMT-07:00) Mountain Time (US & Canada) */
- {"America/Chihuahua", "Mountain Standard Time (Mexico)"}, /* D (GMT-07:00) Chihuahua, La Paz, Mazatlan */
-
- {"America/Managua", "Central America"}, /* S (GMT-06:00) Central America */ /* America/Guatemala? */
- {"America/Regina", "Canada Central"}, /* S (GMT-06:00) Saskatchewan */
- {"America/Mexico_City", "Central Standard Time (Mexico)"}, /* D (GMT-06:00) Guadalajara, Mexico City, Monterrey */
- {"America/Chicago", "Central"}, /* D (GMT-06:00) Central Time (US & Canada) */
-
- {"America/Indianapolis", "US Eastern"}, /* S (GMT-05:00) Indiana (East) */
- {"America/Bogota", "SA Pacific"}, /* S (GMT-05:00) Bogota, Lima, Quito */
- {"America/New_York", "Eastern"}, /* D (GMT-05:00) Eastern Time (US & Canada) */
-
- {"America/Caracas", "SA Western"}, /* S (GMT-04:00) Caracas, La Paz */
- {"America/Santiago", "Pacific SA"}, /* D (GMT-04:00) Santiago */
- {"America/Halifax", "Atlantic"}, /* D (GMT-04:00) Atlantic Time (Canada) */
- {"America/Manaus", "Central Brazilian"}, /* D (GMT-04:00 Manaus */
-
- {"America/St_Johns", "Newfoundland"}, /* D (GMT-03:30) Newfoundland */
-
- {"America/Buenos_Aires", "SA Eastern"}, /* S (GMT-03:00) Buenos Aires, Georgetown */
- {"America/Godthab", "Greenland"}, /* D (GMT-03:00) Greenland */
- {"America/Sao_Paulo", "E. South America"}, /* D (GMT-03:00) Brasilia */
- {"America/Montevideo", "Montevideo"}, /* S (GMT-03:00) Montevideo */
-
- {"America/Noronha", "Mid-Atlantic"}, /* D (GMT-02:00) Mid-Atlantic */
-
- {"Atlantic/Cape_Verde", "Cape Verde"}, /* S (GMT-01:00) Cape Verde Is. */
- {"Atlantic/Azores", "Azores"}, /* D (GMT-01:00) Azores */
-
- {"Africa/Casablanca", "Greenwich"}, /* S (GMT) Casablanca, Monrovia */
- {"Europe/London", "GMT"}, /* D (GMT) Greenwich Mean Time : Dublin, Edinburgh, Lisbon, London */
-
- {"Africa/Lagos", "W. Central Africa"}, /* S (GMT+01:00) West Central Africa */
- {"Europe/Berlin", "W. Europe"}, /* D (GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna */
- {"Europe/Paris", "Romance"}, /* D (GMT+01:00) Brussels, Copenhagen, Madrid, Paris */
- {"Eurpoe/Warsaw", "Central European"}, /* D (GMT+01:00) Sarajevo, Skopje, Warsaw, Zagreb */
- {"Europe/Sarajevo", "Central European"}, /* D (GMT+01:00) Sarajevo, Skopje, Warsaw, Zagreb */
- {"Europe/Prague", "Central Europe"}, /* D (GMT+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague */
- {"Europe/Belgrade", "Central Europe"}, /* D (GMT+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague */
-
- {"Africa/Johannesburg", "South Africa"}, /* S (GMT+02:00) Harare, Pretoria */
- {"Asia/Jerusalem", "Israel"}, /* S (GMT+02:00) Jerusalem */
- {"Europe/Istanbul", "GTB"}, /* D (GMT+02:00) Athens, Istanbul, Minsk */
- {"Europe/Helsinki", "FLE"}, /* D (GMT+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius */
- {"Africa/Cairo", "Egypt"}, /* D (GMT+02:00) Cairo */
- {"Europe/Minsk", "E. Europe"}, /* D (GMT+02:00) Bucharest */
- {"Europe/Bucharest", "E. Europe"}, /* D (GMT+02:00) Bucharest */
- {"Africa/Windhoek", "Namibia"}, /* S (GMT+02:00) Windhoek */
- {"Asia/Amman", "Jordan"}, /* S (GMT+02:00) Aman */
- {"Asia/Beirut", "Middle East"}, /* S (GMT+02:00) Beirut */
-
- {"Africa/Nairobi", "E. Africa"}, /* S (GMT+03:00) Nairobi */
- {"Asia/Riyadh", "Arab"}, /* S (GMT+03:00) Kuwait, Riyadh */
- {"Europe/Moscow", "Russian"}, /* D (GMT+03:00) Moscow, St. Petersburg, Volgograd */
- {"Asia/Baghdad", "Arabic"}, /* D (GMT+03:00) Baghdad */
-
- {"Asia/Tehran", "Iran"}, /* D (GMT+03:30) Tehran */
-
- {"Asia/Muscat", "Arabian"}, /* S (GMT+04:00) Abu Dhabi, Muscat */
- {"Asia/Tbilisi", "Georgian"}, /* D (GMT+04:00) Tbilisi */
- {"Asia/Baku", "Azerbaijan"}, /* S (GMT+04:00) Baku */
- {"Asia/Yerevan", "Caucasus"}, /* S (GMT+04:00) Yerevan */
- {"Asia/Kabul", "Afghanistan"}, /* S (GMT+04:30) Kabul */
-
- {"Asia/Karachi", "West Asia"}, /* S (GMT+05:00) Islamabad, Karachi, Tashkent */
- {"Asia/Yekaterinburg", "Ekaterinburg"}, /* D (GMT+05:00) Ekaterinburg */
-
- {"Asia/Calcutta", "India"}, /* S (GMT+05:30) Chennai, Kolkata, Mumbai, New Delhi */
-
- {"Asia/Katmandu", "Nepal"}, /* S (GMT+05:45) Kathmandu */
-
- {"Asia/Colombo", "Sri Lanka"}, /* S (GMT+06:00) Sri Jayawardenepura */
- {"Asia/Dhaka", "Central Asia"}, /* S (GMT+06:00) Astana, Dhaka */
- {"Asia/Novosibirsk", "N. Central Asia"}, /* D (GMT+06:00) Almaty, Novosibirsk */
-
- {"Asia/Rangoon", "Myanmar"}, /* S (GMT+06:30) Rangoon */
-
- {"Asia/Bangkok", "SE Asia"}, /* S (GMT+07:00) Bangkok, Hanoi, Jakarta */
- {"Asia/Krasnoyarsk", "North Asia"}, /* D (GMT+07:00) Krasnoyarsk */
-
- {"Australia/Perth", "W. Australia"}, /* S (GMT+08:00) Perth */
- {"Asia/Taipei", "Taipei"}, /* S (GMT+08:00) Taipei */
- {"Asia/Singapore", "Singapore"}, /* S (GMT+08:00) Kuala Lumpur, Singapore */
- {"Asia/Shanghai", "China"}, /* S (GMT+08:00) Beijing, Chongqing, Hong Kong, Urumqi */
- {"Asia/Hong_Kong", "China"}, /* S (GMT+08:00) Beijing, Chongqing, Hong Kong, Urumqi */
- {"Asia/Ulaanbaatar", "North Asia East"}, /* D (GMT+08:00) Irkutsk, Ulaan Bataar */
- {"Asia/Irkutsk", "North Asia East"}, /* D (GMT+08:00) Irkutsk, Ulaan Bataar */
-
- {"Asia/Tokyo", "Tokyo"}, /* S (GMT+09:00) Osaka, Sapporo, Tokyo */
- {"Asia/Seoul", "Korea"}, /* S (GMT+09:00) Seoul */
- {"Asia/Yakutsk", "Yakutsk"}, /* D (GMT+09:00) Yakutsk */
-
- {"Australia/Darwin", "AUS Central"}, /* S (GMT+09:30) Darwin */
- {"Australia/Adelaide", "Cen. Australia"}, /* D (GMT+09:30) Adelaide */
-
- {"Pacific/Guam", "West Pacific"}, /* S (GMT+10:00) Guam, Port Moresby */
- {"Australia/Brisbane", "E. Australia"}, /* S (GMT+10:00) Brisbane */
- {"Asia/Vladivostok", "Vladivostok"}, /* D (GMT+10:00) Vladivostok */
- {"Australia/Hobart", "Tasmania"}, /* D (GMT+10:00) Hobart */
- {"Australia/Sydney", "AUS Eastern"}, /* D (GMT+10:00) Canberra, Melbourne, Sydney */
-
- {"Asia/Guadalcanal", "Central Pacific"}, /* S (GMT+11:00) Magadan, Solomon Is., New Caledonia */
- {"Asia/Magadan", "Central Pacific"}, /* S (GMT+11:00) Magadan, Solomon Is., New Caledonia */
-
- {"Pacific/Fiji", "Fiji"}, /* S (GMT+12:00) Fiji, Kamchatka, Marshall Is. */
- {"Pacific/Auckland", "New Zealand"}, /* D (GMT+12:00) Auckland, Wellington */
-
- {"Pacific/Tongatapu", "Tonga"}, /* S (GMT+13:00) Nuku'alofa */
- NULL, NULL
-};
-
-/**
- * If a lookup fails, we attempt to remap certain Windows ids to
- * alternate Windows ids. If the alternate listed here begins with
- * '-', we use it as is (without the '-'). If it begins with '+', we
- * append a " Standard Time" if appropriate.
- */
-static const WindowsZoneRemap ZONE_REMAP[] = {
- "Central European", "-Warsaw",
- "Central Europe", "-Prague Bratislava",
- "China", "-Beijing",
-
- "Greenwich", "+GMT",
- "GTB", "+GFT",
- "Arab", "+Saudi Arabia",
- "SE Asia", "+Bangkok",
- "AUS Eastern", "+Sydney",
- "Mountain Standard Time (Mexico)", "-Mexico Standard Time 2",
- "Central Standard Time (Mexico)", "+Mexico",
- NULL, NULL,
-};
-
-static int32_t fWinType = -1;
+static int32_t gWinType = 0;
static int32_t detectWindowsType()
{
@@ -356,7 +101,7 @@
really want to know is how the registry is laid out.
Specifically, is it 9x/Me or not, and is it "GMT" or "GMT
Standard Time". */
- for (winType = 0; winType < 2; winType += 1) {
+ for (winType = 0; winType < 2; winType++) {
result = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
WIN_TYPE_PROBE_REGKEY[winType],
0,
@@ -369,65 +114,30 @@
}
}
- return winType;
-}
-
-/*
- * TODO: Binary search sorted ZONE_MAP...
- * (u_detectWindowsTimeZone() needs them sorted by offset...)
- */
-static const char *findWindowsZoneID(const UChar *icuid, int32_t length)
-{
- char stackBuffer[ICUID_STACK_BUFFER_SIZE];
- char *buffer = stackBuffer;
- const char *result = NULL;
- int i;
-
- /*
- * NOTE: >= because length doesn't include
- * trailing null.
- */
- if (length >= ICUID_STACK_BUFFER_SIZE) {
- buffer = NEW_ARRAY(char, length + 1);
- }
-
- u_UCharsToChars(icuid, buffer, length);
- buffer[length] = '\0';
-
- for (i = 0; ZONE_MAP[i].icuid != NULL; i += 1) {
- if (uprv_strcmp(buffer, ZONE_MAP[i].icuid) == 0) {
- result = ZONE_MAP[i].winid;
- break;
- }
- }
-
- if (buffer != stackBuffer) {
- DELETE_ARRAY(buffer);
- }
-
- return result;
+ return winType+1; /* +1 to bring it inline with the enum */
}
static LONG openTZRegKey(HKEY *hkey, const char *winid)
{
- char subKeyName[96]; /* TODO: why 96?? */
+ char subKeyName[110]; /* TODO: why 96?? */
char *name;
LONG result;
- /* TODO: This isn't thread safe, but it's probably good enough. */
- if (fWinType < 0) {
- fWinType = detectWindowsType();
+ /* This isn't thread safe, but it's good enough because the result should be constant per system. */
+ if (gWinType <= 0) {
+ gWinType = detectWindowsType();
}
- uprv_strcpy(subKeyName, TZ_REGKEY[(fWinType == WIN_9X_ME_TYPE) ? 0 : 1]);
+ uprv_strcpy(subKeyName, TZ_REGKEY[(gWinType != WIN_9X_ME_TYPE)]);
name = &subKeyName[strlen(subKeyName)];
uprv_strcat(subKeyName, winid);
- if (fWinType != WIN_9X_ME_TYPE &&
- (winid[strlen(winid) - 1] != '2') &&
- (winid[strlen(winid) - 1] != ')') &&
- !(fWinType == WIN_NT_TYPE && strcmp(winid, "GMT") == 0)) {
- uprv_strcat(subKeyName, STANDARD_TIME_REGKEY);
+ if (gWinType == WIN_9X_ME_TYPE) {
+ /* Remove " Standard Time" */
+ char *pStd = uprv_strstr(subKeyName, STANDARD_TIME_REGKEY);
+ if (pStd) {
+ *pStd = 0;
+ }
}
result = RegOpenKeyExA(HKEY_LOCAL_MACHINE,
@@ -435,27 +145,6 @@
0,
KEY_QUERY_VALUE,
hkey);
-
- if (result != ERROR_SUCCESS) {
- int i;
-
- /* If the primary lookup fails, try to remap the Windows zone
- ID, according to the remapping table. */
- for (i=0; ZONE_REMAP[i].winid; i++) {
- if (uprv_strcmp(winid, ZONE_REMAP[i].winid) == 0) {
- uprv_strcpy(name, ZONE_REMAP[i].altwinid + 1);
- if (*(ZONE_REMAP[i].altwinid) == '+' && fWinType != WIN_9X_ME_TYPE) {
- uprv_strcat(subKeyName, STANDARD_TIME_REGKEY);
- }
- return RegOpenKeyExA(HKEY_LOCAL_MACHINE,
- subKeyName,
- 0,
- KEY_QUERY_VALUE,
- hkey);
- }
- }
- }
-
return result;
}
@@ -482,32 +171,31 @@
return result;
}
-U_CAPI UBool U_EXPORT2
-uprv_getWindowsTimeZoneInfo(TIME_ZONE_INFORMATION *zoneInfo, const UChar *icuid, int32_t length)
-{
- const char *winid;
- TZI tzi;
+static LONG getSTDName(const char *winid, char *regStdName, int32_t length) {
+ DWORD cbData = length;
LONG result;
-
- winid = findWindowsZoneID(icuid, length);
+ HKEY hkey;
- if (winid != NULL) {
- result = getTZI(winid, &tzi);
+ result = openTZRegKey(&hkey, winid);
- if (result == ERROR_SUCCESS) {
- zoneInfo->Bias = tzi.bias;
- zoneInfo->DaylightBias = tzi.daylightBias;
- zoneInfo->StandardBias = tzi.standardBias;
- zoneInfo->DaylightDate = tzi.daylightDate;
- zoneInfo->StandardDate = tzi.standardDate;
+ if (result == ERROR_SUCCESS) {
+ result = RegQueryValueExA(hkey,
+ STD_REGKEY,
+ NULL,
+ NULL,
+ (LPBYTE)regStdName,
+ &cbData);
- return TRUE;
- }
}
- return FALSE;
+ RegCloseKey(hkey);
+
+ return result;
}
+
+
+
/*
This code attempts to detect the Windows time zone, as set in the
Windows Date and Time control panel. It attempts to work on
@@ -562,13 +250,22 @@
*/
U_CFUNC const char* U_EXPORT2
uprv_detectWindowsTimeZone() {
+ UErrorCode status = U_ZERO_ERROR;
+ UResourceBundle* bundle = NULL;
+ char* icuid = NULL;
+ UChar apiStd[MAX_LENGTH_ID];
+ char apiStdName[MAX_LENGTH_ID];
+ char regStdName[MAX_LENGTH_ID];
+ char tmpid[MAX_LENGTH_ID];
+ int32_t len;
+ int id;
+ int errorCode;
+ char ISOcode[3]; /* 2 letter iso code */
+
LONG result;
- HKEY hkey;
TZI tziKey;
TZI tziReg;
TIME_ZONE_INFORMATION apiTZI;
- int firstMatch, lastMatch;
- int j;
/* Obtain TIME_ZONE_INFORMATION from the API, and then convert it
to TZI. We could also interrogate the registry directly; we do
@@ -583,24 +280,30 @@
uprv_memcpy((char *)&tziKey.daylightDate, (char*)&apiTZI.DaylightDate,
sizeof(apiTZI.DaylightDate));
- /* For each zone that can be identified by Offset+Rules, see if we
- have a match. Continue scanning after finding a match,
- recording the index of the first and the last match. We have
- to do this because some zones are not unique under
- Offset+Rules. */
- firstMatch = -1;
- lastMatch = -1;
- for (j=0; ZONE_MAP[j].icuid; j++) {
- result = getTZI(ZONE_MAP[j].winid, &tziReg);
+ /* Convert the wchar_t* standard name to char* */
+ uprv_memset(apiStdName, 0, sizeof(apiStdName));
+ WideCharToMultiByte(CP_ACP,0, apiTZI.StandardName, -1, apiStdName, MAX_LENGTH_ID, NULL, NULL);
+
+ tmpid[0] = 0;
+
+ id = GetUserGeoID(GEOCLASS_NATION);
+ errorCode = GetGeoInfo(id,GEO_ISO2,ISOcode,3,0);
+
+ bundle = ures_openDirect(NULL, "windowsZones", &status);
+ ures_getByKey(bundle, "mapTimezones", bundle, &status);
+
+ /* Note: We get the winid not from static tables but from resource bundle. */
+ while (U_SUCCESS(status) && ures_hasNext(bundle)) {
+ UBool idFound = FALSE;
+ const char* winid;
+ UResourceBundle* winTZ = ures_getNextResource(bundle, NULL, &status);
+ if (U_FAILURE(status)) {
+ break;
+ }
+ winid = ures_getKey(winTZ);
+ result = getTZI(winid, &tziReg);
if (result == ERROR_SUCCESS) {
- /* Assume that offsets are grouped together, and bail out
- when we've scanned everything with a matching
- offset. */
- if (firstMatch >= 0 && tziKey.bias != tziReg.bias) {
- break;
- }
-
/* Windows alters the DaylightBias in some situations.
Using the bias and the rules suffices, so overwrite
these unreliable fields. */
@@ -608,81 +311,63 @@
tziKey.daylightBias = tziReg.daylightBias;
if (uprv_memcmp((char *)&tziKey, (char*)&tziReg, sizeof(tziKey)) == 0) {
- if (firstMatch < 0) {
- firstMatch = j;
+ const UChar* icuTZ = NULL;
+ if (errorCode != 0) {
+ icuTZ = ures_getStringByKey(winTZ, ISOcode, &len, &status);
+ }
+ if (errorCode==0 || icuTZ==NULL) {
+ /* fallback to default "001" and reset status */
+ status = U_ZERO_ERROR;
+ icuTZ = ures_getStringByKey(winTZ, "001", &len, &status);
}
- lastMatch = j;
+ if (U_SUCCESS(status)) {
+ /* Get the standard name from the registry key to compare with
+ the one from Windows API call. */
+ uprv_memset(regStdName, 0, sizeof(regStdName));
+ result = getSTDName(winid, regStdName, sizeof(regStdName));
+ if (result == ERROR_SUCCESS) {
+ if (uprv_strcmp(apiStdName, regStdName) == 0) {
+ idFound = TRUE;
+ }
+ }
+
+ /* tmpid buffer holds the ICU timezone ID corresponding to the timezone ID from Windows.
+ * If none is found, tmpid buffer will contain a fallback ID (i.e. the time zone ID matching
+ * the current time zone information)
+ */
+ if (idFound || tmpid[0] == 0) {
+ /* if icuTZ has more than one city, take only the first (i.e. terminate icuTZ at first space) */
+ int index=0;
+ while (! (*icuTZ == '\0' || *icuTZ ==' ')) {
+ tmpid[index++]=*icuTZ++;
+ }
+ tmpid[index]='\0';
+ }
+ }
}
}
+ ures_close(winTZ);
+ if (idFound) {
+ break;
+ }
}
- /* This should never happen; if it does it means our table doesn't
- match Windows AT ALL, perhaps because this is post-XP? */
- if (firstMatch < 0) {
- return NULL;
+ /*
+ * Copy the timezone ID to icuid to be returned.
+ */
+ if (tmpid[0] != 0) {
+ len = uprv_strlen(tmpid);
+ icuid = (char*)uprv_malloc((len + 1) * sizeof(char));
+ uprv_memset(icuid, 0, len + 1);
+ if (icuid != NULL) {
+ uprv_strcpy(icuid, tmpid);
+ }
}
+
+ ures_close(bundle);
- if (firstMatch != lastMatch) {
- char stdName[32];
- DWORD stdNameSize;
- char stdRegName[64];
- DWORD stdRegNameSize;
-
- /* Offset+Rules lookup yielded >= 2 matches. Try to match the
- localized display name. Get the name from the registry
- (not the API). This avoids conversion issues. Use the
- standard name, since Windows modifies the daylight name to
- match the standard name if there is no DST. */
- if (RegOpenKeyExA(HKEY_LOCAL_MACHINE,
- CURRENT_ZONE_REGKEY,
- 0,
- KEY_QUERY_VALUE,
- &hkey) == ERROR_SUCCESS)
- {
- stdNameSize = sizeof(stdName);
- result = RegQueryValueExA(hkey,
- STANDARD_NAME_REGKEY,
- NULL,
- NULL,
- (LPBYTE)stdName,
- &stdNameSize);
- RegCloseKey(hkey);
-
- /*
- * Scan through the Windows time zone data in the registry
- * again (just the range of zones with matching TZIs) and
- * look for a standard display name match.
- */
- for (j = firstMatch; j <= lastMatch; j += 1) {
- stdRegNameSize = sizeof(stdRegName);
- result = openTZRegKey(&hkey, ZONE_MAP[j].winid);
-
- if (result == ERROR_SUCCESS) {
- result = RegQueryValueExA(hkey,
- STD_REGKEY,
- NULL,
- NULL,
- (LPBYTE)stdRegName,
- &stdRegNameSize);
- }
-
- RegCloseKey(hkey);
-
- if (result == ERROR_SUCCESS &&
- stdRegNameSize == stdNameSize &&
- uprv_memcmp(stdName, stdRegName, stdNameSize) == 0)
- {
- firstMatch = j; /* record the match */
- break;
- }
- }
- } else {
- RegCloseKey(hkey); /* should never get here */
- }
- }
-
- return ZONE_MAP[firstMatch].icuid;
+ return icuid;
}
-#endif /* #ifdef U_WINDOWS */
+#endif
diff --git a/source/common/wintz.h b/source/common/wintz.h
index 0704953..8a790a1 100644
--- a/source/common/wintz.h
+++ b/source/common/wintz.h
@@ -1,6 +1,6 @@
/*
********************************************************************************
-* Copyright (C) 2005-2007, International Business Machines
+* Copyright (C) 2005-2012, International Business Machines
* Corporation and others. All Rights Reserved.
********************************************************************************
*
@@ -26,9 +26,6 @@
typedef struct _TIME_ZONE_INFORMATION TIME_ZONE_INFORMATION;
U_CDECL_END
-U_CAPI UBool U_EXPORT2
-uprv_getWindowsTimeZoneInfo(TIME_ZONE_INFORMATION *zoneInfo, const UChar *icuid, int32_t length);
-
U_CFUNC const char* U_EXPORT2
uprv_detectWindowsTimeZone();
diff --git a/source/data/misc/miscfiles.mk b/source/data/misc/miscfiles.mk
index e7b56ab..9647c68 100644
--- a/source/data/misc/miscfiles.mk
+++ b/source/data/misc/miscfiles.mk
@@ -1,4 +1,4 @@
-# * Copyright (C) 2003-2007, International Business Machines
+# * Copyright (C) 2003-2012, International Business Machines
# * Corporation and others. All Rights Reserved.
# A list of txt's to build
# Note:
@@ -23,4 +23,4 @@
#
MISC_SOURCE = \
-zoneinfo.txt supplementalData.txt metazoneInfo.txt
+zoneinfo.txt supplementalData.txt metazoneInfo.txt windowsZones.txt
diff --git a/source/data/misc/windowsZones.txt b/source/data/misc/windowsZones.txt
new file mode 100644
index 0000000..5235943
--- /dev/null
+++ b/source/data/misc/windowsZones.txt
@@ -0,0 +1,678 @@
+// ***************************************************************************
+// *
+// * Copyright (C) 2012 International Business Machines
+// * Corporation and others. All Rights Reserved.
+// * Tool: org.unicode.cldr.icu.NewLdml2IcuConverter
+// * Source File: <path>/windowsZones.xml
+// *
+// ***************************************************************************
+windowsZones:table(nofallback){
+ mapTimezones{
+ "AUS Central Standard Time"{
+ 001{"Australia/Darwin"}
+ AU{"Australia/Darwin"}
+ }
+ "AUS Eastern Standard Time"{
+ 001{"Australia/Sydney"}
+ AU{"Australia/Sydney Australia/Melbourne"}
+ }
+ "Afghanistan Standard Time"{
+ 001{"Asia/Kabul"}
+ AF{"Asia/Kabul"}
+ }
+ "Alaskan Standard Time"{
+ 001{"America/Anchorage"}
+ US{
+ "America/Anchorage America/Juneau America/Nome America/Sitka America/"
+ "Yakutat"
+ }
+ }
+ "Arab Standard Time"{
+ 001{"Asia/Riyadh"}
+ BH{"Asia/Bahrain"}
+ KW{"Asia/Kuwait"}
+ QA{"Asia/Qatar"}
+ SA{"Asia/Riyadh"}
+ YE{"Asia/Aden"}
+ }
+ "Arabian Standard Time"{
+ 001{"Asia/Dubai"}
+ AE{"Asia/Dubai"}
+ OM{"Asia/Muscat"}
+ ZZ{"Etc/GMT-4"}
+ }
+ "Arabic Standard Time"{
+ 001{"Asia/Baghdad"}
+ IQ{"Asia/Baghdad"}
+ }
+ "Argentina Standard Time"{
+ 001{"America/Buenos_Aires"}
+ AR{
+ "America/Buenos_Aires America/Argentina/La_Rioja America/Argentina/Ri"
+ "o_Gallegos America/Argentina/Salta America/Argentina/San_Juan Americ"
+ "a/Argentina/San_Luis America/Argentina/Tucuman America/Argentina/Ush"
+ "uaia America/Catamarca America/Cordoba America/Jujuy America/Mendoza"
+ }
+ }
+ "Atlantic Standard Time"{
+ 001{"America/Halifax"}
+ BM{"Atlantic/Bermuda"}
+ CA{"America/Halifax America/Glace_Bay America/Goose_Bay America/Moncton"}
+ GL{"America/Thule"}
+ }
+ "Azerbaijan Standard Time"{
+ 001{"Asia/Baku"}
+ AZ{"Asia/Baku"}
+ }
+ "Azores Standard Time"{
+ 001{"Atlantic/Azores"}
+ GL{"America/Scoresbysund"}
+ PT{"Atlantic/Azores"}
+ }
+ "Bahia Standard Time"{
+ 001{"America/Bahia"}
+ BR{"America/Bahia"}
+ }
+ "Bangladesh Standard Time"{
+ 001{"Asia/Dhaka"}
+ BD{"Asia/Dhaka"}
+ BT{"Asia/Thimphu"}
+ }
+ "Canada Central Standard Time"{
+ 001{"America/Regina"}
+ CA{"America/Regina America/Swift_Current"}
+ }
+ "Cape Verde Standard Time"{
+ 001{"Atlantic/Cape_Verde"}
+ CV{"Atlantic/Cape_Verde"}
+ ZZ{"Etc/GMT+1"}
+ }
+ "Caucasus Standard Time"{
+ 001{"Asia/Yerevan"}
+ AM{"Asia/Yerevan"}
+ }
+ "Cen. Australia Standard Time"{
+ 001{"Australia/Adelaide"}
+ AU{"Australia/Adelaide Australia/Broken_Hill"}
+ }
+ "Central America Standard Time"{
+ 001{"America/Guatemala"}
+ BZ{"America/Belize"}
+ CR{"America/Costa_Rica"}
+ EC{"Pacific/Galapagos"}
+ GT{"America/Guatemala"}
+ HN{"America/Tegucigalpa"}
+ NI{"America/Managua"}
+ SV{"America/El_Salvador"}
+ ZZ{"Etc/GMT+6"}
+ }
+ "Central Asia Standard Time"{
+ 001{"Asia/Almaty"}
+ AQ{"Antarctica/Vostok"}
+ IO{"Indian/Chagos"}
+ KG{"Asia/Bishkek"}
+ KZ{"Asia/Almaty Asia/Qyzylorda"}
+ ZZ{"Etc/GMT-6"}
+ }
+ "Central Brazilian Standard Time"{
+ 001{"America/Cuiaba"}
+ BR{"America/Cuiaba America/Campo_Grande"}
+ }
+ "Central Europe Standard Time"{
+ 001{"Europe/Budapest"}
+ AL{"Europe/Tirane"}
+ CZ{"Europe/Prague"}
+ HU{"Europe/Budapest"}
+ ME{"Europe/Podgorica"}
+ RS{"Europe/Belgrade"}
+ SI{"Europe/Ljubljana"}
+ SK{"Europe/Bratislava"}
+ }
+ "Central European Standard Time"{
+ 001{"Europe/Warsaw"}
+ BA{"Europe/Sarajevo"}
+ HR{"Europe/Zagreb"}
+ MK{"Europe/Skopje"}
+ PL{"Europe/Warsaw"}
+ }
+ "Central Pacific Standard Time"{
+ 001{"Pacific/Guadalcanal"}
+ AQ{"Antarctica/Macquarie"}
+ FM{"Pacific/Ponape Pacific/Kosrae"}
+ NC{"Pacific/Noumea"}
+ SB{"Pacific/Guadalcanal"}
+ VU{"Pacific/Efate"}
+ ZZ{"Etc/GMT-11"}
+ }
+ "Central Standard Time (Mexico)"{
+ 001{"America/Mexico_City"}
+ MX{
+ "America/Mexico_City America/Bahia_Banderas America/Cancun America/Me"
+ "rida America/Monterrey"
+ }
+ }
+ "Central Standard Time"{
+ 001{"America/Chicago"}
+ CA{
+ "America/Winnipeg America/Rainy_River America/Rankin_Inlet America/Re"
+ "solute"
+ }
+ MX{"America/Matamoros"}
+ US{
+ "America/Chicago America/Indiana/Knox America/Indiana/Tell_City Ameri"
+ "ca/Menominee America/North_Dakota/Beulah America/North_Dakota/Center"
+ " America/North_Dakota/New_Salem"
+ }
+ ZZ{"CST6CDT"}
+ }
+ "China Standard Time"{
+ 001{"Asia/Shanghai"}
+ CN{"Asia/Shanghai Asia/Chongqing Asia/Harbin Asia/Kashgar Asia/Urumqi"}
+ HK{"Asia/Hong_Kong"}
+ MO{"Asia/Macau"}
+ }
+ "Dateline Standard Time"{
+ 001{"Etc/GMT+12"}
+ ZZ{"Etc/GMT+12"}
+ }
+ "E. Africa Standard Time"{
+ 001{"Africa/Nairobi"}
+ AQ{"Antarctica/Syowa"}
+ DJ{"Africa/Djibouti"}
+ ER{"Africa/Asmera"}
+ ET{"Africa/Addis_Ababa"}
+ KE{"Africa/Nairobi"}
+ KM{"Indian/Comoro"}
+ MG{"Indian/Antananarivo"}
+ SD{"Africa/Khartoum"}
+ SO{"Africa/Mogadishu"}
+ SS{"Africa/Juba"}
+ TZ{"Africa/Dar_es_Salaam"}
+ UG{"Africa/Kampala"}
+ YT{"Indian/Mayotte"}
+ ZZ{"Etc/GMT-3"}
+ }
+ "E. Australia Standard Time"{
+ 001{"Australia/Brisbane"}
+ AU{"Australia/Brisbane Australia/Lindeman"}
+ }
+ "E. Europe Standard Time"{
+ 001{"Asia/Nicosia"}
+ CY{"Asia/Nicosia"}
+ }
+ "E. South America Standard Time"{
+ 001{"America/Sao_Paulo"}
+ BR{"America/Sao_Paulo"}
+ }
+ "Eastern Standard Time"{
+ 001{"America/New_York"}
+ BS{"America/Nassau"}
+ CA{
+ "America/Toronto America/Iqaluit America/Montreal America/Nipigon Ame"
+ "rica/Pangnirtung America/Thunder_Bay"
+ }
+ TC{"America/Grand_Turk"}
+ US{
+ "America/New_York America/Detroit America/Indiana/Petersburg America/"
+ "Indiana/Vincennes America/Indiana/Winamac America/Kentucky/Monticell"
+ "o America/Louisville"
+ }
+ ZZ{"EST5EDT"}
+ }
+ "Egypt Standard Time"{
+ 001{"Africa/Cairo"}
+ EG{"Africa/Cairo"}
+ PS{"Asia/Gaza Asia/Hebron"}
+ }
+ "Ekaterinburg Standard Time"{
+ 001{"Asia/Yekaterinburg"}
+ RU{"Asia/Yekaterinburg"}
+ }
+ "FLE Standard Time"{
+ 001{"Europe/Kiev"}
+ AX{"Europe/Mariehamn"}
+ BG{"Europe/Sofia"}
+ EE{"Europe/Tallinn"}
+ FI{"Europe/Helsinki"}
+ LT{"Europe/Vilnius"}
+ LV{"Europe/Riga"}
+ UA{"Europe/Kiev Europe/Simferopol Europe/Uzhgorod Europe/Zaporozhye"}
+ }
+ "Fiji Standard Time"{
+ 001{"Pacific/Fiji"}
+ FJ{"Pacific/Fiji"}
+ }
+ "GMT Standard Time"{
+ 001{"Europe/London"}
+ ES{"Atlantic/Canary"}
+ FO{"Atlantic/Faeroe"}
+ GB{"Europe/London"}
+ GG{"Europe/Guernsey"}
+ IE{"Europe/Dublin"}
+ IM{"Europe/Isle_of_Man"}
+ JE{"Europe/Jersey"}
+ PT{"Europe/Lisbon Atlantic/Madeira"}
+ }
+ "GTB Standard Time"{
+ 001{"Europe/Bucharest"}
+ GR{"Europe/Athens"}
+ MD{"Europe/Chisinau"}
+ RO{"Europe/Bucharest"}
+ }
+ "Georgian Standard Time"{
+ 001{"Asia/Tbilisi"}
+ GE{"Asia/Tbilisi"}
+ }
+ "Greenland Standard Time"{
+ 001{"America/Godthab"}
+ GL{"America/Godthab"}
+ }
+ "Greenwich Standard Time"{
+ 001{"Atlantic/Reykjavik"}
+ BF{"Africa/Ouagadougou"}
+ CI{"Africa/Abidjan"}
+ EH{"Africa/El_Aaiun"}
+ GH{"Africa/Accra"}
+ GM{"Africa/Banjul"}
+ GN{"Africa/Conakry"}
+ GW{"Africa/Bissau"}
+ IS{"Atlantic/Reykjavik"}
+ LR{"Africa/Monrovia"}
+ ML{"Africa/Bamako"}
+ MR{"Africa/Nouakchott"}
+ SH{"Atlantic/St_Helena"}
+ SL{"Africa/Freetown"}
+ SN{"Africa/Dakar"}
+ ST{"Africa/Sao_Tome"}
+ TG{"Africa/Lome"}
+ }
+ "Hawaiian Standard Time"{
+ 001{"Pacific/Honolulu"}
+ CK{"Pacific/Rarotonga"}
+ PF{"Pacific/Tahiti"}
+ UM{"Pacific/Johnston"}
+ US{"Pacific/Honolulu"}
+ ZZ{"Etc/GMT+10"}
+ }
+ "India Standard Time"{
+ 001{"Asia/Calcutta"}
+ IN{"Asia/Calcutta"}
+ }
+ "Iran Standard Time"{
+ 001{"Asia/Tehran"}
+ IR{"Asia/Tehran"}
+ }
+ "Israel Standard Time"{
+ 001{"Asia/Jerusalem"}
+ IL{"Asia/Jerusalem"}
+ }
+ "Jordan Standard Time"{
+ 001{"Asia/Amman"}
+ JO{"Asia/Amman"}
+ }
+ "Kaliningrad Standard Time"{
+ 001{"Europe/Kaliningrad"}
+ BY{"Europe/Minsk"}
+ RU{"Europe/Kaliningrad"}
+ }
+ "Korea Standard Time"{
+ 001{"Asia/Seoul"}
+ KP{"Asia/Pyongyang"}
+ KR{"Asia/Seoul"}
+ }
+ "Magadan Standard Time"{
+ 001{"Asia/Magadan"}
+ RU{"Asia/Magadan Asia/Anadyr Asia/Kamchatka"}
+ }
+ "Mauritius Standard Time"{
+ 001{"Indian/Mauritius"}
+ MU{"Indian/Mauritius"}
+ RE{"Indian/Reunion"}
+ SC{"Indian/Mahe"}
+ }
+ "Middle East Standard Time"{
+ 001{"Asia/Beirut"}
+ LB{"Asia/Beirut"}
+ }
+ "Montevideo Standard Time"{
+ 001{"America/Montevideo"}
+ UY{"America/Montevideo"}
+ }
+ "Morocco Standard Time"{
+ 001{"Africa/Casablanca"}
+ MA{"Africa/Casablanca"}
+ }
+ "Mountain Standard Time (Mexico)"{
+ 001{"America/Chihuahua"}
+ MX{"America/Chihuahua America/Mazatlan"}
+ }
+ "Mountain Standard Time"{
+ 001{"America/Denver"}
+ CA{
+ "America/Edmonton America/Cambridge_Bay America/Inuvik America/Yellow"
+ "knife"
+ }
+ MX{"America/Ojinaga"}
+ US{"America/Denver America/Boise America/Shiprock"}
+ ZZ{"MST7MDT"}
+ }
+ "Myanmar Standard Time"{
+ 001{"Asia/Rangoon"}
+ CC{"Indian/Cocos"}
+ MM{"Asia/Rangoon"}
+ }
+ "N. Central Asia Standard Time"{
+ 001{"Asia/Novosibirsk"}
+ RU{"Asia/Novosibirsk Asia/Novokuznetsk Asia/Omsk"}
+ }
+ "Namibia Standard Time"{
+ 001{"Africa/Windhoek"}
+ NA{"Africa/Windhoek"}
+ }
+ "Nepal Standard Time"{
+ 001{"Asia/Katmandu"}
+ NP{"Asia/Katmandu"}
+ }
+ "New Zealand Standard Time"{
+ 001{"Pacific/Auckland"}
+ AQ{"Antarctica/South_Pole Antarctica/McMurdo"}
+ NZ{"Pacific/Auckland"}
+ }
+ "Newfoundland Standard Time"{
+ 001{"America/St_Johns"}
+ CA{"America/St_Johns"}
+ }
+ "North Asia East Standard Time"{
+ 001{"Asia/Irkutsk"}
+ RU{"Asia/Irkutsk"}
+ }
+ "North Asia Standard Time"{
+ 001{"Asia/Krasnoyarsk"}
+ RU{"Asia/Krasnoyarsk"}
+ }
+ "Pacific SA Standard Time"{
+ 001{"America/Santiago"}
+ AQ{"Antarctica/Palmer"}
+ CL{"America/Santiago"}
+ }
+ "Pacific Standard Time (Mexico)"{
+ 001{"America/Santa_Isabel"}
+ MX{"America/Santa_Isabel"}
+ }
+ "Pacific Standard Time"{
+ 001{"America/Los_Angeles"}
+ CA{"America/Vancouver America/Dawson America/Whitehorse"}
+ MX{"America/Tijuana"}
+ US{"America/Los_Angeles"}
+ ZZ{"PST8PDT"}
+ }
+ "Pakistan Standard Time"{
+ 001{"Asia/Karachi"}
+ PK{"Asia/Karachi"}
+ }
+ "Paraguay Standard Time"{
+ 001{"America/Asuncion"}
+ PY{"America/Asuncion"}
+ }
+ "Romance Standard Time"{
+ 001{"Europe/Paris"}
+ BE{"Europe/Brussels"}
+ DK{"Europe/Copenhagen"}
+ ES{"Europe/Madrid Africa/Ceuta"}
+ FR{"Europe/Paris"}
+ }
+ "Russian Standard Time"{
+ 001{"Europe/Moscow"}
+ RU{"Europe/Moscow Europe/Samara Europe/Volgograd"}
+ }
+ "SA Eastern Standard Time"{
+ 001{"America/Cayenne"}
+ AQ{"Antarctica/Rothera"}
+ BR{
+ "America/Fortaleza America/Araguaina America/Belem America/Maceio Ame"
+ "rica/Recife America/Santarem"
+ }
+ FK{"Atlantic/Stanley"}
+ GF{"America/Cayenne"}
+ SR{"America/Paramaribo"}
+ ZZ{"Etc/GMT+3"}
+ }
+ "SA Pacific Standard Time"{
+ 001{"America/Bogota"}
+ CA{"America/Coral_Harbour"}
+ CO{"America/Bogota"}
+ EC{"America/Guayaquil"}
+ HT{"America/Port-au-Prince"}
+ JM{"America/Jamaica"}
+ KY{"America/Cayman"}
+ PA{"America/Panama"}
+ PE{"America/Lima"}
+ ZZ{"Etc/GMT+5"}
+ }
+ "SA Western Standard Time"{
+ 001{"America/La_Paz"}
+ AG{"America/Antigua"}
+ AI{"America/Anguilla"}
+ AW{"America/Aruba"}
+ BB{"America/Barbados"}
+ BL{"America/St_Barthelemy"}
+ BO{"America/La_Paz"}
+ BQ{"America/Kralendijk"}
+ BR{
+ "America/Manaus America/Boa_Vista America/Eirunepe America/Porto_Velh"
+ "o America/Rio_Branco"
+ }
+ CA{"America/Blanc-Sablon"}
+ CW{"America/Curacao"}
+ DM{"America/Dominica"}
+ DO{"America/Santo_Domingo"}
+ GD{"America/Grenada"}
+ GP{"America/Guadeloupe"}
+ GY{"America/Guyana"}
+ KN{"America/St_Kitts"}
+ LC{"America/St_Lucia"}
+ MF{"America/Marigot"}
+ MQ{"America/Martinique"}
+ MS{"America/Montserrat"}
+ PR{"America/Puerto_Rico"}
+ SX{"America/Lower_Princes"}
+ TT{"America/Port_of_Spain"}
+ VC{"America/St_Vincent"}
+ VG{"America/Tortola"}
+ VI{"America/St_Thomas"}
+ ZZ{"Etc/GMT+4"}
+ }
+ "SE Asia Standard Time"{
+ 001{"Asia/Bangkok"}
+ AQ{"Antarctica/Davis"}
+ CX{"Indian/Christmas"}
+ ID{"Asia/Jakarta Asia/Pontianak"}
+ KH{"Asia/Phnom_Penh"}
+ LA{"Asia/Vientiane"}
+ MN{"Asia/Hovd"}
+ TH{"Asia/Bangkok"}
+ VN{"Asia/Saigon"}
+ ZZ{"Etc/GMT-7"}
+ }
+ "Samoa Standard Time"{
+ 001{"Pacific/Apia"}
+ WS{"Pacific/Apia"}
+ }
+ "Singapore Standard Time"{
+ 001{"Asia/Singapore"}
+ BN{"Asia/Brunei"}
+ ID{"Asia/Makassar"}
+ MY{"Asia/Kuala_Lumpur Asia/Kuching"}
+ PH{"Asia/Manila"}
+ SG{"Asia/Singapore"}
+ ZZ{"Etc/GMT-8"}
+ }
+ "South Africa Standard Time"{
+ 001{"Africa/Johannesburg"}
+ BI{"Africa/Bujumbura"}
+ BW{"Africa/Gaborone"}
+ CD{"Africa/Lubumbashi"}
+ LS{"Africa/Maseru"}
+ LY{"Africa/Tripoli"}
+ MW{"Africa/Blantyre"}
+ MZ{"Africa/Maputo"}
+ RW{"Africa/Kigali"}
+ SZ{"Africa/Mbabane"}
+ ZA{"Africa/Johannesburg"}
+ ZM{"Africa/Lusaka"}
+ ZW{"Africa/Harare"}
+ ZZ{"Etc/GMT-2"}
+ }
+ "Sri Lanka Standard Time"{
+ 001{"Asia/Colombo"}
+ LK{"Asia/Colombo"}
+ }
+ "Syria Standard Time"{
+ 001{"Asia/Damascus"}
+ SY{"Asia/Damascus"}
+ }
+ "Taipei Standard Time"{
+ 001{"Asia/Taipei"}
+ TW{"Asia/Taipei"}
+ }
+ "Tasmania Standard Time"{
+ 001{"Australia/Hobart"}
+ AU{"Australia/Hobart Australia/Currie"}
+ }
+ "Tokyo Standard Time"{
+ 001{"Asia/Tokyo"}
+ ID{"Asia/Jayapura"}
+ JP{"Asia/Tokyo"}
+ PW{"Pacific/Palau"}
+ TL{"Asia/Dili"}
+ ZZ{"Etc/GMT-9"}
+ }
+ "Tonga Standard Time"{
+ 001{"Pacific/Tongatapu"}
+ KI{"Pacific/Enderbury"}
+ TK{"Pacific/Fakaofo"}
+ TO{"Pacific/Tongatapu"}
+ ZZ{"Etc/GMT-13"}
+ }
+ "Turkey Standard Time"{
+ 001{"Europe/Istanbul"}
+ TR{"Europe/Istanbul"}
+ }
+ "US Eastern Standard Time"{
+ 001{"America/Indianapolis"}
+ US{"America/Indianapolis America/Indiana/Marengo America/Indiana/Vevay"}
+ }
+ "US Mountain Standard Time"{
+ 001{"America/Phoenix"}
+ CA{"America/Dawson_Creek America/Creston"}
+ MX{"America/Hermosillo"}
+ US{"America/Phoenix"}
+ ZZ{"Etc/GMT+7"}
+ }
+ "UTC"{
+ 001{"Etc/GMT"}
+ GL{"America/Danmarkshavn"}
+ ZZ{"Etc/GMT"}
+ }
+ "UTC+12"{
+ 001{"Etc/GMT-12"}
+ KI{"Pacific/Tarawa"}
+ MH{"Pacific/Majuro Pacific/Kwajalein"}
+ NR{"Pacific/Nauru"}
+ TV{"Pacific/Funafuti"}
+ UM{"Pacific/Wake"}
+ WF{"Pacific/Wallis"}
+ ZZ{"Etc/GMT-12"}
+ }
+ "UTC-02"{
+ 001{"Etc/GMT+2"}
+ BR{"America/Noronha"}
+ GS{"Atlantic/South_Georgia"}
+ ZZ{"Etc/GMT+2"}
+ }
+ "UTC-11"{
+ 001{"Etc/GMT+11"}
+ AS{"Pacific/Pago_Pago"}
+ NU{"Pacific/Niue"}
+ UM{"Pacific/Midway"}
+ ZZ{"Etc/GMT+11"}
+ }
+ "Ulaanbaatar Standard Time"{
+ 001{"Asia/Ulaanbaatar"}
+ MN{"Asia/Ulaanbaatar Asia/Choibalsan"}
+ }
+ "Venezuela Standard Time"{
+ 001{"America/Caracas"}
+ VE{"America/Caracas"}
+ }
+ "Vladivostok Standard Time"{
+ 001{"Asia/Vladivostok"}
+ RU{"Asia/Vladivostok Asia/Sakhalin"}
+ }
+ "W. Australia Standard Time"{
+ 001{"Australia/Perth"}
+ AQ{"Antarctica/Casey"}
+ AU{"Australia/Perth"}
+ }
+ "W. Central Africa Standard Time"{
+ 001{"Africa/Lagos"}
+ AO{"Africa/Luanda"}
+ BJ{"Africa/Porto-Novo"}
+ CD{"Africa/Kinshasa"}
+ CF{"Africa/Bangui"}
+ CG{"Africa/Brazzaville"}
+ CM{"Africa/Douala"}
+ DZ{"Africa/Algiers"}
+ GA{"Africa/Libreville"}
+ GQ{"Africa/Malabo"}
+ NE{"Africa/Niamey"}
+ NG{"Africa/Lagos"}
+ TD{"Africa/Ndjamena"}
+ TN{"Africa/Tunis"}
+ ZZ{"Etc/GMT-1"}
+ }
+ "W. Europe Standard Time"{
+ 001{"Europe/Berlin"}
+ AD{"Europe/Andorra"}
+ AT{"Europe/Vienna"}
+ CH{"Europe/Zurich"}
+ DE{"Europe/Berlin"}
+ GI{"Europe/Gibraltar"}
+ IT{"Europe/Rome"}
+ LI{"Europe/Vaduz"}
+ LU{"Europe/Luxembourg"}
+ MC{"Europe/Monaco"}
+ MT{"Europe/Malta"}
+ NL{"Europe/Amsterdam"}
+ NO{"Europe/Oslo"}
+ SE{"Europe/Stockholm"}
+ SJ{"Arctic/Longyearbyen"}
+ SM{"Europe/San_Marino"}
+ VA{"Europe/Vatican"}
+ }
+ "West Asia Standard Time"{
+ 001{"Asia/Tashkent"}
+ AQ{"Antarctica/Mawson"}
+ KZ{"Asia/Oral Asia/Aqtau Asia/Aqtobe"}
+ MV{"Indian/Maldives"}
+ TF{"Indian/Kerguelen"}
+ TJ{"Asia/Dushanbe"}
+ TM{"Asia/Ashgabat"}
+ UZ{"Asia/Tashkent Asia/Samarkand"}
+ ZZ{"Etc/GMT-5"}
+ }
+ "West Pacific Standard Time"{
+ 001{"Pacific/Port_Moresby"}
+ AQ{"Antarctica/DumontDUrville"}
+ FM{"Pacific/Truk"}
+ GU{"Pacific/Guam"}
+ MP{"Pacific/Saipan"}
+ PG{"Pacific/Port_Moresby"}
+ ZZ{"Etc/GMT-10"}
+ }
+ "Yakutsk Standard Time"{
+ 001{"Asia/Yakutsk"}
+ RU{"Asia/Yakutsk"}
+ }
+ }
+}
diff --git a/source/i18n/windtfmt.cpp b/source/i18n/windtfmt.cpp
index 5e37e41..a83df50 100644
--- a/source/i18n/windtfmt.cpp
+++ b/source/i18n/windtfmt.cpp
@@ -1,6 +1,6 @@
/*
********************************************************************************
-* Copyright (C) 2005-2007, International Business Machines
+* Copyright (C) 2005-2012, International Business Machines
* Corporation and others. All Rights Reserved.
********************************************************************************
*
@@ -26,9 +26,12 @@
#include "unicode/unistr.h"
#include "unicode/ustring.h"
#include "unicode/timezone.h"
+#include "unicode/basictz.h"
#include "unicode/utmscale.h"
+#include "uassert.h"
#include "cmemory.h"
+#include "putilimp.h"
#include "uresimp.h"
#include "windtfmt.h"
#include "wintz.h"
@@ -307,6 +310,127 @@
return zoneID;
}
+static UBool getSystemTimeInformation(TimeZone *tz, SYSTEMTIME &daylightDate, SYSTEMTIME &standardDate, int32_t &bias, int32_t &daylightBias, int32_t &standardBias) {
+ UErrorCode status = U_ZERO_ERROR;
+ UBool result = TRUE;
+ BasicTimeZone *btz = (BasicTimeZone*)tz; // we should check type
+ InitialTimeZoneRule *initial = NULL;
+ AnnualTimeZoneRule *std = NULL, *dst = NULL;
+
+ btz->getSimpleRulesNear(uprv_getUTCtime(), initial, std, dst, status);
+ if (U_SUCCESS(status)) {
+ if (std == NULL || dst == NULL) {
+ bias = -1 * (initial->getRawOffset()/60000);
+ standardBias = 0;
+ daylightBias = 0;
+ // Do not use DST. Set 0 to all stadardDate/daylightDate fields
+ standardDate.wYear = standardDate.wMonth = standardDate.wDayOfWeek = standardDate.wDay =
+ standardDate.wHour = standardDate.wMinute = standardDate.wSecond = standardDate.wMilliseconds = 0;
+ daylightDate.wYear = daylightDate.wMonth = daylightDate.wDayOfWeek = daylightDate.wDay =
+ daylightDate.wHour = daylightDate.wMinute = daylightDate.wSecond = daylightDate.wMilliseconds = 0;
+ } else {
+ U_ASSERT(std->getRule()->getDateRuleType() == DateTimeRule::DOW);
+ U_ASSERT(dst->getRule()->getDateRuleType() == DateTimeRule::DOW);
+
+ bias = -1 * (std->getRawOffset()/60000);
+ standardBias = 0;
+ daylightBias = -1 * (dst->getDSTSavings()/60000);
+ // Always use DOW type rule
+ int32_t hour, min, sec, mil;
+ standardDate.wYear = 0;
+ standardDate.wMonth = std->getRule()->getRuleMonth() + 1;
+ standardDate.wDay = std->getRule()->getRuleWeekInMonth();
+ if (standardDate.wDay < 0) {
+ standardDate.wDay = 5;
+ }
+ standardDate.wDayOfWeek = std->getRule()->getRuleDayOfWeek() - 1;
+
+ mil = std->getRule()->getRuleMillisInDay();
+ hour = mil/3600000;
+ mil %= 3600000;
+ min = mil/60000;
+ mil %= 60000;
+ sec = mil/1000;
+ mil %= 1000;
+
+ standardDate.wHour = hour;
+ standardDate.wMinute = min;
+ standardDate.wSecond = sec;
+ standardDate.wMilliseconds = mil;
+
+ daylightDate.wYear = 0;
+ daylightDate.wMonth = dst->getRule()->getRuleMonth() + 1;
+ daylightDate.wDay = dst->getRule()->getRuleWeekInMonth();
+ if (daylightDate.wDay < 0) {
+ daylightDate.wDay = 5;
+ }
+ daylightDate.wDayOfWeek = dst->getRule()->getRuleDayOfWeek() - 1;
+
+ mil = dst->getRule()->getRuleMillisInDay();
+ hour = mil/3600000;
+ mil %= 3600000;
+ min = mil/60000;
+ mil %= 60000;
+ sec = mil/1000;
+ mil %= 1000;
+
+ daylightDate.wHour = hour;
+ daylightDate.wMinute = min;
+ daylightDate.wSecond = sec;
+ daylightDate.wMilliseconds = mil;
+ }
+ } else {
+ result = FALSE;
+ }
+
+ delete initial;
+ delete std;
+ delete dst;
+
+ return result;
+}
+
+static UBool getWindowsTimeZoneInfo(TIME_ZONE_INFORMATION *zoneInfo, const UChar *icuid, int32_t length) {
+ UBool result = FALSE;
+ UnicodeString id = UnicodeString(icuid, length);
+ TimeZone *tz = TimeZone::createTimeZone(id);
+
+ if (tz != NULL) {
+ int32_t bias;
+ int32_t daylightBias;
+ int32_t standardBias;
+ SYSTEMTIME daylightDate;
+ SYSTEMTIME standardDate;
+
+ if (getSystemTimeInformation(tz, daylightDate, standardDate, bias, daylightBias, standardBias)) {
+ uprv_memset(zoneInfo, 0, sizeof(TIME_ZONE_INFORMATION)); // We do not set standard/daylight names, so nullify first.
+ zoneInfo->Bias = bias;
+ zoneInfo->DaylightBias = daylightBias;
+ zoneInfo->StandardBias = standardBias;
+ zoneInfo->DaylightDate = daylightDate;
+ zoneInfo->StandardDate = standardDate;
+
+ result = TRUE;
+ }
+ }
+
+ return result;
+}
+
+/*
+ * Given the timezone icuid, fill in zoneInfo by calling auxillary functions that creates a timezone and extract the
+ * information to put into zoneInfo. This includes bias and standard time date and daylight saving date.
+ */
+U_CAPI UBool U_EXPORT2
+uprv_getWindowsTimeZoneInfo(TIME_ZONE_INFORMATION *zoneInfo, const UChar *icuid, int32_t length)
+{
+ if (getWindowsTimeZoneInfo(zoneInfo, icuid, length)) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
U_NAMESPACE_END
#endif /* #if !UCONFIG_NO_FORMATTING */
diff --git a/source/i18n/windtfmt.h b/source/i18n/windtfmt.h
index 869044e..d9c2531 100644
--- a/source/i18n/windtfmt.h
+++ b/source/i18n/windtfmt.h
@@ -1,6 +1,6 @@
/*
********************************************************************************
-* Copyright (C) 2005-2007, International Business Machines
+* Copyright (C) 2005-2012, International Business Machines
* Corporation and others. All Rights Reserved.
********************************************************************************
*
@@ -37,6 +37,9 @@
U_NAMESPACE_BEGIN
+U_CAPI UBool U_EXPORT2
+uprv_getWindowsTimeZoneInfo(TIME_ZONE_INFORMATION *zoneInfo, const UChar *icuid, int32_t length);
+
class Win32DateFormat : public DateFormat
{
public: