ICU-7489 Optimize tz canonicalization for zones that are already canonical

X-SVN-Rev: 28535
This commit is contained in:
John Emmons 2010-08-26 15:38:04 +00:00
parent 590648b41e
commit 090df3b5a4
2 changed files with 77 additions and 43 deletions

View file

@ -85,19 +85,6 @@ timezoneTypes:table(nofallback){
"Pacific:Pohnpei"{"Pacific/Ponape"}
"Pacific:Samoa"{"Pacific/Pago_Pago"}
"Pacific:Yap"{"Pacific/Truk"}
"SystemV:AST4"{"Etc/GMT+4"}
"SystemV:AST4ADT"{"America/Halifax"}
"SystemV:CST6"{"Etc/GMT+6"}
"SystemV:CST6CDT"{"CST6CDT"}
"SystemV:EST5"{"Etc/GMT+5"}
"SystemV:EST5EDT"{"EST5EDT"}
"SystemV:HST10"{"Etc/GMT+10"}
"SystemV:MST7"{"Etc/GMT+7"}
"SystemV:MST7MDT"{"MST7MDT"}
"SystemV:PST8"{"Etc/GMT+8"}
"SystemV:PST8PDT"{"PST8PDT"}
"SystemV:YST9"{"Etc/GMT+9"}
"SystemV:YST9YDT"{"America/Anchorage"}
"US:Alaska"{"America/Anchorage"}
"US:Aleutian"{"America/Adak"}
"US:Arizona"{"America/Phoenix"}

View file

@ -93,8 +93,9 @@ static const char gMetaZones[] = "metaZones";
static const char gMetazoneInfo[] = "metazoneInfo";
static const char gMapTimezonesTag[] = "mapTimezones";
static const char gKeyTypeData[] = "keyTypeData";
static const char gTimeZoneTypes[] = "timezoneTypes";
static const char gTypeAliasTag[] = "typeAlias";
static const char gTypeMapTag[] = "typeMap";
static const char gTimezoneTag[] = "timezone";
static const char gWorldTag[] = "001";
@ -185,43 +186,89 @@ parseDate (const UChar *text, UErrorCode &status) {
UnicodeString& U_EXPORT2
ZoneMeta::getCanonicalSystemID(const UnicodeString &tzid, UnicodeString &systemID, UErrorCode& status) {
// Dereference the input ID using the tz data first
const UChar *canonical = TimeZone::dereferOlsonLink(tzid);
if (canonical != NULL) {
// check canonical mapping in CLDR
char id[ZID_KEY_MAX];
int32_t len = u_strlen(canonical);
if (len < (int32_t)sizeof(id)) {
u_UCharsToChars(canonical, id, len + 1 /* include the terminator */);
// replace '/' with ':'
char *p = id;
while (*p) {
if (*p == '/') {
*p = ':';
}
p++;
}
int32_t len = tzid.length();
if ( len >= ZID_KEY_MAX ) {
status = U_ILLEGAL_ARGUMENT_ERROR;
systemID.remove();
return systemID;
}
UErrorCode tmpStatus = U_ZERO_ERROR;
UResourceBundle *rb = ures_openDirect(NULL, gKeyTypeData, &tmpStatus);
ures_getByKey(rb, gTypeAliasTag, rb, &tmpStatus);
ures_getByKey(rb, gTimezoneTag, rb, &tmpStatus);
const UChar *cldrCanonical = ures_getStringByKey(rb, id, NULL, &tmpStatus);
if (U_SUCCESS(tmpStatus)) {
// canonical map found
canonical = cldrCanonical;
}
ures_close(rb);
char id[ZID_KEY_MAX];
const UChar* idChars = tzid.getBuffer();
u_UCharsToChars(idChars,id,len);
id[len] = (char) 0; // Make sure it is null terminated.
// replace '/' with ':'
char *p = id;
while (*p++) {
if (*p == '/') {
*p = ':';
}
}
if (canonical == NULL) {
UErrorCode tmpStatus = U_ZERO_ERROR;
UResourceBundle *top = ures_openDirect(NULL, gTimeZoneTypes, &tmpStatus);
UResourceBundle *rb = ures_getByKey(top, gTypeMapTag, NULL, &tmpStatus);
ures_getByKey(rb, gTimezoneTag, rb, &tmpStatus);
ures_getByKey(rb, id, rb, &tmpStatus);
if (U_SUCCESS(tmpStatus)) {
// direct map found
systemID.setTo(tzid);
ures_close(rb);
ures_close(top);
return systemID;
}
// If a map element not found, then look for an alias
tmpStatus = U_ZERO_ERROR;
ures_getByKey(top, gTypeAliasTag, rb, &tmpStatus);
ures_getByKey(rb, gTimezoneTag, rb, &tmpStatus);
const UChar *alias = ures_getStringByKey(rb,id,NULL,&tmpStatus);
if (U_SUCCESS(tmpStatus)) {
// alias found
ures_close(rb);
ures_close(top);
systemID.setTo(alias);
return systemID;
}
// Dereference the input ID using the tz data
const UChar *derefer = TimeZone::dereferOlsonLink(tzid);
if (derefer == NULL) {
systemID.remove();
status = U_ILLEGAL_ARGUMENT_ERROR;
} else {
systemID.setTo(canonical);
len = u_strlen(derefer);
u_UCharsToChars(derefer,id,len);
id[len] = (char) 0; // Make sure it is null terminated.
// replace '/' with ':'
char *p = id;
while (*p++) {
if (*p == '/') {
*p = ':';
}
}
// If a dereference turned something up then look for an alias.
// rb still points to the alias table, so we don't have to go looking
// for it.
tmpStatus = U_ZERO_ERROR;
const UChar *alias = ures_getStringByKey(rb,id,NULL,&tmpStatus);
if (U_SUCCESS(tmpStatus)) {
// alias found
systemID.setTo(alias);
} else {
systemID.setTo(derefer);
}
}
return systemID;
ures_close(rb);
ures_close(top);
return systemID;
}
UnicodeString& U_EXPORT2