ICU-8278 New APIs TimeZone::createTimeZoneIDEnumeration and ucal_openTimeZoneIDEnumeration for supporting canonical/canonical location zone iteration. The fix for ticket#8349 Etc/Unknown problem was also done at the same time.
X-SVN-Rev: 29498
This commit is contained in:
parent
00e54087ea
commit
34bc79c98b
@ -124,6 +124,14 @@ static U_NAMESPACE_QUALIFIER TimeZone* _GMT = NULL; // cf. TimeZone::GMT
|
||||
static char TZDATA_VERSION[16];
|
||||
static UBool TZDataVersionInitialized = FALSE;
|
||||
|
||||
static int32_t* MAP_SYSTEM_ZONES = NULL;
|
||||
static int32_t* MAP_CANONICAL_SYSTEM_ZONES = NULL;
|
||||
static int32_t* MAP_CANONICAL_SYSTEM_LOCATION_ZONES = NULL;
|
||||
|
||||
int32_t LEN_SYSTEM_ZONES = 0;
|
||||
int32_t LEN_CANONICAL_SYSTEM_ZONES = 0;
|
||||
int32_t LEN_CANONICAL_SYSTEM_LOCATION_ZONES = 0;
|
||||
|
||||
U_CDECL_BEGIN
|
||||
static UBool U_CALLCONV timeZone_cleanup(void)
|
||||
{
|
||||
@ -136,6 +144,18 @@ static UBool U_CALLCONV timeZone_cleanup(void)
|
||||
uprv_memset(TZDATA_VERSION, 0, sizeof(TZDATA_VERSION));
|
||||
TZDataVersionInitialized = FALSE;
|
||||
|
||||
LEN_SYSTEM_ZONES = 0;
|
||||
uprv_free(MAP_SYSTEM_ZONES);
|
||||
MAP_SYSTEM_ZONES = 0;
|
||||
|
||||
LEN_CANONICAL_SYSTEM_ZONES = 0;
|
||||
uprv_free(MAP_CANONICAL_SYSTEM_ZONES);
|
||||
MAP_CANONICAL_SYSTEM_ZONES = 0;
|
||||
|
||||
LEN_CANONICAL_SYSTEM_LOCATION_ZONES = 0;
|
||||
uprv_free(MAP_CANONICAL_SYSTEM_LOCATION_ZONES);
|
||||
MAP_CANONICAL_SYSTEM_LOCATION_ZONES = 0;
|
||||
|
||||
if (LOCK) {
|
||||
umtx_destroy(&LOCK);
|
||||
LOCK = NULL;
|
||||
@ -151,49 +171,6 @@ U_CDECL_END
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
/**
|
||||
* The Olson data is stored the "zoneinfo" resource bundle.
|
||||
* Sub-resources are organized into three ranges of data: Zones, final
|
||||
* rules, and country tables. There is also a meta-data resource
|
||||
* which has 3 integers: The number of zones, rules, and countries,
|
||||
* respectively. The country count includes the non-country 'Default'.
|
||||
*/
|
||||
static int32_t OLSON_ZONE_COUNT = 0; // count of zones
|
||||
|
||||
/**
|
||||
* Given a pointer to an open "zoneinfo" resource, load up the Olson
|
||||
* meta-data. Return TRUE if successful.
|
||||
*/
|
||||
static UBool getOlsonMeta(const UResourceBundle* top) {
|
||||
if (OLSON_ZONE_COUNT == 0) {
|
||||
UErrorCode ec = U_ZERO_ERROR;
|
||||
UResourceBundle res;
|
||||
ures_initStackObject(&res);
|
||||
ures_getByKey(top, kZONES, &res, &ec);
|
||||
if(U_SUCCESS(ec)) {
|
||||
OLSON_ZONE_COUNT = ures_getSize(&res);
|
||||
U_DEBUG_TZ_MSG(("OZC%d\n",OLSON_ZONE_COUNT));
|
||||
}
|
||||
ures_close(&res);
|
||||
}
|
||||
return (OLSON_ZONE_COUNT > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load up the Olson meta-data. Return TRUE if successful.
|
||||
*/
|
||||
static UBool getOlsonMeta() {
|
||||
if (OLSON_ZONE_COUNT == 0) {
|
||||
UErrorCode ec = U_ZERO_ERROR;
|
||||
UResourceBundle *top = ures_openDirect(0, kZONEINFO, &ec);
|
||||
if (U_SUCCESS(ec)) {
|
||||
getOlsonMeta(top);
|
||||
}
|
||||
ures_close(top);
|
||||
}
|
||||
return (OLSON_ZONE_COUNT > 0);
|
||||
}
|
||||
|
||||
static int32_t findInStringArray(UResourceBundle* array, const UnicodeString& id, UErrorCode &status)
|
||||
{
|
||||
UnicodeString copy;
|
||||
@ -304,7 +281,7 @@ static UResourceBundle* openOlsonResource(const UnicodeString& id,
|
||||
// Dereference if this is an alias. Docs say result should be 1
|
||||
// but it is 0 in 2.8 (?).
|
||||
U_DEBUG_TZ_MSG(("Loading zone '%s' (%s, size %d) - %s\n", buf, ures_getKey((UResourceBundle*)&res), ures_getSize(&res), u_errorName(ec)));
|
||||
if (ures_getType(&res) == URES_INT && getOlsonMeta(top)) {
|
||||
if (ures_getType(&res) == URES_INT) {
|
||||
int32_t deref = ures_getInt(&res, &ec) + 0;
|
||||
U_DEBUG_TZ_MSG(("getInt: %s - type is %d\n", u_errorName(ec), ures_getType(&res)));
|
||||
UResourceBundle *ares = ures_getByKey(top, kZONES, NULL, &ec); // dereference Zones section
|
||||
@ -424,8 +401,16 @@ TimeZone::createTimeZone(const UnicodeString& ID)
|
||||
*/
|
||||
TimeZone*
|
||||
TimeZone::createSystemTimeZone(const UnicodeString& id) {
|
||||
TimeZone* z = 0;
|
||||
UErrorCode ec = U_ZERO_ERROR;
|
||||
return createSystemTimeZone(id, ec);
|
||||
}
|
||||
|
||||
TimeZone*
|
||||
TimeZone::createSystemTimeZone(const UnicodeString& id, UErrorCode& ec) {
|
||||
if (U_FAILURE(ec)) {
|
||||
return NULL;
|
||||
}
|
||||
TimeZone* z = 0;
|
||||
UResourceBundle res;
|
||||
ures_initStackObject(&res);
|
||||
U_DEBUG_TZ_MSG(("pre-err=%s\n", u_errorName(ec)));
|
||||
@ -657,10 +642,17 @@ private:
|
||||
// Map into to zones. Our results are zone[map[i]] for
|
||||
// i=0..len-1, where zone[i] is the i-th Olson zone. If map==NULL
|
||||
// then our results are zone[i] for i=0..len-1. Len will be zero
|
||||
// iff the zone data could not be loaded.
|
||||
// if the zone data could not be loaded.
|
||||
int32_t* map;
|
||||
int32_t len;
|
||||
int32_t pos;
|
||||
int32_t* localMap;
|
||||
|
||||
TZEnumeration(int32_t* mapData, int32_t mapLen, UBool adoptMapData) : pos(0) {
|
||||
map = mapData;
|
||||
localMap = adoptMapData ? mapData : NULL;
|
||||
len = mapLen;
|
||||
}
|
||||
|
||||
UBool getID(int32_t i) {
|
||||
UErrorCode ec = U_ZERO_ERROR;
|
||||
@ -679,118 +671,272 @@ private:
|
||||
return U_SUCCESS(ec);
|
||||
}
|
||||
|
||||
public:
|
||||
TZEnumeration() : map(NULL), len(0), pos(0) {
|
||||
if (getOlsonMeta()) {
|
||||
len = OLSON_ZONE_COUNT;
|
||||
static int32_t* getMap(USystemTimeZoneType type, int32_t& len, UErrorCode& ec) {
|
||||
len = 0;
|
||||
if (U_FAILURE(ec)) {
|
||||
return NULL;
|
||||
}
|
||||
int32_t* m = NULL;
|
||||
switch (type) {
|
||||
case UCAL_ZONE_TYPE_ANY:
|
||||
m = MAP_SYSTEM_ZONES;
|
||||
len = LEN_SYSTEM_ZONES;
|
||||
break;
|
||||
case UCAL_ZONE_TYPE_CANONICAL:
|
||||
m = MAP_CANONICAL_SYSTEM_ZONES;
|
||||
len = LEN_CANONICAL_SYSTEM_ZONES;
|
||||
break;
|
||||
case UCAL_ZONE_TYPE_CANONICAL_LOCATION:
|
||||
m = MAP_CANONICAL_SYSTEM_LOCATION_ZONES;
|
||||
len = LEN_CANONICAL_SYSTEM_LOCATION_ZONES;
|
||||
break;
|
||||
}
|
||||
UBool needsInit = FALSE;
|
||||
UMTX_CHECK(&LOCK, (len == 0), needsInit);
|
||||
if (needsInit) {
|
||||
m = initMap(type, len, ec);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
TZEnumeration(int32_t rawOffset) : map(NULL), len(0), pos(0) {
|
||||
if (!getOlsonMeta()) {
|
||||
return;
|
||||
static int32_t* initMap(USystemTimeZoneType type, int32_t& len, UErrorCode& ec) {
|
||||
len = 0;
|
||||
if (U_FAILURE(ec)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Allocate more space than we'll need. The end of the array will
|
||||
// be blank.
|
||||
map = (int32_t*)uprv_malloc(OLSON_ZONE_COUNT * sizeof(int32_t));
|
||||
if (map == 0) {
|
||||
return;
|
||||
}
|
||||
int32_t *result = NULL;
|
||||
|
||||
uprv_memset(map, 0, sizeof(int32_t) * OLSON_ZONE_COUNT);
|
||||
|
||||
UnicodeString s;
|
||||
for (int32_t i=0; i<OLSON_ZONE_COUNT; ++i) {
|
||||
if (getID(i)) {
|
||||
// This is VERY inefficient.
|
||||
TimeZone* z = TimeZone::createTimeZone(unistr);
|
||||
// Make sure we get back the ID we wanted (if the ID is
|
||||
// invalid we get back GMT).
|
||||
if (z != 0 && z->getID(s) == unistr &&
|
||||
z->getRawOffset() == rawOffset) {
|
||||
map[len++] = i;
|
||||
}
|
||||
delete z;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TZEnumeration(const char* country) : map(NULL), len(0), pos(0) {
|
||||
if (!getOlsonMeta()) {
|
||||
return;
|
||||
}
|
||||
|
||||
UErrorCode ec = U_ZERO_ERROR;
|
||||
UResourceBundle *res = ures_openDirect(0, kZONEINFO, &ec);
|
||||
ures_getByKey(res, kREGIONS, res, &ec);
|
||||
if (U_SUCCESS(ec) && ures_getType(res) == URES_ARRAY) {
|
||||
UChar uCountry[] = {0, 0, 0, 0};
|
||||
if (country) {
|
||||
u_charsToUChars(country, uCountry, 2);
|
||||
res = ures_getByKey(res, kNAMES, res, &ec); // dereference Zones section
|
||||
if (U_SUCCESS(ec)) {
|
||||
int32_t size = ures_getSize(res);
|
||||
int32_t *m = (int32_t *)uprv_malloc(size * sizeof(int32_t));
|
||||
if (m == NULL) {
|
||||
ec = U_MEMORY_ALLOCATION_ERROR;
|
||||
} else {
|
||||
u_strcpy(uCountry, WORLD);
|
||||
}
|
||||
|
||||
// count matches
|
||||
int32_t count = 0;
|
||||
int32_t i;
|
||||
const UChar *region;
|
||||
for (i = 0; i < ures_getSize(res); i++) {
|
||||
region = ures_getStringByIndex(res, i, NULL, &ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
break;
|
||||
}
|
||||
if (u_strcmp(uCountry, region) == 0) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
if (count > 0) {
|
||||
map = (int32_t*)uprv_malloc(sizeof(int32_t) * count);
|
||||
if (map != NULL) {
|
||||
int32_t idx = 0;
|
||||
for (i = 0; i < ures_getSize(res); i++) {
|
||||
region = ures_getStringByIndex(res, i, NULL, &ec);
|
||||
int32_t numEntries = 0;
|
||||
for (int32_t i = 0; i < size; i++) {
|
||||
const UChar *id = ures_getStringByIndex(res, i, NULL, &ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
break;
|
||||
}
|
||||
if (u_strcmp(id, UNKNOWN_ZONE_ID) == 0) {
|
||||
// exclude Etc/Unknown
|
||||
continue;
|
||||
}
|
||||
if (type == UCAL_ZONE_TYPE_CANONICAL || type == UCAL_ZONE_TYPE_CANONICAL_LOCATION) {
|
||||
UnicodeString canonicalID;
|
||||
ZoneMeta::getCanonicalCLDRID(id, canonicalID, ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
break;
|
||||
}
|
||||
if (u_strcmp(uCountry, region) == 0) {
|
||||
map[idx++] = i;
|
||||
if (canonicalID.compare(id, -1) != 0) {
|
||||
// exclude aliases
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (U_SUCCESS(ec)) {
|
||||
len = count;
|
||||
} else {
|
||||
uprv_free(map);
|
||||
map = NULL;
|
||||
if (type == UCAL_ZONE_TYPE_CANONICAL_LOCATION) {
|
||||
const UChar *region = TimeZone::getRegion(id, ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
break;
|
||||
}
|
||||
if (u_strcmp(region, WORLD) == 0) {
|
||||
// exclude non-location ("001")
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
U_DEBUG_TZ_MSG(("Failed to load tz for region %s: %s\n", country, u_errorName(ec)));
|
||||
m[numEntries++] = i;
|
||||
}
|
||||
if (U_SUCCESS(ec)) {
|
||||
int32_t *tmp = m;
|
||||
m = (int32_t *)uprv_realloc(tmp, numEntries * sizeof(int32_t));
|
||||
if (m == NULL) {
|
||||
// realloc failed.. use the original one even it has unused
|
||||
// area at the end
|
||||
m = tmp;
|
||||
}
|
||||
|
||||
umtx_lock(&LOCK);
|
||||
{
|
||||
switch(type) {
|
||||
case UCAL_ZONE_TYPE_ANY:
|
||||
if (MAP_SYSTEM_ZONES == NULL) {
|
||||
MAP_SYSTEM_ZONES = m;
|
||||
LEN_SYSTEM_ZONES = numEntries;
|
||||
m = NULL;
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
|
||||
}
|
||||
result = MAP_SYSTEM_ZONES;
|
||||
len = LEN_SYSTEM_ZONES;
|
||||
break;
|
||||
case UCAL_ZONE_TYPE_CANONICAL:
|
||||
if (MAP_CANONICAL_SYSTEM_ZONES == NULL) {
|
||||
MAP_CANONICAL_SYSTEM_ZONES = m;
|
||||
LEN_CANONICAL_SYSTEM_ZONES = numEntries;
|
||||
m = NULL;
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
|
||||
}
|
||||
result = MAP_CANONICAL_SYSTEM_ZONES;
|
||||
len = LEN_CANONICAL_SYSTEM_ZONES;
|
||||
break;
|
||||
case UCAL_ZONE_TYPE_CANONICAL_LOCATION:
|
||||
if (MAP_CANONICAL_SYSTEM_LOCATION_ZONES == NULL) {
|
||||
MAP_CANONICAL_SYSTEM_LOCATION_ZONES = m;
|
||||
LEN_CANONICAL_SYSTEM_LOCATION_ZONES = numEntries;
|
||||
m = NULL;
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
|
||||
}
|
||||
result = MAP_CANONICAL_SYSTEM_LOCATION_ZONES;
|
||||
len = LEN_CANONICAL_SYSTEM_LOCATION_ZONES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
umtx_unlock(&LOCK);
|
||||
}
|
||||
uprv_free(m);
|
||||
}
|
||||
}
|
||||
|
||||
ures_close(res);
|
||||
return result;
|
||||
}
|
||||
|
||||
TZEnumeration(const TZEnumeration &other) : StringEnumeration(), map(NULL), len(0), pos(0) {
|
||||
if(other.len > 0) {
|
||||
if(other.map != NULL) {
|
||||
map = (int32_t *)uprv_malloc(other.len * sizeof(int32_t));
|
||||
if(map != NULL) {
|
||||
len = other.len;
|
||||
uprv_memcpy(map, other.map, len * sizeof(int32_t));
|
||||
pos = other.pos;
|
||||
}
|
||||
} else {
|
||||
len = other.len;
|
||||
pos = other.pos;
|
||||
public:
|
||||
|
||||
#define DEFAULT_FILTERED_MAP_SIZE 8
|
||||
#define MAP_INCREMENT_SIZE 8
|
||||
|
||||
static TZEnumeration* create(USystemTimeZoneType type, const char* region, const int32_t* rawOffset, UErrorCode& ec) {
|
||||
if (U_FAILURE(ec)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int32_t baseLen;
|
||||
int32_t *baseMap = getMap(type, baseLen, ec);
|
||||
|
||||
if (U_FAILURE(ec)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// If any additional conditions are available,
|
||||
// create instance local map filtered by the conditions.
|
||||
|
||||
int32_t *filteredMap = NULL;
|
||||
int32_t numEntries = 0;
|
||||
|
||||
if (region != NULL || rawOffset != NULL) {
|
||||
int32_t filteredMapSize = DEFAULT_FILTERED_MAP_SIZE;
|
||||
filteredMap = (int32_t *)uprv_malloc(filteredMapSize * sizeof(int32_t));
|
||||
if (filteredMap == NULL) {
|
||||
ec = U_MEMORY_ALLOCATION_ERROR;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Walk through the base map
|
||||
UResourceBundle *res = ures_openDirect(0, kZONEINFO, &ec);
|
||||
res = ures_getByKey(res, kNAMES, res, &ec); // dereference Zones section
|
||||
for (int32_t i = 0; i < baseLen; i++) {
|
||||
int32_t zidx = baseMap[i];
|
||||
const UChar *id = ures_getStringByIndex(res, zidx, NULL, &ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
break;
|
||||
}
|
||||
if (region != NULL) {
|
||||
// Filter by region
|
||||
char tzregion[4]; // max 3 letters + null term
|
||||
TimeZone::getRegion(id, tzregion, sizeof(tzregion), ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
break;
|
||||
}
|
||||
if (uprv_stricmp(tzregion, region) != 0) {
|
||||
// region does not match
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (rawOffset != NULL) {
|
||||
// Filter by raw offset
|
||||
// Note: This is VERY inefficient
|
||||
TimeZone *z = TimeZone::createSystemTimeZone(id, ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
break;
|
||||
}
|
||||
int32_t tzoffset = z->getRawOffset();
|
||||
delete z;
|
||||
|
||||
if (tzoffset != *rawOffset) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (filteredMapSize <= numEntries) {
|
||||
filteredMapSize += MAP_INCREMENT_SIZE;
|
||||
int32_t *tmp = (int32_t *)uprv_realloc(filteredMap, filteredMapSize * sizeof(int32_t));
|
||||
if (tmp == NULL) {
|
||||
ec = U_MEMORY_ALLOCATION_ERROR;
|
||||
break;
|
||||
} else {
|
||||
filteredMap = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
filteredMap[numEntries++] = zidx;
|
||||
}
|
||||
|
||||
if (U_FAILURE(ec)) {
|
||||
uprv_free(filteredMap);
|
||||
filteredMap = NULL;
|
||||
}
|
||||
|
||||
ures_close(res);
|
||||
}
|
||||
|
||||
TZEnumeration *result = NULL;
|
||||
if (U_SUCCESS(ec)) {
|
||||
// Finally, create a new enumeration instance
|
||||
if (filteredMap == NULL) {
|
||||
result = new TZEnumeration(baseMap, baseLen, FALSE);
|
||||
} else {
|
||||
result = new TZEnumeration(filteredMap, numEntries, TRUE);
|
||||
filteredMap = NULL;
|
||||
}
|
||||
if (result == NULL) {
|
||||
ec = U_MEMORY_ALLOCATION_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (filteredMap != NULL) {
|
||||
uprv_free(filteredMap);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
TZEnumeration(const TZEnumeration &other) : StringEnumeration(), map(NULL), localMap(NULL), len(0), pos(0) {
|
||||
if (other.localMap != NULL) {
|
||||
localMap = (int32_t *)uprv_malloc(other.len * sizeof(int32_t));
|
||||
if (localMap != NULL) {
|
||||
len = other.len;
|
||||
uprv_memcpy(localMap, other.localMap, len * sizeof(int32_t));
|
||||
pos = other.pos;
|
||||
map = localMap;
|
||||
} else {
|
||||
len = 0;
|
||||
pos = 0;
|
||||
map = NULL;
|
||||
}
|
||||
} else {
|
||||
map = other.map;
|
||||
localMap = NULL;
|
||||
len = other.len;
|
||||
pos = other.pos;
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~TZEnumeration() {
|
||||
uprv_free(map);
|
||||
if (localMap != NULL) {
|
||||
uprv_free(localMap);
|
||||
}
|
||||
}
|
||||
|
||||
virtual StringEnumeration *clone() const {
|
||||
@ -802,8 +948,8 @@ public:
|
||||
}
|
||||
|
||||
virtual const UnicodeString* snext(UErrorCode& status) {
|
||||
if (U_SUCCESS(status) && pos < len) {
|
||||
getID((map == 0) ? pos : map[pos]);
|
||||
if (U_SUCCESS(status) && map != NULL && pos < len) {
|
||||
getID(map[pos]);
|
||||
++pos;
|
||||
return &unistr;
|
||||
}
|
||||
@ -821,19 +967,31 @@ public:
|
||||
|
||||
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(TZEnumeration)
|
||||
|
||||
StringEnumeration* U_EXPORT2
|
||||
TimeZone::createTimeZoneIDEnumeration(
|
||||
USystemTimeZoneType zoneType,
|
||||
const char* region,
|
||||
const int32_t* rawOffset,
|
||||
UErrorCode& ec) {
|
||||
return TZEnumeration::create(zoneType, region, rawOffset, ec);
|
||||
}
|
||||
|
||||
StringEnumeration* U_EXPORT2
|
||||
TimeZone::createEnumeration() {
|
||||
return new TZEnumeration();
|
||||
UErrorCode ec = U_ZERO_ERROR;
|
||||
return TZEnumeration::create(UCAL_ZONE_TYPE_ANY, NULL, NULL, ec);
|
||||
}
|
||||
|
||||
StringEnumeration* U_EXPORT2
|
||||
TimeZone::createEnumeration(int32_t rawOffset) {
|
||||
return new TZEnumeration(rawOffset);
|
||||
UErrorCode ec = U_ZERO_ERROR;
|
||||
return TZEnumeration::create(UCAL_ZONE_TYPE_ANY, NULL, &rawOffset, ec);
|
||||
}
|
||||
|
||||
StringEnumeration* U_EXPORT2
|
||||
TimeZone::createEnumeration(const char* country) {
|
||||
return new TZEnumeration(country);
|
||||
UErrorCode ec = U_ZERO_ERROR;
|
||||
return TZEnumeration::create(UCAL_ZONE_TYPE_ANY, country, NULL, ec);
|
||||
}
|
||||
|
||||
// ---------------------------------------
|
||||
@ -876,7 +1034,7 @@ TimeZone::getEquivalentID(const UnicodeString& id, int32_t index) {
|
||||
ures_getByKey(&res, kLINKS, &r, &ec);
|
||||
const int32_t* v = ures_getIntVector(&r, &size, &ec);
|
||||
if (U_SUCCESS(ec)) {
|
||||
if (index >= 0 && index < size && getOlsonMeta()) {
|
||||
if (index >= 0 && index < size) {
|
||||
zone = v[index];
|
||||
}
|
||||
}
|
||||
@ -940,18 +1098,26 @@ TimeZone::dereferOlsonLink(const UnicodeString& id) {
|
||||
|
||||
const UChar*
|
||||
TimeZone::getRegion(const UnicodeString& id) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
return getRegion(id, status);
|
||||
}
|
||||
|
||||
const UChar*
|
||||
TimeZone::getRegion(const UnicodeString& id, UErrorCode& status) {
|
||||
if (U_FAILURE(status)) {
|
||||
return NULL;
|
||||
}
|
||||
const UChar *result = NULL;
|
||||
UErrorCode ec = U_ZERO_ERROR;
|
||||
UResourceBundle *rb = ures_openDirect(NULL, kZONEINFO, &ec);
|
||||
UResourceBundle *rb = ures_openDirect(NULL, kZONEINFO, &status);
|
||||
|
||||
// resolve zone index by name
|
||||
UResourceBundle *res = ures_getByKey(rb, kNAMES, NULL, &ec);
|
||||
int32_t idx = findInStringArray(res, id, ec);
|
||||
UResourceBundle *res = ures_getByKey(rb, kNAMES, NULL, &status);
|
||||
int32_t idx = findInStringArray(res, id, status);
|
||||
|
||||
// get region mapping
|
||||
ures_getByKey(rb, kREGIONS, res, &ec);
|
||||
const UChar *tmp = ures_getStringByIndex(res, idx, NULL, &ec);
|
||||
if (U_SUCCESS(ec)) {
|
||||
ures_getByKey(rb, kREGIONS, res, &status);
|
||||
const UChar *tmp = ures_getStringByIndex(res, idx, NULL, &status);
|
||||
if (U_SUCCESS(status)) {
|
||||
result = tmp;
|
||||
}
|
||||
|
||||
@ -961,6 +1127,7 @@ TimeZone::getRegion(const UnicodeString& id) {
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------
|
||||
int32_t
|
||||
TimeZone::getRegion(const UnicodeString& id, char *region, int32_t capacity, UErrorCode& status)
|
||||
@ -1399,13 +1566,19 @@ TimeZone::getCanonicalID(const UnicodeString& id, UnicodeString& canonicalID, UB
|
||||
if (U_FAILURE(status)) {
|
||||
return canonicalID;
|
||||
}
|
||||
ZoneMeta::getCanonicalSystemID(id, canonicalID, status);
|
||||
if (U_SUCCESS(status)) {
|
||||
isSystemID = TRUE;
|
||||
if (id.compare(UNKNOWN_ZONE_ID, UNKNOWN_ZONE_ID_LENGTH) == 0) {
|
||||
// special case - Etc/Unknown is a canonical ID, but not system ID
|
||||
canonicalID.fastCopyFrom(id);
|
||||
isSystemID = FALSE;
|
||||
} else {
|
||||
// Not a system ID
|
||||
status = U_ZERO_ERROR;
|
||||
getCustomID(id, canonicalID, status);
|
||||
ZoneMeta::getCanonicalCLDRID(id, canonicalID, status);
|
||||
if (U_SUCCESS(status)) {
|
||||
isSystemID = TRUE;
|
||||
} else {
|
||||
// Not a system ID
|
||||
status = U_ZERO_ERROR;
|
||||
getCustomID(id, canonicalID, status);
|
||||
}
|
||||
}
|
||||
return canonicalID;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 1996-2010, International Business Machines
|
||||
* Copyright (C) 1996-2011, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
*******************************************************************************
|
||||
*/
|
||||
@ -45,6 +45,13 @@ _createTimeZone(const UChar* zoneID, int32_t len, UErrorCode* ec) {
|
||||
return zone;
|
||||
}
|
||||
|
||||
U_CAPI UEnumeration* U_EXPORT2
|
||||
ucal_openTimeZoneIDEnumeration(USystemTimeZoneType zoneType, const char* region,
|
||||
const int32_t* rawOffset, UErrorCode* ec) {
|
||||
return uenum_openFromStringEnumeration(TimeZone::createTimeZoneIDEnumeration(
|
||||
zoneType, region, rawOffset, *ec), ec);
|
||||
}
|
||||
|
||||
U_CAPI UEnumeration* U_EXPORT2
|
||||
ucal_openTimeZones(UErrorCode* ec) {
|
||||
return uenum_openFromStringEnumeration(TimeZone::createEnumeration(), ec);
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "unicode/uobject.h"
|
||||
#include "unicode/unistr.h"
|
||||
#include "unicode/ures.h"
|
||||
#include "unicode/ucal.h"
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
@ -146,6 +147,28 @@ public:
|
||||
*/
|
||||
static TimeZone* U_EXPORT2 createTimeZone(const UnicodeString& ID);
|
||||
|
||||
|
||||
/**
|
||||
* Returns an enumeration over system time zone IDs with the given
|
||||
* filter conditions.
|
||||
* @param zoneType The system time zone type.
|
||||
* @param region The ISO 3166 two-letter country code or UN M.49
|
||||
* three-digit area code. When NULL, no filtering
|
||||
* done by region.
|
||||
* @param rawOffset An offset from GMT in milliseconds, ignoring
|
||||
* the effect of daylight savings time, if any.
|
||||
* When NULL, no filtering done by zone offset.
|
||||
* @param ec Output param to filled in with a success or
|
||||
* an error.
|
||||
* @return an enumeration object, owned by the caller.
|
||||
* @draft ICU 4.8
|
||||
*/
|
||||
static StringEnumeration* U_EXPORT2 createTimeZoneIDEnumeration(
|
||||
USystemTimeZoneType zoneType,
|
||||
const char* region,
|
||||
const int32_t* rawOffset,
|
||||
UErrorCode& ec);
|
||||
|
||||
/**
|
||||
* Returns an enumeration over all recognized time zone IDs. (i.e.,
|
||||
* all strings that createTimeZone() accepts)
|
||||
@ -725,6 +748,15 @@ private:
|
||||
*/
|
||||
static const UChar* getRegion(const UnicodeString& id);
|
||||
|
||||
/**
|
||||
* Returns the region code associated with the given zone,
|
||||
* or NULL if the zone is not known.
|
||||
* @param id zone id string
|
||||
* @param status Status parameter
|
||||
* @return the region associated with the given zone
|
||||
*/
|
||||
static const UChar* getRegion(const UnicodeString& id, UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Parses the given custom time zone identifier
|
||||
* @param id id A string of the form GMT[+-]hh:mm, GMT[+-]hhmm, or
|
||||
@ -779,9 +811,11 @@ private:
|
||||
* @return the TimeZone indicated by the 'name'.
|
||||
*/
|
||||
static TimeZone* createSystemTimeZone(const UnicodeString& name);
|
||||
static TimeZone* createSystemTimeZone(const UnicodeString& name, UErrorCode& ec);
|
||||
|
||||
UnicodeString fID; // this time zone's ID
|
||||
|
||||
friend class TZEnumeration;
|
||||
};
|
||||
|
||||
|
||||
|
@ -521,6 +521,53 @@ enum UCalendarAMPMs {
|
||||
/** @stable ICU 2.0 */
|
||||
typedef enum UCalendarAMPMs UCalendarAMPMs;
|
||||
|
||||
/**
|
||||
* System time zone type constants used by filtering zones
|
||||
* in ucal_openTimeZoneIDEnumeration.
|
||||
* @see ucal_openTimeZoneIDEnumeration
|
||||
* @draft ICU 4.8
|
||||
*/
|
||||
enum USystemTimeZoneType {
|
||||
/**
|
||||
* Any system zones.
|
||||
* @draft ICU 4.8
|
||||
*/
|
||||
UCAL_ZONE_TYPE_ANY,
|
||||
/**
|
||||
* Canonical system zones.
|
||||
* @draft ICU 4.8
|
||||
*/
|
||||
UCAL_ZONE_TYPE_CANONICAL,
|
||||
/**
|
||||
* Canonical system zones associated with actual locations.
|
||||
* @draft ICU 4.8
|
||||
*/
|
||||
UCAL_ZONE_TYPE_CANONICAL_LOCATION
|
||||
};
|
||||
|
||||
/** @draft ICU 4.8 */
|
||||
typedef enum USystemTimeZoneType USystemTimeZoneType;
|
||||
|
||||
/**
|
||||
* Create an enumeration over system time zone IDs with the given
|
||||
* filter conditions.
|
||||
* @param zoneType The system time zone type.
|
||||
* @param region The ISO 3166 two-letter country code or UN M.49
|
||||
* three-digit area code. When NULL, no filtering
|
||||
* done by region.
|
||||
* @param rawOffset An offset from GMT in milliseconds, ignoring the
|
||||
* effect of daylight savings time, if any. When NULL,
|
||||
* no filtering done by zone offset.
|
||||
* @param ec A pointer to an UErrorCode to receive any errors
|
||||
* @return an enumeration object that the caller must dispose of
|
||||
* using enum_close(), or NULL upon failure. In case of failure,
|
||||
* *ec will indicate the error.
|
||||
* @draft ICU 4.8
|
||||
*/
|
||||
U_DRAFT UEnumeration* U_EXPORT2
|
||||
ucal_openTimeZoneIDEnumeration(USystemTimeZoneType zoneType, const char* region,
|
||||
const int32_t* rawOffset, UErrorCode* ec);
|
||||
|
||||
/**
|
||||
* Create an enumeration over all time zones.
|
||||
*
|
||||
|
@ -185,7 +185,7 @@ parseDate (const UChar *text, UErrorCode &status) {
|
||||
}
|
||||
|
||||
UnicodeString& U_EXPORT2
|
||||
ZoneMeta::getCanonicalSystemID(const UnicodeString &tzid, UnicodeString &systemID, UErrorCode& status) {
|
||||
ZoneMeta::getCanonicalCLDRID(const UnicodeString &tzid, UnicodeString &systemID, UErrorCode& status) {
|
||||
int32_t len = tzid.length();
|
||||
if ( len >= ZID_KEY_MAX ) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
@ -348,27 +348,11 @@ ZoneMeta::getSingleCountry(const UnicodeString &tzid, UnicodeString &country) {
|
||||
char buf[] = {0, 0, 0};
|
||||
u_UCharsToChars(region, buf, 2);
|
||||
|
||||
StringEnumeration *ids = TimeZone::createEnumeration(buf);
|
||||
StringEnumeration *ids = TimeZone::createTimeZoneIDEnumeration(UCAL_ZONE_TYPE_CANONICAL_LOCATION, buf, NULL, status);
|
||||
int32_t idsLen = ids->count(status);
|
||||
if (U_SUCCESS(status) && idsLen > 1) {
|
||||
// multiple zones are available for the region
|
||||
UnicodeString canonical, tmp;
|
||||
const UnicodeString *id = ids->snext(status);
|
||||
getCanonicalSystemID(*id, canonical, status);
|
||||
if (U_SUCCESS(status)) {
|
||||
// check if there are any other canonical zone in the group
|
||||
while ((id = ids->snext(status))!=NULL) {
|
||||
getCanonicalSystemID(*id, tmp, status);
|
||||
if (U_FAILURE(status)) {
|
||||
break;
|
||||
}
|
||||
if (canonical != tmp) {
|
||||
// another canonical zone was found
|
||||
multiZones = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// multiple canonical zones are available for the region
|
||||
multiZones = TRUE;
|
||||
}
|
||||
if (U_FAILURE(status)) {
|
||||
// no single country by default for any error cases
|
||||
@ -519,7 +503,7 @@ ZoneMeta::createMetazoneMappings(const UnicodeString &tzid) {
|
||||
UnicodeString canonicalID;
|
||||
UResourceBundle *rb = ures_openDirect(NULL, gMetaZones, &status);
|
||||
ures_getByKey(rb, gMetazoneInfo, rb, &status);
|
||||
TimeZone::getCanonicalID(tzid, canonicalID, status);
|
||||
getCanonicalCLDRID(tzid, canonicalID, status);
|
||||
|
||||
if (U_SUCCESS(status)) {
|
||||
char tzKey[ZID_KEY_MAX];
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2007-2010, International Business Machines Corporation and *
|
||||
* Copyright (C) 2007-2011, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
@ -27,10 +27,13 @@ class UVector;
|
||||
class U_I18N_API ZoneMeta {
|
||||
public:
|
||||
/**
|
||||
* Return the canonical id for this system tzid, which might be the id itself.
|
||||
* If the given system tzid is not know, U_ILLEGAL_ARGUMENT_ERROR is set in the status.
|
||||
* Return the canonical id for this tzid defined by CLDR, which might be the id itself.
|
||||
* If the given system tzid is not known, U_ILLEGAL_ARGUMENT_ERROR is set in the status.
|
||||
*
|
||||
* Note: this internal API supports all known system IDs and "Etc/Unknown" (which is
|
||||
* NOT a system ID).
|
||||
*/
|
||||
static UnicodeString& U_EXPORT2 getCanonicalSystemID(const UnicodeString &tzid, UnicodeString &systemID, UErrorCode& status);
|
||||
static UnicodeString& U_EXPORT2 getCanonicalCLDRID(const UnicodeString &tzid, UnicodeString &systemID, UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Return the canonical country code for this tzid. If we have none, or if the time zone
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
||||
/********************************************************************
|
||||
* Copyright (c) 1997-2010, International Business Machines
|
||||
* Copyright (c) 1997-2011, International Business Machines
|
||||
* Corporation and others. All Rights Reserved.
|
||||
********************************************************************
|
||||
*
|
||||
@ -123,12 +123,36 @@ static void TestCalendar()
|
||||
status=U_ZERO_ERROR;
|
||||
#endif
|
||||
|
||||
/*Test ucal_openTimeZones & ucal_openCountryTimeZones*/
|
||||
for (j=0; j<2; ++j) {
|
||||
const char* api = (j==0) ? "ucal_openTimeZones()" :
|
||||
"ucal_openCountryTimeZones(US)";
|
||||
uenum = (j==0) ? ucal_openTimeZones(&status) :
|
||||
ucal_openCountryTimeZones("US", &status);
|
||||
/*Test ucal_openTimeZones, ucal_openCountryTimeZones and ucal_openTimeZoneIDEnumeration */
|
||||
for (j=0; j<6; ++j) {
|
||||
const char *api;
|
||||
const int32_t offsetMinus5 = -5*60*60*1000;
|
||||
switch (j) {
|
||||
case 0:
|
||||
api = "ucal_openTimeZones()";
|
||||
uenum = ucal_openTimeZones(&status);
|
||||
break;
|
||||
case 1:
|
||||
api = "ucal_openCountryTimeZones(US)";
|
||||
uenum = ucal_openCountryTimeZones("US", &status);
|
||||
break;
|
||||
case 2:
|
||||
api = "ucal_openTimeZoneIDEnumerarion(UCAL_ZONE_TYPE_CANONICAL, NULL, NULL)";
|
||||
uenum = ucal_openTimeZoneIDEnumeration(UCAL_ZONE_TYPE_CANONICAL, NULL, NULL, &status);
|
||||
break;
|
||||
case 3:
|
||||
api = "ucal_openTimeZoneIDEnumerarion(UCAL_ZONE_TYPE_CANONICAL_LOCATION, CA, NULL)";
|
||||
uenum = ucal_openTimeZoneIDEnumeration(UCAL_ZONE_TYPE_CANONICAL_LOCATION, "CA", NULL, &status);
|
||||
break;
|
||||
case 4:
|
||||
api = "ucal_openTimeZoneIDEnumerarion(UCAL_ZONE_TYPE_ANY, NULL, -5 hour)";
|
||||
uenum = ucal_openTimeZoneIDEnumeration(UCAL_ZONE_TYPE_ANY, NULL, &offsetMinus5, &status);
|
||||
break;
|
||||
case 5:
|
||||
api = "ucal_openTimeZoneIDEnumerarion(UCAL_ZONE_TYPE_ANY, US, -5 hour)";
|
||||
uenum = ucal_openTimeZoneIDEnumeration(UCAL_ZONE_TYPE_ANY, "US", &offsetMinus5, &status);
|
||||
break;
|
||||
}
|
||||
if (U_FAILURE(status)) {
|
||||
log_err("FAIL: %s failed with %s", api,
|
||||
u_errorName(status));
|
||||
|
@ -62,7 +62,8 @@ void TimeZoneTest::runIndexedTest( int32_t index, UBool exec, const char* &name,
|
||||
CASE(16, TestCanonicalID);
|
||||
CASE(17, TestDisplayNamesMeta);
|
||||
CASE(18, TestGetRegion);
|
||||
default: name = ""; break;
|
||||
CASE(19, TestGetAvailableIDsNew);
|
||||
default: name = ""; break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -510,6 +511,234 @@ TimeZoneTest::TestGetAvailableIDs913()
|
||||
delete s;
|
||||
}
|
||||
|
||||
void
|
||||
TimeZoneTest::TestGetAvailableIDsNew()
|
||||
{
|
||||
UErrorCode ec = U_ZERO_ERROR;
|
||||
StringEnumeration *any, *canonical, *canonicalLoc;
|
||||
StringEnumeration *any_US, *canonical_US, *canonicalLoc_US;
|
||||
StringEnumeration *any_W5, *any_CA_W5;
|
||||
StringEnumeration *any_US_E14;
|
||||
int32_t rawOffset;
|
||||
const UnicodeString *id1, *id2;
|
||||
UnicodeString canonicalID;
|
||||
UBool isSystemID;
|
||||
char region[4];
|
||||
int32_t zoneCount;
|
||||
|
||||
any = TimeZone::createTimeZoneIDEnumeration(UCAL_ZONE_TYPE_ANY, NULL, NULL, ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
errln("Failed to create enumration for ANY");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
canonical = TimeZone::createTimeZoneIDEnumeration(UCAL_ZONE_TYPE_CANONICAL, NULL, NULL, ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
errln("Failed to create enumration for CANONICAL");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
canonicalLoc = TimeZone::createTimeZoneIDEnumeration(UCAL_ZONE_TYPE_CANONICAL_LOCATION, NULL, NULL, ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
errln("Failed to create enumration for CANONICALLOC");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
any_US = TimeZone::createTimeZoneIDEnumeration(UCAL_ZONE_TYPE_ANY, "US", NULL, ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
errln("Failed to create enumration for ANY_US");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
canonical_US = TimeZone::createTimeZoneIDEnumeration(UCAL_ZONE_TYPE_CANONICAL, "US", NULL, ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
errln("Failed to create enumration for CANONICAL_US");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
canonicalLoc_US = TimeZone::createTimeZoneIDEnumeration(UCAL_ZONE_TYPE_CANONICAL_LOCATION, "US", NULL, ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
errln("Failed to create enumration for CANONICALLOC_US");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
rawOffset = (-5)*60*60*1000;
|
||||
any_W5 = TimeZone::createTimeZoneIDEnumeration(UCAL_ZONE_TYPE_ANY, NULL, &rawOffset, ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
errln("Failed to create enumration for ANY_W5");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
any_CA_W5 = TimeZone::createTimeZoneIDEnumeration(UCAL_ZONE_TYPE_ANY, "CA", &rawOffset, ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
errln("Failed to create enumration for ANY_CA_W5");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
rawOffset = 14*60*60*1000;
|
||||
any_US_E14 = TimeZone::createTimeZoneIDEnumeration(UCAL_ZONE_TYPE_ANY, "US", &rawOffset, ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
errln("Failed to create enumration for ANY_US_E14");
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
checkContainsAll(any, "ANY", canonical, "CANONICAL");
|
||||
checkContainsAll(canonical, "CANONICAL", canonicalLoc, "CANONICALLOC");
|
||||
|
||||
checkContainsAll(any, "ANY", any_US, "ANY_US");
|
||||
checkContainsAll(canonical, "CANONICAL", canonical_US, "CANONICAL_US");
|
||||
checkContainsAll(canonicalLoc, "CANONICALLOC", canonicalLoc_US, "CANONICALLOC_US");
|
||||
|
||||
checkContainsAll(any_US, "ANY_US", canonical_US, "CANONICAL_US");
|
||||
checkContainsAll(canonical_US, "CANONICAL_US", canonicalLoc_US, "CANONICALLOC_US");
|
||||
|
||||
checkContainsAll(any, "ANY", any_W5, "ANY_W5");
|
||||
checkContainsAll(any_W5, "ANY_W5", any_CA_W5, "ANY_CA_W5");
|
||||
|
||||
// And ID in any set, but not in canonical set must not be a canonical ID
|
||||
any->reset(ec);
|
||||
while (id1 = any->snext(ec)) {
|
||||
UBool found = FALSE;
|
||||
canonical->reset(ec);
|
||||
while (id2 = canonical->snext(ec)) {
|
||||
if (*id1 == *id2) {
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (U_FAILURE(ec)) {
|
||||
break;
|
||||
}
|
||||
if (!found) {
|
||||
TimeZone::getCanonicalID(*id1, canonicalID, isSystemID, ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
break;
|
||||
}
|
||||
if (*id1 == canonicalID) {
|
||||
errln((UnicodeString)"FAIL: canonicalID [" + *id1 + "] is not in CANONICAL");
|
||||
}
|
||||
if (!isSystemID) {
|
||||
errln((UnicodeString)"FAIL: ANY contains non-system ID: " + *id1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (U_FAILURE(ec)) {
|
||||
errln("Error checking IDs in ANY, but not in CANONICAL");
|
||||
ec = U_ZERO_ERROR;
|
||||
}
|
||||
|
||||
// canonical set must contains only canonical IDs
|
||||
canonical->reset(ec);
|
||||
while (id1 = canonical->snext(ec)) {
|
||||
TimeZone::getCanonicalID(*id1, canonicalID, isSystemID, ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
break;
|
||||
}
|
||||
if (*id1 != canonicalID) {
|
||||
errln((UnicodeString)"FAIL: CANONICAL contains non-canonical ID: " + *id1);
|
||||
}
|
||||
if (!isSystemID) {
|
||||
errln((UnicodeString)"FAILE: CANONICAL contains non-system ID: " + *id1);
|
||||
}
|
||||
}
|
||||
if (U_FAILURE(ec)) {
|
||||
errln("Error checking IDs in CANONICAL");
|
||||
ec = U_ZERO_ERROR;
|
||||
}
|
||||
|
||||
// canonicalLoc set must contain only canonical location IDs
|
||||
canonicalLoc->reset(ec);
|
||||
while (id1 = canonicalLoc->snext(ec)) {
|
||||
TimeZone::getRegion(*id1, region, sizeof(region), ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
break;
|
||||
}
|
||||
if (uprv_strcmp(region, "001") == 0) {
|
||||
errln((UnicodeString)"FAIL: CANONICALLOC contains non location zone: " + *id1);
|
||||
}
|
||||
}
|
||||
if (U_FAILURE(ec)) {
|
||||
errln("Error checking IDs in CANONICALLOC");
|
||||
ec = U_ZERO_ERROR;
|
||||
}
|
||||
|
||||
// any_US must contain only US zones
|
||||
any_US->reset(ec);
|
||||
while (id1 = any_US->snext(ec)) {
|
||||
TimeZone::getRegion(*id1, region, sizeof(region), ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
break;
|
||||
}
|
||||
if (uprv_strcmp(region, "US") != 0) {
|
||||
errln((UnicodeString)"FAIL: ANY_US contains non-US zone ID: " + *id1);
|
||||
}
|
||||
}
|
||||
if (U_FAILURE(ec)) {
|
||||
errln("Error checking IDs in ANY_US");
|
||||
ec = U_ZERO_ERROR;
|
||||
}
|
||||
|
||||
// any_W5 must contain only GMT-05:00 zones
|
||||
any_W5->reset(ec);
|
||||
while (id1 = any_W5->snext(ec)) {
|
||||
TimeZone *tz = TimeZone::createTimeZone(*id1);
|
||||
if (tz->getRawOffset() != (-5)*60*60*1000) {
|
||||
errln((UnicodeString)"FAIL: ANY_W5 contains a zone whose offset is not -05:00: " + *id1);
|
||||
}
|
||||
}
|
||||
if (U_FAILURE(ec)) {
|
||||
errln("Error checking IDs in ANY_W5");
|
||||
ec = U_ZERO_ERROR;
|
||||
}
|
||||
|
||||
// No US zone swith GMT+14:00
|
||||
zoneCount = any_US_E14->count(ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
errln("Error checking IDs in ANY_US_E14");
|
||||
ec = U_ZERO_ERROR;
|
||||
} else if (zoneCount != 0) {
|
||||
errln("FAIL: ANY_US_E14 must be empty");
|
||||
}
|
||||
|
||||
cleanup:
|
||||
delete any;
|
||||
delete canonical;
|
||||
delete canonicalLoc;
|
||||
delete any_US;
|
||||
delete canonical_US;
|
||||
delete canonicalLoc_US;
|
||||
delete any_W5;
|
||||
delete any_CA_W5;
|
||||
}
|
||||
|
||||
void
|
||||
TimeZoneTest::checkContainsAll(StringEnumeration *s1, const char *name1,
|
||||
StringEnumeration *s2, const char *name2)
|
||||
{
|
||||
UErrorCode ec = U_ZERO_ERROR;
|
||||
const UnicodeString *id1, *id2;
|
||||
|
||||
s2->reset(ec);
|
||||
|
||||
while (id2 = s2->snext(ec)) {
|
||||
UBool found = FALSE;
|
||||
s1->reset(ec);
|
||||
while (id1 = s1->snext(ec)) {
|
||||
if (*id1 == *id2) {
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
errln((UnicodeString)"FAIL: " + name1 + "does not contain "
|
||||
+ *id2 + " in " + name2);
|
||||
}
|
||||
}
|
||||
|
||||
if (U_FAILURE(ec)) {
|
||||
errln((UnicodeString)"Error checkContainsAll for " + name1 + " - " + name2);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* NOTE: As of ICU 2.8, this test confirms that the "tz.alias"
|
||||
@ -1847,6 +2076,7 @@ void TimeZoneTest::TestCanonicalID() {
|
||||
{"GMT-091015", "GMT-09:10:15", FALSE},
|
||||
{"GMT+1:90", 0, FALSE},
|
||||
{"America/Argentina/Buenos_Aires", "America/Buenos_Aires", TRUE},
|
||||
{"Etc/Unknown", "Etc/Unknown", FALSE},
|
||||
{"bogus", 0, FALSE},
|
||||
{"", 0, FALSE},
|
||||
{0, 0, FALSE}
|
||||
|
@ -37,6 +37,8 @@ public:
|
||||
*/
|
||||
virtual void TestGetAvailableIDs913(void);
|
||||
|
||||
virtual void TestGetAvailableIDsNew(void);
|
||||
|
||||
/**
|
||||
* Generic API testing for API coverage.
|
||||
*/
|
||||
@ -105,6 +107,9 @@ private:
|
||||
// when year/rule are changed.
|
||||
static const int32_t REFERENCE_YEAR;
|
||||
static const char *REFERENCE_DATA_VERSION;
|
||||
|
||||
void checkContainsAll(StringEnumeration *s1, const char *name1,
|
||||
StringEnumeration *s2, const char *name2);
|
||||
};
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
Loading…
Reference in New Issue
Block a user