1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* 2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************* 3b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho* Copyright (C) 2007-2011, International Business Machines Corporation and * 4b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* others. All Rights Reserved. * 5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************* 6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/ 7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/utypes.h" 9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_FORMATTING 11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "zonemeta.h" 13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/timezone.h" 15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/ustring.h" 16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/putil.h" 17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "umutex.h" 19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uvector.h" 20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cmemory.h" 21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "gregoimp.h" 22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cstring.h" 23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ucln_in.h" 2450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "uassert.h" 25b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "uresimp.h" 26b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "uhash.h" 27b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "olsontz.h" 28b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 29b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UMTX gZoneMetaLock = NULL; 3050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 31b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// CLDR Canonical ID mapping table 32b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic UHashtable *gCanonicalIDCache = NULL; 33b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic UBool gCanonicalIDCacheInitialized = FALSE; 34b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 3550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// Metazone mapping table 36b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UHashtable *gOlsonToMeta = NULL; 37b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool gOlsonToMetaInitialized = FALSE; 38b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 39b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// Available metazone IDs vector and table 40b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic U_NAMESPACE_QUALIFIER UVector *gMetaZoneIDs = NULL; 41b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic UHashtable *gMetaZoneIDTable = NULL; 42b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic UBool gMetaZoneIDsInitialized = FALSE; 43b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 4450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// Country info vectors 4550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic U_NAMESPACE_QUALIFIER UVector *gSingleZoneCountries = NULL; 4650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic U_NAMESPACE_QUALIFIER UVector *gMultiZonesCountries = NULL; 4750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic UBool gCountryInfoVectorsInitialized = FALSE; 48b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 4950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CDECL_BEGIN 50b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 51b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Cleanup callback func 53b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool U_CALLCONV zoneMeta_cleanup(void) 55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 56b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho umtx_destroy(&gZoneMetaLock); 57b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 58b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (gCanonicalIDCache != NULL) { 59b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uhash_close(gCanonicalIDCache); 60b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho gCanonicalIDCache = NULL; 61b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 62b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho gCanonicalIDCacheInitialized = FALSE; 63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (gOlsonToMeta != NULL) { 65b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uhash_close(gOlsonToMeta); 66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru gOlsonToMeta = NULL; 67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 68b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru gOlsonToMetaInitialized = FALSE; 69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 70b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (gMetaZoneIDTable != NULL) { 71b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uhash_close(gMetaZoneIDTable); 72b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 73b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // delete after closing gMetaZoneIDTable, because it holds 74b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // value objects held by the hashtable 75b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho delete gMetaZoneIDs; 76b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho gMetaZoneIDsInitialized = FALSE; 77b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 7850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho delete gSingleZoneCountries; 7950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho delete gMultiZonesCountries; 8050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho gCountryInfoVectorsInitialized = FALSE; 81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return TRUE; 83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 86b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * Deleter for UChar* string 87b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */ 88b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void U_CALLCONV 89b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QuerudeleteUCharString(void *obj) { 90b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UChar *entry = (UChar*)obj; 91b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(entry); 92b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 93b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 94b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/** 95b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Deleter for UVector 96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void U_CALLCONV 98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerudeleteUVector(void *obj) { 99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru delete (U_NAMESPACE_QUALIFIER UVector*) obj; 100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Deleter for OlsonToMetaMappingEntry 104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void U_CALLCONV 106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerudeleteOlsonToMetaMappingEntry(void *obj) { 107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru U_NAMESPACE_QUALIFIER OlsonToMetaMappingEntry *entry = (U_NAMESPACE_QUALIFIER OlsonToMetaMappingEntry*)obj; 108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_free(entry); 109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_END 112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_BEGIN 114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ZID_KEY_MAX 128 116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 11750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const char gMetaZones[] = "metaZones"; 11850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const char gMetazoneInfo[] = "metazoneInfo"; 119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char gMapTimezonesTag[] = "mapTimezones"; 120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 12127f654740f2a26ad62a5c155af9199af9e69b889clairehostatic const char gTimeZoneTypes[] = "timezoneTypes"; 12250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const char gTypeAliasTag[] = "typeAlias"; 12327f654740f2a26ad62a5c155af9199af9e69b889clairehostatic const char gTypeMapTag[] = "typeMap"; 12450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const char gTimezoneTag[] = "timezone"; 125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 12650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const char gWorldTag[] = "001"; 127b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const UChar gWorld[] = {0x30, 0x30, 0x31, 0x00}; // "001" 129b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 13050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const UChar gDefaultFrom[] = {0x31, 0x39, 0x37, 0x30, 0x2D, 0x30, 0x31, 0x2D, 0x30, 0x31, 13150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 0x20, 0x30, 0x30, 0x3A, 0x30, 0x30, 0x00}; // "1970-01-01 00:00" 13250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const UChar gDefaultTo[] = {0x39, 0x39, 0x39, 0x39, 0x2D, 0x31, 0x32, 0x2D, 0x33, 0x31, 13350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 0x20, 0x32, 0x33, 0x3A, 0x35, 0x39, 0x00}; // "9999-12-31 23:59" 13450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ASCII_DIGIT(c) (((c)>=0x30 && (c)<=0x39) ? (c)-0x30 : -1) 136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* 138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Convert a date string used by metazone mappings to UDate. 139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * The format used by CLDR metazone mapping is "yyyy-MM-dd HH:mm". 140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 141c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querustatic UDate 142c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruparseDate (const UChar *text, UErrorCode &status) { 143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t len = u_strlen(text); 147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (len != 16 && len != 10) { 148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // It must be yyyy-MM-dd HH:mm (length 16) or yyyy-MM-dd (length 10) 149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_INVALID_FORMAT_ERROR; 150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t year = 0, month = 0, day = 0, hour = 0, min = 0, n; 154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t idx; 155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // "yyyy" (0 - 3) 157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (idx = 0; idx <= 3 && U_SUCCESS(status); idx++) { 158b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru n = ASCII_DIGIT((int32_t)text[idx]); 159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (n >= 0) { 160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru year = 10*year + n; 161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_INVALID_FORMAT_ERROR; 163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // "MM" (5 - 6) 166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (idx = 5; idx <= 6 && U_SUCCESS(status); idx++) { 167b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru n = ASCII_DIGIT((int32_t)text[idx]); 168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (n >= 0) { 169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru month = 10*month + n; 170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_INVALID_FORMAT_ERROR; 172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // "dd" (8 - 9) 175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (idx = 8; idx <= 9 && U_SUCCESS(status); idx++) { 176b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru n = ASCII_DIGIT((int32_t)text[idx]); 177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (n >= 0) { 178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru day = 10*day + n; 179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_INVALID_FORMAT_ERROR; 181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (len == 16) { 184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // "HH" (11 - 12) 185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (idx = 11; idx <= 12 && U_SUCCESS(status); idx++) { 186b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru n = ASCII_DIGIT((int32_t)text[idx]); 187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (n >= 0) { 188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru hour = 10*hour + n; 189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_INVALID_FORMAT_ERROR; 191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // "mm" (14 - 15) 194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (idx = 14; idx <= 15 && U_SUCCESS(status); idx++) { 195b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru n = ASCII_DIGIT((int32_t)text[idx]); 196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (n >= 0) { 197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru min = 10*min + n; 198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_INVALID_FORMAT_ERROR; 200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_SUCCESS(status)) { 205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UDate date = Grego::fieldsToDay(year, month - 1, day) * U_MILLIS_PER_DAY 206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru + hour * U_MILLIS_PER_HOUR + min * U_MILLIS_PER_MINUTE; 207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return date; 208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 212b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UChar* U_EXPORT2 213b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZoneMeta::getCanonicalCLDRID(const UnicodeString &tzid, UErrorCode& status) { 214b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_FAILURE(status)) { 215b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return NULL; 216b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 217b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 21827f654740f2a26ad62a5c155af9199af9e69b889claireho int32_t len = tzid.length(); 219b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (len > ZID_KEY_MAX) { 22027f654740f2a26ad62a5c155af9199af9e69b889claireho status = U_ILLEGAL_ARGUMENT_ERROR; 221b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return NULL; 222b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 223b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 224b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Checking the cached results 225b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UBool initialized; 226b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UMTX_CHECK(&gZoneMetaLock, gCanonicalIDCacheInitialized, initialized); 227b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (!initialized) { 228b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Create empty hashtable 229b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho umtx_lock(&gZoneMetaLock); 230b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho { 231b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (!gCanonicalIDCacheInitialized) { 232b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho gCanonicalIDCache = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status); 233b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (gCanonicalIDCache == NULL) { 234b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho status = U_MEMORY_ALLOCATION_ERROR; 235b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 236b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_FAILURE(status)) { 237b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho gCanonicalIDCache = NULL; 238b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return NULL; 239b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 240b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // No key/value deleters - keys/values are from a resource bundle 241b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho gCanonicalIDCacheInitialized = TRUE; 242b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho ucln_i18n_registerCleanup(UCLN_I18N_ZONEMETA, zoneMeta_cleanup); 243b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 244b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 245b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho umtx_unlock(&gZoneMetaLock); 246b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 247b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 248b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UChar *canonicalID = NULL; 249b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 250b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UErrorCode tmpStatus = U_ZERO_ERROR; 251b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UChar utzid[ZID_KEY_MAX + 1]; 252b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho tzid.extract(utzid, ZID_KEY_MAX + 1, tmpStatus); 253b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho U_ASSERT(tmpStatus == U_ZERO_ERROR); // we checked the length of tzid already 254b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 255b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Check if it was already cached 256b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho umtx_lock(&gZoneMetaLock); 257b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho { 258b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho canonicalID = (const UChar *)uhash_get(gCanonicalIDCache, utzid); 25927f654740f2a26ad62a5c155af9199af9e69b889claireho } 260b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho umtx_unlock(&gZoneMetaLock); 261c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru 262b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (canonicalID != NULL) { 263b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return canonicalID; 264b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 265b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 266b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // If not, resolve CLDR canonical ID with resource data 267b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UBool isInputCanonical = FALSE; 268b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho char id[ZID_KEY_MAX + 1]; 26927f654740f2a26ad62a5c155af9199af9e69b889claireho const UChar* idChars = tzid.getBuffer(); 27027f654740f2a26ad62a5c155af9199af9e69b889claireho 27127f654740f2a26ad62a5c155af9199af9e69b889claireho u_UCharsToChars(idChars,id,len); 27227f654740f2a26ad62a5c155af9199af9e69b889claireho id[len] = (char) 0; // Make sure it is null terminated. 27327f654740f2a26ad62a5c155af9199af9e69b889claireho 27427f654740f2a26ad62a5c155af9199af9e69b889claireho // replace '/' with ':' 27527f654740f2a26ad62a5c155af9199af9e69b889claireho char *p = id; 27627f654740f2a26ad62a5c155af9199af9e69b889claireho while (*p++) { 27727f654740f2a26ad62a5c155af9199af9e69b889claireho if (*p == '/') { 27827f654740f2a26ad62a5c155af9199af9e69b889claireho *p = ':'; 27950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 28127f654740f2a26ad62a5c155af9199af9e69b889claireho 28227f654740f2a26ad62a5c155af9199af9e69b889claireho UResourceBundle *top = ures_openDirect(NULL, gTimeZoneTypes, &tmpStatus); 28327f654740f2a26ad62a5c155af9199af9e69b889claireho UResourceBundle *rb = ures_getByKey(top, gTypeMapTag, NULL, &tmpStatus); 28427f654740f2a26ad62a5c155af9199af9e69b889claireho ures_getByKey(rb, gTimezoneTag, rb, &tmpStatus); 28527f654740f2a26ad62a5c155af9199af9e69b889claireho ures_getByKey(rb, id, rb, &tmpStatus); 28627f654740f2a26ad62a5c155af9199af9e69b889claireho if (U_SUCCESS(tmpStatus)) { 287b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // type entry (canonical) found 288b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // the input is the canonical ID. resolve to const UChar* 289b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho canonicalID = TimeZone::findID(tzid); 290b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho isInputCanonical = TRUE; 29127f654740f2a26ad62a5c155af9199af9e69b889claireho } 29227f654740f2a26ad62a5c155af9199af9e69b889claireho 293b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (canonicalID == NULL) { 294b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // If a map element not found, then look for an alias 295b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho tmpStatus = U_ZERO_ERROR; 296b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho ures_getByKey(top, gTypeAliasTag, rb, &tmpStatus); 297b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho ures_getByKey(rb, gTimezoneTag, rb, &tmpStatus); 298b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UChar *canonical = ures_getStringByKey(rb,id,NULL,&tmpStatus); 299b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_SUCCESS(tmpStatus)) { 300b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // canonical map found 301b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho canonicalID = canonical; 302b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 30327f654740f2a26ad62a5c155af9199af9e69b889claireho 304b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (canonicalID == NULL) { 305b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Dereference the input ID using the tz data 306b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UChar *derefer = TimeZone::dereferOlsonLink(tzid); 307b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (derefer == NULL) { 308b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho status = U_ILLEGAL_ARGUMENT_ERROR; 309b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 310b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho len = u_strlen(derefer); 311b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho u_UCharsToChars(derefer,id,len); 312b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho id[len] = (char) 0; // Make sure it is null terminated. 313b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 314b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // replace '/' with ':' 315b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho char *p = id; 316b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho while (*p++) { 317b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (*p == '/') { 318b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho *p = ':'; 319b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 320b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 32127f654740f2a26ad62a5c155af9199af9e69b889claireho 322b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // If a dereference turned something up then look for an alias. 323b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // rb still points to the alias table, so we don't have to go looking 324b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // for it. 325b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho tmpStatus = U_ZERO_ERROR; 326b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho canonical = ures_getStringByKey(rb,id,NULL,&tmpStatus); 327b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_SUCCESS(tmpStatus)) { 328b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // canonical map for the dereferenced ID found 329b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho canonicalID = canonical; 330b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 331b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho canonicalID = derefer; 332b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho isInputCanonical = TRUE; 333b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 33427f654740f2a26ad62a5c155af9199af9e69b889claireho } 33527f654740f2a26ad62a5c155af9199af9e69b889claireho } 336b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 337b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho ures_close(rb); 338b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho ures_close(top); 33927f654740f2a26ad62a5c155af9199af9e69b889claireho 340b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_SUCCESS(status)) { 341b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho U_ASSERT(canonicalID != NULL); // canocanilD must be non-NULL here 342b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 343b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Put the resolved canonical ID to the cache 344b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho umtx_lock(&gZoneMetaLock); 345b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho { 346b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UChar* idInCache = (const UChar *)uhash_get(gCanonicalIDCache, utzid); 347b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (idInCache == NULL) { 348b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UChar* key = ZoneMeta::findTimeZoneID(tzid); 349b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho U_ASSERT(key != NULL); 350b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (key != NULL) { 351b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho idInCache = (const UChar *)uhash_put(gCanonicalIDCache, (void *)key, (void *)canonicalID, &status); 352b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho U_ASSERT(idInCache == NULL); 353b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 354b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 355b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_SUCCESS(status) && isInputCanonical) { 356b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Also put canonical ID itself into the cache if not exist 357b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UChar *canonicalInCache = (const UChar*)uhash_get(gCanonicalIDCache, canonicalID); 358b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (canonicalInCache == NULL) { 359b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho canonicalInCache = (const UChar *)uhash_put(gCanonicalIDCache, (void *)canonicalID, (void *)canonicalID, &status); 360b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho U_ASSERT(canonicalInCache == NULL); 361b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 362b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 36327f654740f2a26ad62a5c155af9199af9e69b889claireho } 364b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho umtx_unlock(&gZoneMetaLock); 365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 367b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return canonicalID; 36850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 37050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUnicodeString& U_EXPORT2 371b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZoneMeta::getCanonicalCLDRID(const UnicodeString &tzid, UnicodeString &systemID, UErrorCode& status) { 372b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UChar *canonicalID = getCanonicalCLDRID(tzid, status); 373b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_FAILURE(status) || canonicalID == NULL) { 374b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho systemID.setToBogus(); 375b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return systemID; 376b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 377b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho systemID.setTo(TRUE, canonicalID, -1); 378b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return systemID; 379b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 380b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 381b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UChar* U_EXPORT2 382b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZoneMeta::getCanonicalCLDRID(const TimeZone& tz) { 383b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (dynamic_cast<const OlsonTimeZone *>(&tz) != NULL) { 384b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // short cut for OlsonTimeZone 385b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const OlsonTimeZone *otz = (const OlsonTimeZone*)&tz; 386b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return otz->getCanonicalID(); 387b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 388b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UErrorCode status = U_ZERO_ERROR; 389b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UnicodeString tzID; 390b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return getCanonicalCLDRID(tz.getID(tzID), status); 391b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 392b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 393b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 394b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 395b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeString& U_EXPORT2 39650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoZoneMeta::getCanonicalCountry(const UnicodeString &tzid, UnicodeString &canonicalCountry) { 39750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UChar *region = TimeZone::getRegion(tzid); 398b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (region != NULL && u_strcmp(gWorld, region) != 0) { 39950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho canonicalCountry.setTo(region, -1); 40050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 401b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho canonicalCountry.setToBogus(); 40250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 40350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return canonicalCountry; 40450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 405b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 40650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUnicodeString& U_EXPORT2 40750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoZoneMeta::getSingleCountry(const UnicodeString &tzid, UnicodeString &country) { 40850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Get canonical country for the zone 40950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UChar *region = TimeZone::getRegion(tzid); 410b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (region == NULL || u_strcmp(gWorld, region) == 0) { 411b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // special case - unknown or "001" 412b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho country.setToBogus(); 41350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return country; 41450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 41650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Checking the cached results 41750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode status = U_ZERO_ERROR; 41850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UBool initialized; 41950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UMTX_CHECK(&gZoneMetaLock, gCountryInfoVectorsInitialized, initialized); 42050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!initialized) { 42150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Create empty vectors 42250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho umtx_lock(&gZoneMetaLock); 42350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho { 42450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!gCountryInfoVectorsInitialized) { 42550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // No deleters for these UVectors, it's a reference to a resource bundle string. 42650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho gSingleZoneCountries = new UVector(NULL, uhash_compareUChars, status); 42750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (gSingleZoneCountries == NULL) { 42850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status = U_MEMORY_ALLOCATION_ERROR; 42950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 43050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho gMultiZonesCountries = new UVector(NULL, uhash_compareUChars, status); 43150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (gMultiZonesCountries == NULL) { 43250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status = U_MEMORY_ALLOCATION_ERROR; 43350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 43550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_SUCCESS(status)) { 43650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho gCountryInfoVectorsInitialized = TRUE; 43750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 43850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho delete gSingleZoneCountries; 43950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho delete gMultiZonesCountries; 44050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 44150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 44350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho umtx_unlock(&gZoneMetaLock); 444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 446b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho country.setToBogus(); 44750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return country; 448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 44950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 450b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 45150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Check if it was already cached 45250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UBool cached = FALSE; 45350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UBool multiZones = FALSE; 45450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho umtx_lock(&gZoneMetaLock); 45550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho { 45650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho multiZones = cached = gMultiZonesCountries->contains((void*)region); 45750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!multiZones) { 45850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho cached = gSingleZoneCountries->contains((void*)region); 459c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru } 460c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru } 46150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho umtx_unlock(&gZoneMetaLock); 462c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru 46350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!cached) { 46450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // We need to go through all zones associated with the region. 46550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // This is relatively heavy operation. 46650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 46750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho U_ASSERT(u_strlen(region) == 2); 46850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 46950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho char buf[] = {0, 0, 0}; 47050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho u_UCharsToChars(region, buf, 2); 47150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 472b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho StringEnumeration *ids = TimeZone::createTimeZoneIDEnumeration(UCAL_ZONE_TYPE_CANONICAL_LOCATION, buf, NULL, status); 47350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t idsLen = ids->count(status); 47450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_SUCCESS(status) && idsLen > 1) { 475b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // multiple canonical zones are available for the region 476b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho multiZones = TRUE; 47750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 47850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(status)) { 47950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // no single country by default for any error cases 48050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho multiZones = TRUE; 48150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 48250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho delete ids; 48350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 48450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // Cache the result 48550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho umtx_lock(&gZoneMetaLock); 48650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho { 48750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode ec = U_ZERO_ERROR; 48850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (multiZones) { 48950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!gMultiZonesCountries->contains((void*)region)) { 49050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho gMultiZonesCountries->addElement((void*)region, ec); 491c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru } 492c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru } else { 49350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!gSingleZoneCountries->contains((void*)region)) { 49450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho gSingleZoneCountries->addElement((void*)region, ec); 49550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 49850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho umtx_unlock(&gZoneMetaLock); 499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 50150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (multiZones) { 502b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho country.setToBogus(); 50350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 50450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho country.setTo(region, -1); 505b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 50650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return country; 507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 50950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUnicodeString& U_EXPORT2 51050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoZoneMeta::getMetazoneID(const UnicodeString &tzid, UDate date, UnicodeString &result) { 51150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UBool isSet = FALSE; 51250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UVector *mappings = getMetazoneMappings(tzid); 51350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (mappings != NULL) { 51450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (int32_t i = 0; i < mappings->size(); i++) { 51550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho OlsonToMetaMappingEntry *mzm = (OlsonToMetaMappingEntry*)mappings->elementAt(i); 51650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (mzm->from <= date && mzm->to > date) { 51750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result.setTo(mzm->mzid, -1); 51850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho isSet = TRUE; 519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 521b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 522b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 52350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!isSet) { 524b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho result.setToBogus(); 525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 52650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return result; 527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 52950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoconst UVector* U_EXPORT2 53050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoZoneMeta::getMetazoneMappings(const UnicodeString &tzid) { 531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UErrorCode status = U_ZERO_ERROR; 532b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UChar tzidUChars[ZID_KEY_MAX + 1]; 533b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho tzid.extract(tzidUChars, ZID_KEY_MAX + 1, status); 53450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING) { 535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 53850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UBool initialized; 53950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UMTX_CHECK(&gZoneMetaLock, gOlsonToMetaInitialized, initialized); 54050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!initialized) { 54150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UHashtable *tmpOlsonToMeta = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status); 542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 54350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return NULL; 544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 54550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uhash_setKeyDeleter(tmpOlsonToMeta, deleteUCharString); 54650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uhash_setValueDeleter(tmpOlsonToMeta, deleteUVector); 54750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 54850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho umtx_lock(&gZoneMetaLock); 54950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho { 55050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!gOlsonToMetaInitialized) { 55150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho gOlsonToMeta = tmpOlsonToMeta; 55250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho tmpOlsonToMeta = NULL; 55350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho gOlsonToMetaInitialized = TRUE; 554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 55650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho umtx_unlock(&gZoneMetaLock); 557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 55850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // OK to call the following multiple times with the same function 55950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ucln_i18n_registerCleanup(UCLN_I18N_ZONEMETA, zoneMeta_cleanup); 56050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (tmpOlsonToMeta != NULL) { 56150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uhash_close(tmpOlsonToMeta); 56250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 56550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // get the mapping from cache 56650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UVector *result = NULL; 567b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 568b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru umtx_lock(&gZoneMetaLock); 56950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho { 57050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result = (UVector*) uhash_get(gOlsonToMeta, tzidUChars); 571b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 572b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru umtx_unlock(&gZoneMetaLock); 573b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 57450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (result != NULL) { 57550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return result; 576b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 577c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru 57850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // miss the cache - create new one 57950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UVector *tmpResult = createMetazoneMappings(tzid); 58050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (tmpResult == NULL) { 58150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // not available 58250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return NULL; 583b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 584c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru 58550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // put the new one into the cache 586c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru umtx_lock(&gZoneMetaLock); 58750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho { 58850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // make sure it's already created 58950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result = (UVector*) uhash_get(gOlsonToMeta, tzidUChars); 59050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (result == NULL) { 59150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // add the one just created 59250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t tzidLen = tzid.length() + 1; 59350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UChar *key = (UChar*)uprv_malloc(tzidLen * sizeof(UChar)); 59450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (key == NULL) { 59550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // memory allocation error.. just return NULL 59650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result = NULL; 59750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho delete tmpResult; 59850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 59950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho tzid.extract(key, tzidLen, status); 60050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uhash_put(gOlsonToMeta, key, tmpResult, &status); 60150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(status)) { 60250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // delete the mapping 60350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result = NULL; 60450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho delete tmpResult; 60550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 60650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result = tmpResult; 60750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 60850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 60950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 61050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // another thread already put the one 61150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho delete tmpResult; 61250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 613b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 614b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru umtx_unlock(&gZoneMetaLock); 615b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 61650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return result; 617c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru} 618c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru 61950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUVector* 62050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoZoneMeta::createMetazoneMappings(const UnicodeString &tzid) { 62150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UVector *mzMappings = NULL; 62250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode status = U_ZERO_ERROR; 623b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 62450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UnicodeString canonicalID; 62550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UResourceBundle *rb = ures_openDirect(NULL, gMetaZones, &status); 62650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_getByKey(rb, gMetazoneInfo, rb, &status); 627b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho getCanonicalCLDRID(tzid, canonicalID, status); 628b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 62950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_SUCCESS(status)) { 630b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho char tzKey[ZID_KEY_MAX + 1]; 631b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho int32_t tzKeyLen = canonicalID.extract(0, canonicalID.length(), tzKey, sizeof(tzKey), US_INV); 632b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho tzKey[tzKeyLen] = 0; 63350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 63450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // tzid keys are using ':' as separators 63550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho char *p = tzKey; 63650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho while (*p) { 63750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*p == '/') { 63850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *p = ':'; 63950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 64050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho p++; 641b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 64350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_getByKey(rb, tzKey, rb, &status); 644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 64550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_SUCCESS(status)) { 64650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UResourceBundle *mz = NULL; 64750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho while (ures_hasNext(rb)) { 64850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mz = ures_getNextResource(rb, mz, &status); 649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 65050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UChar *mz_name = ures_getStringByIndex(mz, 0, NULL, &status); 65150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UChar *mz_from = gDefaultFrom; 65250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UChar *mz_to = gDefaultTo; 653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 65450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ures_getSize(mz) == 3) { 65550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mz_from = ures_getStringByIndex(mz, 1, NULL, &status); 65650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mz_to = ures_getStringByIndex(mz, 2, NULL, &status); 65750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 65850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 65950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(U_FAILURE(status)){ 66050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status = U_ZERO_ERROR; 66150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; 66250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 66350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // We do not want to use SimpleDateformat to parse boundary dates, 66450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // because this code could be triggered by the initialization code 66550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // used by SimpleDateFormat. 66650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UDate from = parseDate(mz_from, status); 66750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UDate to = parseDate(mz_to, status); 66850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(status)) { 66950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status = U_ZERO_ERROR; 67050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; 67150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 67250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 67350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho OlsonToMetaMappingEntry *entry = (OlsonToMetaMappingEntry*)uprv_malloc(sizeof(OlsonToMetaMappingEntry)); 67450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (entry == NULL) { 67550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status = U_MEMORY_ALLOCATION_ERROR; 676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 67850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho entry->mzid = mz_name; 67950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho entry->from = from; 68050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho entry->to = to; 68150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 68250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (mzMappings == NULL) { 68350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mzMappings = new UVector(deleteOlsonToMetaMappingEntry, NULL, status); 68450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(status)) { 68550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho delete mzMappings; 68650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho deleteOlsonToMetaMappingEntry(entry); 68750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_free(entry); 68850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 68950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 69050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 69150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 69250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mzMappings->addElement(entry, status); 69350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(status)) { 69450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 69550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 69650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 69750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_close(mz); 69850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(status)) { 69950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (mzMappings != NULL) { 70050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho delete mzMappings; 70150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mzMappings = NULL; 70250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 70650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_close(rb); 70750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return mzMappings; 708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 710c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruUnicodeString& U_EXPORT2 71150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoZoneMeta::getZoneIdByMetazone(const UnicodeString &mzid, const UnicodeString ®ion, UnicodeString &result) { 71250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode status = U_ZERO_ERROR; 71350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UChar *tzid = NULL; 71450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t tzidLen = 0; 71550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho char keyBuf[ZID_KEY_MAX + 1]; 71650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t keyLen = 0; 71750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 718b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (mzid.length() > ZID_KEY_MAX) { 719b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho result.setToBogus(); 72050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return result; 721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 723b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho keyLen = mzid.extract(0, mzid.length(), keyBuf, ZID_KEY_MAX + 1, US_INV); 724b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho keyBuf[keyLen] = 0; 725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 72650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UResourceBundle *rb = ures_openDirect(NULL, gMetaZones, &status); 72750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_getByKey(rb, gMapTimezonesTag, rb, &status); 72850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_getByKey(rb, keyBuf, rb, &status); 72950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 73050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_SUCCESS(status)) { 73150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // check region mapping 73250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (region.length() == 2 || region.length() == 3) { 733b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho keyLen = region.extract(0, region.length(), keyBuf, ZID_KEY_MAX + 1, US_INV); 734b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho keyBuf[keyLen] = 0; 73550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho tzid = ures_getStringByKey(rb, keyBuf, &tzidLen, &status); 73650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status == U_MISSING_RESOURCE_ERROR) { 73750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status = U_ZERO_ERROR; 738b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 74050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_SUCCESS(status) && tzid == NULL) { 74150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // try "001" 74250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho tzid = ures_getStringByKey(rb, gWorldTag, &tzidLen, &status); 74350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 74550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_close(rb); 74650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 74750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (tzid == NULL) { 748b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho result.setToBogus(); 74950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 75050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result.setTo(tzid, tzidLen); 751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 75250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return result; 754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 756b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehovoid 757b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZoneMeta::initAvailableMetaZoneIDs () { 758b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UBool initialized; 759b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UMTX_CHECK(&gZoneMetaLock, gMetaZoneIDsInitialized, initialized); 760b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (!initialized) { 761b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho umtx_lock(&gZoneMetaLock); 762b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho { 763b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (!gMetaZoneIDsInitialized) { 764b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UErrorCode status = U_ZERO_ERROR; 765b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UHashtable *metaZoneIDTable = uhash_open(uhash_hashUnicodeString, uhash_compareUnicodeString, NULL, &status); 766b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uhash_setKeyDeleter(metaZoneIDTable, uhash_deleteUnicodeString); 767b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // No valueDeleter, because the vector maintain the value objects 768b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UVector *metaZoneIDs = NULL; 769b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_SUCCESS(status)) { 770b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho metaZoneIDs = new UVector(NULL, uhash_compareUChars, status); 771b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (metaZoneIDs == NULL) { 772b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho status = U_MEMORY_ALLOCATION_ERROR; 773b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 774b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 775b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uhash_close(metaZoneIDTable); 776b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 777b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_SUCCESS(status)) { 778b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho metaZoneIDs->setDeleter(uhash_freeBlock); 779b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 780b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UResourceBundle *rb = ures_openDirect(NULL, gMetaZones, &status); 781b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UResourceBundle *bundle = ures_getByKey(rb, gMapTimezonesTag, NULL, &status); 782b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UResourceBundle res; 783b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho ures_initStackObject(&res); 784b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho while (U_SUCCESS(status) && ures_hasNext(bundle)) { 785b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho ures_getNextResource(bundle, &res, &status); 786b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_FAILURE(status)) { 787b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho break; 788b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 789b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const char *mzID = ures_getKey(&res); 790b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho int32_t len = uprv_strlen(mzID); 791b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UChar *uMzID = (UChar*)uprv_malloc(sizeof(UChar) * (len + 1)); 792b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (uMzID == NULL) { 793b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho status = U_MEMORY_ALLOCATION_ERROR; 794b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho break; 795b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 796b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho u_charsToUChars(mzID, uMzID, len); 797b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uMzID[len] = 0; 798b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UnicodeString *usMzID = new UnicodeString(uMzID); 799b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (uhash_get(metaZoneIDTable, usMzID) == NULL) { 800b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho metaZoneIDs->addElement((void *)uMzID, status); 801b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uhash_put(metaZoneIDTable, (void *)usMzID, (void *)uMzID, &status); 802b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 803b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uprv_free(uMzID); 804b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho delete usMzID; 805b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 806b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 807b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_SUCCESS(status)) { 808b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho gMetaZoneIDs = metaZoneIDs; 809b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho gMetaZoneIDTable = metaZoneIDTable; 810b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho gMetaZoneIDsInitialized = TRUE; 811b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 812b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uhash_close(metaZoneIDTable); 813b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho delete metaZoneIDs; 814b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 815b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho ures_close(&res); 816b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho ures_close(bundle); 817b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho ures_close(rb); 818b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 819b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 820b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 821b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho umtx_unlock(&gZoneMetaLock); 822b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 823b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 824b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 825b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UVector* 826b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZoneMeta::getAvailableMetazoneIDs() { 827b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho initAvailableMetaZoneIDs(); 828b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return gMetaZoneIDs; 829b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 830b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 831b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UChar* 832b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZoneMeta::findMetaZoneID(const UnicodeString& mzid) { 833b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho initAvailableMetaZoneIDs(); 834b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return (const UChar*)uhash_get(gMetaZoneIDTable, &mzid); 835b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 836b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 837b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UChar* 838b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZoneMeta::findTimeZoneID(const UnicodeString& tzid) { 839b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return TimeZone::findID(tzid); 840b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 841b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 842b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_END 843b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 844b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_FORMATTING */ 845