int32_t U_EXPORT2 TimeZone::countEquivalentIDs(const UnicodeString& id) { int32_t result = 0; UErrorCode ec = U_ZERO_ERROR; UResourceBundle res; ures_initStackObject(&res); U_DEBUG_TZ_MSG(("countEquivalentIDs..\n")); UResourceBundle *top = openOlsonResource(id, res, ec); if (U_SUCCESS(ec)) { int32_t size = ures_getSize(&res); U_DEBUG_TZ_MSG(("cEI: success (size %d, key %s)..\n", size, ures_getKey(&res))); if (size == 4 || size == 6) { UResourceBundle r; ures_initStackObject(&r); ures_getByIndex(&res, size-1, &r, &ec); //result = ures_getSize(&r); // doesn't work ures_getIntVector(&r, &result, &ec); U_DEBUG_TZ_MSG(("ceI: result %d, err %s\n", result, u_errorName(ec))); ures_close(&r); } } else { U_DEBUG_TZ_MSG(("cEI: fail, %s\n", u_errorName(ec))); } ures_close(&res); ures_close(top); return result; }
TimeZone* TimeZone::createSystemTimeZone(const UnicodeString& id) { TimeZone* z = 0; UErrorCode ec = U_ZERO_ERROR; UResourceBundle res; ures_initStackObject(&res); U_DEBUG_TZ_MSG(("pre-err=%s\n", u_errorName(ec))); UResourceBundle *top = openOlsonResource(id, res, ec); U_DEBUG_TZ_MSG(("post-err=%s\n", u_errorName(ec))); if (U_SUCCESS(ec)) { z = new OlsonTimeZone(top, &res, ec); if (z) { z->setID(id); } else { U_DEBUG_TZ_MSG(("cstz: olson time zone failed to initialize - err %s\n", u_errorName(ec))); } } ures_close(&res); ures_close(top); if (U_FAILURE(ec)) { U_DEBUG_TZ_MSG(("cstz: failed to create, err %s\n", u_errorName(ec))); delete z; z = 0; } return z; }
static UResourceBundle* getZoneByName(const UResourceBundle* top, const UnicodeString& id, UResourceBundle *oldbundle, UErrorCode& status) { // load the Rules object UResourceBundle *tmp = ures_getByKey(top, kNAMES, NULL, &status); // search for the string int32_t idx = findInStringArray(tmp, id, status); if((idx == -1) && U_SUCCESS(status)) { // not found status = U_MISSING_RESOURCE_ERROR; //ures_close(oldbundle); //oldbundle = NULL; } else { U_DEBUG_TZ_MSG(("gzbn: oldbundle= size %d, type %d, %s\n", ures_getSize(tmp), ures_getType(tmp), u_errorName(status))); tmp = ures_getByKey(top, kZONES, tmp, &status); // get Zones object from top U_DEBUG_TZ_MSG(("gzbn: loaded ZONES, size %d, type %d, path %s %s\n", ures_getSize(tmp), ures_getType(tmp), ures_getPath(tmp), u_errorName(status))); oldbundle = ures_getByIndex(tmp, idx, oldbundle, &status); // get nth Zone object U_DEBUG_TZ_MSG(("gzbn: loaded z#%d, size %d, type %d, path %s, %s\n", idx, ures_getSize(oldbundle), ures_getType(oldbundle), ures_getPath(oldbundle), u_errorName(status))); } ures_close(tmp); if(U_FAILURE(status)) { //ures_close(oldbundle); return NULL; } else { return oldbundle; } }
TimeZone* U_EXPORT2 TimeZone::createTimeZone(const UnicodeString& ID) { /* We first try to lookup the zone ID in our system list. If this * fails, we try to parse it as a custom string GMT[+-]hh:mm. If * all else fails, we return GMT, which is probably not what the * user wants, but at least is a functioning TimeZone object. * * We cannot return NULL, because that would break compatibility * with the JDK. */ TimeZone* result = createSystemTimeZone(ID); if (result == 0) { U_DEBUG_TZ_MSG(("failed to load system time zone with id - falling to custom")); result = createCustomTimeZone(ID); } if (result == 0) { U_DEBUG_TZ_MSG(("failed to load time zone with id - falling to GMT")); const TimeZone* temptz = getGMT(); if (temptz == NULL) { result = NULL; } else { result = temptz->clone(); } } return result; }
UResourceBundle* TimeZone::loadRule(const UResourceBundle* top, const UnicodeString& ruleid, UResourceBundle* oldbundle, UErrorCode& status) { char key[64]; ruleid.extract(0, sizeof(key)-1, key, (int32_t)sizeof(key)-1, US_INV); U_DEBUG_TZ_MSG(("loadRule(%s)\n", key)); UResourceBundle *r = ures_getByKey(top, kRULES, oldbundle, &status); U_DEBUG_TZ_MSG(("loadRule(%s) -> kRULES [%s]\n", key, u_errorName(status))); r = ures_getByKey(r, key, r, &status); U_DEBUG_TZ_MSG(("loadRule(%s) -> item [%s]\n", key, u_errorName(status))); return r; }
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); } 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); if (U_FAILURE(ec)) { break; } if (u_strcmp(uCountry, region) == 0) { map[idx++] = i; } } if (U_SUCCESS(ec)) { len = count; } else { uprv_free(map); map = NULL; } } else { U_DEBUG_TZ_MSG(("Failed to load tz for region %s: %s\n", country, u_errorName(ec))); } } } ures_close(res); }
const UnicodeString U_EXPORT2 TimeZone::getEquivalentID(const UnicodeString& id, int32_t index) { U_DEBUG_TZ_MSG(("gEI(%d)\n", index)); UnicodeString result; UErrorCode ec = U_ZERO_ERROR; UResourceBundle res; ures_initStackObject(&res); UResourceBundle *top = openOlsonResource(id, res, ec); int32_t zone = -1; if (U_SUCCESS(ec)) { int32_t size = ures_getSize(&res); if (size == 4 || size == 6) { UResourceBundle r; ures_initStackObject(&r); ures_getByIndex(&res, size-1, &r, &ec); const int32_t* v = ures_getIntVector(&r, &size, &ec); if (index >= 0 && index < size && getOlsonMeta()) { zone = v[index]; } ures_close(&r); } } ures_close(&res); if (zone >= 0) { UResourceBundle *ares = ures_getByKey(top, kNAMES, NULL, &ec); // dereference Zones section if (U_SUCCESS(ec)) { int32_t idLen = 0; const UChar* id = ures_getStringByIndex(ares, zone, &idLen, &ec); result.fastCopyFrom(UnicodeString(TRUE, id, idLen)); U_DEBUG_TZ_MSG(("gei(%d) -> %d, len%d, %s\n", index, zone, result.length(), u_errorName(ec))); } ures_close(ares); } ures_close(top); #if defined(U_DEBUG_TZ) if(result.length() ==0) { U_DEBUG_TZ_MSG(("equiv [__, #%d] -> 0 (%s)\n", index, u_errorName(ec))); } #endif return result; }
static UResourceBundle* openOlsonResource(const UnicodeString& id, UResourceBundle& res, UErrorCode& ec) { #if U_DEBUG_TZ char buf[128]; id.extract(0, sizeof(buf)-1, buf, sizeof(buf), ""); #endif UResourceBundle *top = ures_openDirect(0, kZONEINFO, &ec); U_DEBUG_TZ_MSG(("pre: res sz=%d\n", ures_getSize(&res))); /* &res = */ getZoneByName(top, id, &res, ec); // 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_getSize(&res) <= 1 && getOlsonMeta(top)) { 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 ures_getByIndex(ares, deref, &res, &ec); ures_close(ares); U_DEBUG_TZ_MSG(("alias to #%d (%s) - %s\n", deref, "??", u_errorName(ec))); } else { U_DEBUG_TZ_MSG(("not an alias - size %d\n", ures_getSize(&res))); } U_DEBUG_TZ_MSG(("%s - final status is %s\n", buf, u_errorName(ec))); return top; }
static int32_t findInStringArray(UResourceBundle* array, const UnicodeString& id, UErrorCode &status) { UnicodeString copy; const UChar *u; int32_t len; int32_t start = 0; int32_t limit = ures_getSize(array); int32_t mid; int32_t lastMid = INT32_MAX; if(U_FAILURE(status) || (limit < 1)) { return -1; } U_DEBUG_TZ_MSG(("fisa: Looking for %s, between %d and %d\n", U_DEBUG_TZ_STR(UnicodeString(id).getTerminatedBuffer()), start, limit)); for (;;) { mid = (int32_t)((start + limit) / 2); if (lastMid == mid) { /* Have we moved? */ break; /* We haven't moved, and it wasn't found. */ } lastMid = mid; u = ures_getStringByIndex(array, mid, &len, &status); if (U_FAILURE(status)) { break; } U_DEBUG_TZ_MSG(("tz: compare to %s, %d .. [%d] .. %d\n", U_DEBUG_TZ_STR(u), start, mid, limit)); copy.setTo(TRUE, u, len); int r = id.compare(copy); if(r==0) { U_DEBUG_TZ_MSG(("fisa: found at %d\n", mid)); return mid; } else if(r<0) { limit = mid; } else { start = mid; } } U_DEBUG_TZ_MSG(("fisa: not found\n")); return -1; }
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); }
int32_t U_EXPORT2 TimeZone::countEquivalentIDs(const UnicodeString& id) { int32_t result = 0; UErrorCode ec = U_ZERO_ERROR; UResourceBundle res; ures_initStackObject(&res); U_DEBUG_TZ_MSG(("countEquivalentIDs..\n")); UResourceBundle *top = openOlsonResource(id, res, ec); if (U_SUCCESS(ec)) { UResourceBundle r; ures_initStackObject(&r); ures_getByKey(&res, kLINKS, &r, &ec); ures_getIntVector(&r, &result, &ec); ures_close(&r); } ures_close(&res); ures_close(top); return result; }
TZEnumeration(const char* country) : map(NULL), len(0), pos(0) { if (!getOlsonMeta()) { return; } char key[] = {0, 0, 0, 0,0, 0, 0,0, 0, 0,0}; // e.g., "US", or "Default" for no country if (country) { uprv_strncat(key, country, 2); } else { uprv_strcpy(key, kDEFAULT); } UErrorCode ec = U_ZERO_ERROR; UResourceBundle *top = ures_openDirect(0, kZONEINFO, &ec); top = ures_getByKey(top, kREGIONS, top, &ec); // dereference 'Regions' section if (U_SUCCESS(ec)) { UResourceBundle res; ures_initStackObject(&res); ures_getByKey(top, key, &res, &ec); // The list of zones is a list of integers, from 0..n-1, // where n is the total number of system zones. const int32_t* v = ures_getIntVector(&res, &len, &ec); if (U_SUCCESS(ec)) { U_ASSERT(len > 0); map = (int32_t*)uprv_malloc(sizeof(int32_t) * len); if (map != 0) { for (uint16_t i=0; i<len; ++i) { U_ASSERT(v[i] >= 0 && v[i] < OLSON_ZONE_COUNT); map[i] = v[i]; } } } else { U_DEBUG_TZ_MSG(("Failed to load tz for region %s: %s\n", country, u_errorName(ec))); } ures_close(&res); } ures_close(top); }
//--------------------------------------- UnicodeString& TimeZone::getDisplayName(UBool daylight, EDisplayType style, const Locale& locale, UnicodeString& result) const { // SRL TODO: cache the SDF, just like java. UErrorCode status = U_ZERO_ERROR; #ifdef U_DEBUG_TZ char buf[128]; fID.extract(0, sizeof(buf)-1, buf, sizeof(buf), ""); #endif SimpleDateFormat format(style == LONG ? ZZZZ_STR : Z_STR, locale, status); U_DEBUG_TZ_MSG(("getDisplayName(%s)\n", buf)); if(!U_SUCCESS(status)) { #ifdef U_DEBUG_TZ char buf2[128]; result.extract(0, sizeof(buf2)-1, buf2, sizeof(buf2), ""); U_DEBUG_TZ_MSG(("getDisplayName(%s) -> %s\n", buf, buf2)); #endif return result.remove(); } UDate d = Calendar::getNow(); int32_t rawOffset; int32_t dstOffset; this->getOffset(d, FALSE, rawOffset, dstOffset, status); if (U_FAILURE(status)) { return result.remove(); } if ((daylight && dstOffset != 0) || (!daylight && dstOffset == 0)) { // Current time and the request (daylight / not daylight) agree. format.setTimeZone(*this); return format.format(d, result); } // Create a new SimpleTimeZone as a stand-in for this zone; the // stand-in will have no DST, or DST during July, but the same ID and offset, // and hence the same display name. // We don't cache these because they're small and cheap to create. UnicodeString tempID; getID(tempID); SimpleTimeZone *tz = NULL; if(daylight && useDaylightTime()){ // The display name for daylight saving time was requested, but currently not in DST // Set a fixed date (July 1) in this Gregorian year GregorianCalendar cal(*this, status); if (U_FAILURE(status)) { return result.remove(); } cal.set(UCAL_MONTH, UCAL_JULY); cal.set(UCAL_DATE, 1); // Get July 1 date d = cal.getTime(status); // Check if it is in DST if (cal.get(UCAL_DST_OFFSET, status) == 0) { // We need to create a fake time zone tz = new SimpleTimeZone(rawOffset, tempID, UCAL_JUNE, 1, 0, 0, UCAL_AUGUST, 1, 0, 0, getDSTSavings(), status); if (U_FAILURE(status) || tz == NULL) { if (U_SUCCESS(status)) { status = U_MEMORY_ALLOCATION_ERROR; } return result.remove(); } format.adoptTimeZone(tz); } else { format.setTimeZone(*this); } } else { // The display name for standard time was requested, but currently in DST // or display name for daylight saving time was requested, but this zone no longer // observes DST. tz = new SimpleTimeZone(rawOffset, tempID); if (U_FAILURE(status) || tz == NULL) { if (U_SUCCESS(status)) { status = U_MEMORY_ALLOCATION_ERROR; } return result.remove(); } format.adoptTimeZone(tz); } format.format(d, result, status); return result; }