ICU-9752 Update Windows time zone detection to use CLDR data

X-SVN-Rev: 32860
This commit is contained in:
Michael Ow 2012-11-17 01:05:13 +00:00
parent 5d778f0ba4
commit 8fbc9902bd
6 changed files with 931 additions and 444 deletions

View file

@ -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 @@ typedef struct
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 @@ static const char* const TZ_REGKEY[] = {
* 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 @@ static int32_t detectWindowsType()
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 @@ static int32_t detectWindowsType()
}
}
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 @@ static LONG openTZRegKey(HKEY *hkey, const char *winid)
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 @@ static LONG getTZI(const char *winid, TZI *tzi)
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 @@ uprv_getWindowsTimeZoneInfo(TIME_ZONE_INFORMATION *zoneInfo, const UChar *icuid,
*/
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_detectWindowsTimeZone() {
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 @@ uprv_detectWindowsTimeZone() {
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

View file

@ -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 @@ U_CDECL_BEGIN
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();

View file

@ -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

View file

@ -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"}
}
}
}

View file

@ -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 @@ UnicodeString Win32DateFormat::setTimeZoneInfo(TIME_ZONE_INFORMATION *tzi, const
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 */

View file

@ -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_CDECL_END
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: