1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* 2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru******************************************************************************* 3fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* Copyright (C) 2007-2014, International Business Machines Corporation and 459d709d503bab6e2b61931737e662dd293b40578ccornelius* 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" 17103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "unicode/simpletz.h" 18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "umutex.h" 20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uvector.h" 21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cmemory.h" 22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "gregoimp.h" 23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cstring.h" 24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ucln_in.h" 2550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "uassert.h" 26b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "uresimp.h" 27b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "uhash.h" 28b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "olsontz.h" 29b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 30fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) 31fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 3254dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic UMutex gZoneMetaLock = U_MUTEX_INITIALIZER; 3350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 34b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// CLDR Canonical ID mapping table 35b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic UHashtable *gCanonicalIDCache = NULL; 3659d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic icu::UInitOnce gCanonicalIDCacheInitOnce = U_INITONCE_INITIALIZER; 37b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 3850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// Metazone mapping table 39b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UHashtable *gOlsonToMeta = NULL; 4059d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic icu::UInitOnce gOlsonToMetaInitOnce = U_INITONCE_INITIALIZER; 41b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 42b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// Available metazone IDs vector and table 43103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic icu::UVector *gMetaZoneIDs = NULL; 44b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic UHashtable *gMetaZoneIDTable = NULL; 4559d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic icu::UInitOnce gMetaZoneIDsInitOnce = U_INITONCE_INITIALIZER; 46b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 4750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// Country info vectors 48103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic icu::UVector *gSingleZoneCountries = NULL; 49103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic icu::UVector *gMultiZonesCountries = NULL; 5059d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic icu::UInitOnce gCountryInfoVectorsInitOnce = U_INITONCE_INITIALIZER; 51b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 5250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CDECL_BEGIN 53b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Cleanup callback func 56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool U_CALLCONV zoneMeta_cleanup(void) 58b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 59b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (gCanonicalIDCache != NULL) { 60b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uhash_close(gCanonicalIDCache); 61b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho gCanonicalIDCache = NULL; 62b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 6359d709d503bab6e2b61931737e662dd293b40578ccornelius gCanonicalIDCacheInitOnce.reset(); 64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (gOlsonToMeta != NULL) { 66b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uhash_close(gOlsonToMeta); 67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru gOlsonToMeta = NULL; 68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 6959d709d503bab6e2b61931737e662dd293b40578ccornelius gOlsonToMetaInitOnce.reset(); 70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 71b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (gMetaZoneIDTable != NULL) { 72b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uhash_close(gMetaZoneIDTable); 7359d709d503bab6e2b61931737e662dd293b40578ccornelius gMetaZoneIDTable = NULL; 74b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 75b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // delete after closing gMetaZoneIDTable, because it holds 76b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // value objects held by the hashtable 77b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho delete gMetaZoneIDs; 7859d709d503bab6e2b61931737e662dd293b40578ccornelius gMetaZoneIDs = NULL; 7959d709d503bab6e2b61931737e662dd293b40578ccornelius gMetaZoneIDsInitOnce.reset(); 80b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 8150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho delete gSingleZoneCountries; 8259d709d503bab6e2b61931737e662dd293b40578ccornelius gSingleZoneCountries = NULL; 8350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho delete gMultiZonesCountries; 8459d709d503bab6e2b61931737e662dd293b40578ccornelius gMultiZonesCountries = NULL; 8559d709d503bab6e2b61931737e662dd293b40578ccornelius gCountryInfoVectorsInitOnce.reset(); 86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return TRUE; 88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 89b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 91b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * Deleter for UChar* string 92b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */ 93b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void U_CALLCONV 94b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QuerudeleteUCharString(void *obj) { 95b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UChar *entry = (UChar*)obj; 96b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(entry); 97b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 98b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 99b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/** 100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Deleter for UVector 101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void U_CALLCONV 103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerudeleteUVector(void *obj) { 104103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius delete (icu::UVector*) obj; 105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Deleter for OlsonToMetaMappingEntry 109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void U_CALLCONV 111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerudeleteOlsonToMetaMappingEntry(void *obj) { 112103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius icu::OlsonToMetaMappingEntry *entry = (icu::OlsonToMetaMappingEntry*)obj; 113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_free(entry); 114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_END 117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_BEGIN 119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 120b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ZID_KEY_MAX 128 121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 12250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const char gMetaZones[] = "metaZones"; 12350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const char gMetazoneInfo[] = "metazoneInfo"; 124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char gMapTimezonesTag[] = "mapTimezones"; 125b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1268393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusstatic const char gKeyTypeData[] = "keyTypeData"; 12750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const char gTypeAliasTag[] = "typeAlias"; 12827f654740f2a26ad62a5c155af9199af9e69b889clairehostatic const char gTypeMapTag[] = "typeMap"; 12950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const char gTimezoneTag[] = "timezone"; 130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1318393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusstatic const char gPrimaryZonesTag[] = "primaryZones"; 1328393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius 13350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const char gWorldTag[] = "001"; 134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const UChar gWorld[] = {0x30, 0x30, 0x31, 0x00}; // "001" 136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 13750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const UChar gDefaultFrom[] = {0x31, 0x39, 0x37, 0x30, 0x2D, 0x30, 0x31, 0x2D, 0x30, 0x31, 13850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 0x20, 0x30, 0x30, 0x3A, 0x30, 0x30, 0x00}; // "1970-01-01 00:00" 13950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const UChar gDefaultTo[] = {0x39, 0x39, 0x39, 0x39, 0x2D, 0x31, 0x32, 0x2D, 0x33, 0x31, 14050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 0x20, 0x32, 0x33, 0x3A, 0x35, 0x39, 0x00}; // "9999-12-31 23:59" 14150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 142103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic const UChar gCustomTzPrefix[] = {0x47, 0x4D, 0x54, 0}; // "GMT" 143103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ASCII_DIGIT(c) (((c)>=0x30 && (c)<=0x39) ? (c)-0x30 : -1) 145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* 147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Convert a date string used by metazone mappings to UDate. 148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * The format used by CLDR metazone mapping is "yyyy-MM-dd HH:mm". 149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 150c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querustatic UDate 151c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruparseDate (const UChar *text, UErrorCode &status) { 152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t len = u_strlen(text); 156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (len != 16 && len != 10) { 157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // It must be yyyy-MM-dd HH:mm (length 16) or yyyy-MM-dd (length 10) 158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_INVALID_FORMAT_ERROR; 159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t year = 0, month = 0, day = 0, hour = 0, min = 0, n; 163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t idx; 164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // "yyyy" (0 - 3) 166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (idx = 0; idx <= 3 && U_SUCCESS(status); idx++) { 167b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru n = ASCII_DIGIT((int32_t)text[idx]); 168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (n >= 0) { 169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru year = 10*year + n; 170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_INVALID_FORMAT_ERROR; 172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // "MM" (5 - 6) 175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (idx = 5; idx <= 6 && U_SUCCESS(status); idx++) { 176b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru n = ASCII_DIGIT((int32_t)text[idx]); 177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (n >= 0) { 178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru month = 10*month + n; 179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_INVALID_FORMAT_ERROR; 181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // "dd" (8 - 9) 184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (idx = 8; idx <= 9 && U_SUCCESS(status); idx++) { 185b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru n = ASCII_DIGIT((int32_t)text[idx]); 186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (n >= 0) { 187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru day = 10*day + n; 188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_INVALID_FORMAT_ERROR; 190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (len == 16) { 193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // "HH" (11 - 12) 194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (idx = 11; idx <= 12 && U_SUCCESS(status); idx++) { 195b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru n = ASCII_DIGIT((int32_t)text[idx]); 196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (n >= 0) { 197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru hour = 10*hour + n; 198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_INVALID_FORMAT_ERROR; 200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // "mm" (14 - 15) 203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (idx = 14; idx <= 15 && U_SUCCESS(status); idx++) { 204b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru n = ASCII_DIGIT((int32_t)text[idx]); 205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (n >= 0) { 206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru min = 10*min + n; 207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_INVALID_FORMAT_ERROR; 209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_SUCCESS(status)) { 214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UDate date = Grego::fieldsToDay(year, month - 1, day) * U_MILLIS_PER_DAY 215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru + hour * U_MILLIS_PER_HOUR + min * U_MILLIS_PER_MINUTE; 216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return date; 217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 22159d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic void U_CALLCONV initCanonicalIDCache(UErrorCode &status) { 22259d709d503bab6e2b61931737e662dd293b40578ccornelius gCanonicalIDCache = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status); 22359d709d503bab6e2b61931737e662dd293b40578ccornelius if (gCanonicalIDCache == NULL) { 22459d709d503bab6e2b61931737e662dd293b40578ccornelius status = U_MEMORY_ALLOCATION_ERROR; 22559d709d503bab6e2b61931737e662dd293b40578ccornelius } 22659d709d503bab6e2b61931737e662dd293b40578ccornelius if (U_FAILURE(status)) { 22759d709d503bab6e2b61931737e662dd293b40578ccornelius gCanonicalIDCache = NULL; 22859d709d503bab6e2b61931737e662dd293b40578ccornelius } 22959d709d503bab6e2b61931737e662dd293b40578ccornelius // No key/value deleters - keys/values are from a resource bundle 23059d709d503bab6e2b61931737e662dd293b40578ccornelius ucln_i18n_registerCleanup(UCLN_I18N_ZONEMETA, zoneMeta_cleanup); 23159d709d503bab6e2b61931737e662dd293b40578ccornelius} 23259d709d503bab6e2b61931737e662dd293b40578ccornelius 23359d709d503bab6e2b61931737e662dd293b40578ccornelius 234b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UChar* U_EXPORT2 235b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZoneMeta::getCanonicalCLDRID(const UnicodeString &tzid, UErrorCode& status) { 236b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_FAILURE(status)) { 237b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return NULL; 238b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 239b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 240fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (tzid.isBogus() || tzid.length() > ZID_KEY_MAX) { 24127f654740f2a26ad62a5c155af9199af9e69b889claireho status = U_ILLEGAL_ARGUMENT_ERROR; 242b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return NULL; 243b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 244b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 245b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Checking the cached results 24659d709d503bab6e2b61931737e662dd293b40578ccornelius umtx_initOnce(gCanonicalIDCacheInitOnce, &initCanonicalIDCache, status); 24759d709d503bab6e2b61931737e662dd293b40578ccornelius if (U_FAILURE(status)) { 24859d709d503bab6e2b61931737e662dd293b40578ccornelius return NULL; 249b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 250b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 251b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UChar *canonicalID = NULL; 252b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 253b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UErrorCode tmpStatus = U_ZERO_ERROR; 254b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UChar utzid[ZID_KEY_MAX + 1]; 255b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho tzid.extract(utzid, ZID_KEY_MAX + 1, tmpStatus); 256b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho U_ASSERT(tmpStatus == U_ZERO_ERROR); // we checked the length of tzid already 257b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 258b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Check if it was already cached 259b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho umtx_lock(&gZoneMetaLock); 260b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho { 261b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho canonicalID = (const UChar *)uhash_get(gCanonicalIDCache, utzid); 26227f654740f2a26ad62a5c155af9199af9e69b889claireho } 263b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho umtx_unlock(&gZoneMetaLock); 264c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru 265b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (canonicalID != NULL) { 266b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return canonicalID; 267b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 268b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 269b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // If not, resolve CLDR canonical ID with resource data 270b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UBool isInputCanonical = FALSE; 271b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho char id[ZID_KEY_MAX + 1]; 272fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius tzid.extract(0, 0x7fffffff, id, LENGTHOF(id), US_INV); 27327f654740f2a26ad62a5c155af9199af9e69b889claireho 27427f654740f2a26ad62a5c155af9199af9e69b889claireho // replace '/' with ':' 27527f654740f2a26ad62a5c155af9199af9e69b889claireho char *p = id; 27627f654740f2a26ad62a5c155af9199af9e69b889claireho while (*p++) { 27727f654740f2a26ad62a5c155af9199af9e69b889claireho if (*p == '/') { 27827f654740f2a26ad62a5c155af9199af9e69b889claireho *p = ':'; 27950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 28127f654740f2a26ad62a5c155af9199af9e69b889claireho 2828393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius UResourceBundle *top = ures_openDirect(NULL, gKeyTypeData, &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 { 310fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t 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 39359d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic void U_CALLCONV countryInfoVectorsInit(UErrorCode &status) { 39459d709d503bab6e2b61931737e662dd293b40578ccornelius // Create empty vectors 39559d709d503bab6e2b61931737e662dd293b40578ccornelius // No deleters for these UVectors, it's a reference to a resource bundle string. 39659d709d503bab6e2b61931737e662dd293b40578ccornelius gSingleZoneCountries = new UVector(NULL, uhash_compareUChars, status); 39759d709d503bab6e2b61931737e662dd293b40578ccornelius if (gSingleZoneCountries == NULL) { 39859d709d503bab6e2b61931737e662dd293b40578ccornelius status = U_MEMORY_ALLOCATION_ERROR; 39959d709d503bab6e2b61931737e662dd293b40578ccornelius } 40059d709d503bab6e2b61931737e662dd293b40578ccornelius gMultiZonesCountries = new UVector(NULL, uhash_compareUChars, status); 40159d709d503bab6e2b61931737e662dd293b40578ccornelius if (gMultiZonesCountries == NULL) { 40259d709d503bab6e2b61931737e662dd293b40578ccornelius status = U_MEMORY_ALLOCATION_ERROR; 40359d709d503bab6e2b61931737e662dd293b40578ccornelius } 40459d709d503bab6e2b61931737e662dd293b40578ccornelius 40559d709d503bab6e2b61931737e662dd293b40578ccornelius if (U_FAILURE(status)) { 40659d709d503bab6e2b61931737e662dd293b40578ccornelius delete gSingleZoneCountries; 40759d709d503bab6e2b61931737e662dd293b40578ccornelius delete gMultiZonesCountries; 40859d709d503bab6e2b61931737e662dd293b40578ccornelius gSingleZoneCountries = NULL; 40959d709d503bab6e2b61931737e662dd293b40578ccornelius gMultiZonesCountries = NULL; 41059d709d503bab6e2b61931737e662dd293b40578ccornelius } 41159d709d503bab6e2b61931737e662dd293b40578ccornelius ucln_i18n_registerCleanup(UCLN_I18N_ZONEMETA, zoneMeta_cleanup); 41259d709d503bab6e2b61931737e662dd293b40578ccornelius} 41359d709d503bab6e2b61931737e662dd293b40578ccornelius 41459d709d503bab6e2b61931737e662dd293b40578ccornelius 415b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeString& U_EXPORT2 4168393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusZoneMeta::getCanonicalCountry(const UnicodeString &tzid, UnicodeString &country, UBool *isPrimary /* = NULL */) { 4178393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (isPrimary != NULL) { 4188393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius *isPrimary = FALSE; 41950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 420b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 42150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UChar *region = TimeZone::getRegion(tzid); 4228393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (region != NULL && u_strcmp(gWorld, region) != 0) { 4238393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius country.setTo(region, -1); 4248393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } else { 425b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho country.setToBogus(); 42650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return country; 42750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 4298393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (isPrimary != NULL) { 4308393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius char regionBuf[] = {0, 0, 0}; 4318393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius 4328393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius // Checking the cached results 4338393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius UErrorCode status = U_ZERO_ERROR; 43459d709d503bab6e2b61931737e662dd293b40578ccornelius umtx_initOnce(gCountryInfoVectorsInitOnce, &countryInfoVectorsInit, status); 43559d709d503bab6e2b61931737e662dd293b40578ccornelius if (U_FAILURE(status)) { 43659d709d503bab6e2b61931737e662dd293b40578ccornelius return country; 437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 4398393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius // Check if it was already cached 4408393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius UBool cached = FALSE; 4418393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius UBool singleZone = FALSE; 4428393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius umtx_lock(&gZoneMetaLock); 4438393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius { 4448393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius singleZone = cached = gSingleZoneCountries->contains((void*)region); 4458393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (!cached) { 4468393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius cached = gMultiZonesCountries->contains((void*)region); 4478393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } 448c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru } 4498393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius umtx_unlock(&gZoneMetaLock); 450c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru 4518393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (!cached) { 4528393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius // We need to go through all zones associated with the region. 4538393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius // This is relatively heavy operation. 45450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 4558393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius U_ASSERT(u_strlen(region) == 2); 45650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 4578393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius u_UCharsToChars(region, regionBuf, 2); 45850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 4598393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius StringEnumeration *ids = TimeZone::createTimeZoneIDEnumeration(UCAL_ZONE_TYPE_CANONICAL_LOCATION, regionBuf, NULL, status); 4608393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius int32_t idsLen = ids->count(status); 4618393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (U_SUCCESS(status) && idsLen == 1) { 4628393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius // only the single zone is available for the region 4638393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius singleZone = TRUE; 4648393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } 4658393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius delete ids; 4668393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius 4678393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius // Cache the result 4688393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius umtx_lock(&gZoneMetaLock); 4698393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius { 4708393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius UErrorCode ec = U_ZERO_ERROR; 4718393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (singleZone) { 4728393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (!gSingleZoneCountries->contains((void*)region)) { 4738393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius gSingleZoneCountries->addElement((void*)region, ec); 4748393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } 4758393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } else { 4768393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (!gMultiZonesCountries->contains((void*)region)) { 4778393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius gMultiZonesCountries->addElement((void*)region, ec); 4788393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } 4798393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } 4808393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } 4818393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius umtx_unlock(&gZoneMetaLock); 48250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 48350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 4848393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (singleZone) { 4858393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius *isPrimary = TRUE; 4868393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } else { 4878393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius // Note: We may cache the primary zone map in future. 4888393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius 4898393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius // Even a country has multiple zones, one of them might be 4908393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius // dominant and treated as a primary zone 4918393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius int32_t idLen = 0; 4928393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (regionBuf[0] == 0) { 4938393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius u_UCharsToChars(region, regionBuf, 2); 4948393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } 4958393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius 4968393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius UResourceBundle *rb = ures_openDirect(NULL, gMetaZones, &status); 4978393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius ures_getByKey(rb, gPrimaryZonesTag, rb, &status); 4988393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius const UChar *primaryZone = ures_getStringByKey(rb, regionBuf, &idLen, &status); 4998393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (U_SUCCESS(status)) { 5008393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (tzid.compare(primaryZone, idLen) == 0) { 5018393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius *isPrimary = TRUE; 5028393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } else { 5038393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius // The given ID might not be a canonical ID 5048393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius UnicodeString canonicalID; 5058393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius TimeZone::getCanonicalID(tzid, canonicalID, status); 5068393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (U_SUCCESS(status) && canonicalID.compare(primaryZone, idLen) == 0) { 5078393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius *isPrimary = TRUE; 5088393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } 50950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 5118393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius ures_close(rb); 512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 51550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return country; 516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 51850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUnicodeString& U_EXPORT2 51950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoZoneMeta::getMetazoneID(const UnicodeString &tzid, UDate date, UnicodeString &result) { 52050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UBool isSet = FALSE; 52150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UVector *mappings = getMetazoneMappings(tzid); 52250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (mappings != NULL) { 52350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (int32_t i = 0; i < mappings->size(); i++) { 52450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho OlsonToMetaMappingEntry *mzm = (OlsonToMetaMappingEntry*)mappings->elementAt(i); 52550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (mzm->from <= date && mzm->to > date) { 52650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result.setTo(mzm->mzid, -1); 52750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho isSet = TRUE; 528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 530b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 53250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!isSet) { 533b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho result.setToBogus(); 534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 53550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return result; 536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 53859d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic void U_CALLCONV olsonToMetaInit(UErrorCode &status) { 53959d709d503bab6e2b61931737e662dd293b40578ccornelius U_ASSERT(gOlsonToMeta == NULL); 54059d709d503bab6e2b61931737e662dd293b40578ccornelius ucln_i18n_registerCleanup(UCLN_I18N_ZONEMETA, zoneMeta_cleanup); 54159d709d503bab6e2b61931737e662dd293b40578ccornelius gOlsonToMeta = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status); 54259d709d503bab6e2b61931737e662dd293b40578ccornelius if (U_FAILURE(status)) { 54359d709d503bab6e2b61931737e662dd293b40578ccornelius gOlsonToMeta = NULL; 54459d709d503bab6e2b61931737e662dd293b40578ccornelius } else { 54559d709d503bab6e2b61931737e662dd293b40578ccornelius uhash_setKeyDeleter(gOlsonToMeta, deleteUCharString); 54659d709d503bab6e2b61931737e662dd293b40578ccornelius uhash_setValueDeleter(gOlsonToMeta, deleteUVector); 54759d709d503bab6e2b61931737e662dd293b40578ccornelius } 54859d709d503bab6e2b61931737e662dd293b40578ccornelius} 54959d709d503bab6e2b61931737e662dd293b40578ccornelius 55059d709d503bab6e2b61931737e662dd293b40578ccornelius 55150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoconst UVector* U_EXPORT2 55250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoZoneMeta::getMetazoneMappings(const UnicodeString &tzid) { 553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UErrorCode status = U_ZERO_ERROR; 554b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UChar tzidUChars[ZID_KEY_MAX + 1]; 555b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho tzid.extract(tzidUChars, ZID_KEY_MAX + 1, status); 55650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING) { 557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 56059d709d503bab6e2b61931737e662dd293b40578ccornelius umtx_initOnce(gOlsonToMetaInitOnce, &olsonToMetaInit, status); 56159d709d503bab6e2b61931737e662dd293b40578ccornelius if (U_FAILURE(status)) { 56259d709d503bab6e2b61931737e662dd293b40578ccornelius return NULL; 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 718fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (mzid.isBogus() || 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 75659d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic void U_CALLCONV initAvailableMetaZoneIDs () { 75759d709d503bab6e2b61931737e662dd293b40578ccornelius U_ASSERT(gMetaZoneIDs == NULL); 75859d709d503bab6e2b61931737e662dd293b40578ccornelius U_ASSERT(gMetaZoneIDTable == NULL); 75959d709d503bab6e2b61931737e662dd293b40578ccornelius ucln_i18n_registerCleanup(UCLN_I18N_ZONEMETA, zoneMeta_cleanup); 76059d709d503bab6e2b61931737e662dd293b40578ccornelius 76159d709d503bab6e2b61931737e662dd293b40578ccornelius UErrorCode status = U_ZERO_ERROR; 76259d709d503bab6e2b61931737e662dd293b40578ccornelius gMetaZoneIDTable = uhash_open(uhash_hashUnicodeString, uhash_compareUnicodeString, NULL, &status); 76359d709d503bab6e2b61931737e662dd293b40578ccornelius if (U_FAILURE(status) || gMetaZoneIDTable == NULL) { 76459d709d503bab6e2b61931737e662dd293b40578ccornelius gMetaZoneIDTable = NULL; 76559d709d503bab6e2b61931737e662dd293b40578ccornelius return; 76659d709d503bab6e2b61931737e662dd293b40578ccornelius } 76759d709d503bab6e2b61931737e662dd293b40578ccornelius uhash_setKeyDeleter(gMetaZoneIDTable, uprv_deleteUObject); 76859d709d503bab6e2b61931737e662dd293b40578ccornelius // No valueDeleter, because the vector maintain the value objects 76959d709d503bab6e2b61931737e662dd293b40578ccornelius gMetaZoneIDs = new UVector(NULL, uhash_compareUChars, status); 77059d709d503bab6e2b61931737e662dd293b40578ccornelius if (U_FAILURE(status) || gMetaZoneIDs == NULL) { 77159d709d503bab6e2b61931737e662dd293b40578ccornelius gMetaZoneIDs = NULL; 77259d709d503bab6e2b61931737e662dd293b40578ccornelius uhash_close(gMetaZoneIDTable); 77359d709d503bab6e2b61931737e662dd293b40578ccornelius gMetaZoneIDTable = NULL; 77459d709d503bab6e2b61931737e662dd293b40578ccornelius return; 77559d709d503bab6e2b61931737e662dd293b40578ccornelius } 77659d709d503bab6e2b61931737e662dd293b40578ccornelius gMetaZoneIDs->setDeleter(uprv_free); 77759d709d503bab6e2b61931737e662dd293b40578ccornelius 77859d709d503bab6e2b61931737e662dd293b40578ccornelius UResourceBundle *rb = ures_openDirect(NULL, gMetaZones, &status); 77959d709d503bab6e2b61931737e662dd293b40578ccornelius UResourceBundle *bundle = ures_getByKey(rb, gMapTimezonesTag, NULL, &status); 78059d709d503bab6e2b61931737e662dd293b40578ccornelius UResourceBundle res; 78159d709d503bab6e2b61931737e662dd293b40578ccornelius ures_initStackObject(&res); 78259d709d503bab6e2b61931737e662dd293b40578ccornelius while (U_SUCCESS(status) && ures_hasNext(bundle)) { 78359d709d503bab6e2b61931737e662dd293b40578ccornelius ures_getNextResource(bundle, &res, &status); 78459d709d503bab6e2b61931737e662dd293b40578ccornelius if (U_FAILURE(status)) { 78559d709d503bab6e2b61931737e662dd293b40578ccornelius break; 786b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 78759d709d503bab6e2b61931737e662dd293b40578ccornelius const char *mzID = ures_getKey(&res); 78859d709d503bab6e2b61931737e662dd293b40578ccornelius int32_t len = uprv_strlen(mzID); 78959d709d503bab6e2b61931737e662dd293b40578ccornelius UChar *uMzID = (UChar*)uprv_malloc(sizeof(UChar) * (len + 1)); 79059d709d503bab6e2b61931737e662dd293b40578ccornelius if (uMzID == NULL) { 79159d709d503bab6e2b61931737e662dd293b40578ccornelius status = U_MEMORY_ALLOCATION_ERROR; 79259d709d503bab6e2b61931737e662dd293b40578ccornelius break; 79359d709d503bab6e2b61931737e662dd293b40578ccornelius } 79459d709d503bab6e2b61931737e662dd293b40578ccornelius u_charsToUChars(mzID, uMzID, len); 79559d709d503bab6e2b61931737e662dd293b40578ccornelius uMzID[len] = 0; 79659d709d503bab6e2b61931737e662dd293b40578ccornelius UnicodeString *usMzID = new UnicodeString(uMzID); 79759d709d503bab6e2b61931737e662dd293b40578ccornelius if (uhash_get(gMetaZoneIDTable, usMzID) == NULL) { 79859d709d503bab6e2b61931737e662dd293b40578ccornelius gMetaZoneIDs->addElement((void *)uMzID, status); 79959d709d503bab6e2b61931737e662dd293b40578ccornelius uhash_put(gMetaZoneIDTable, (void *)usMzID, (void *)uMzID, &status); 80059d709d503bab6e2b61931737e662dd293b40578ccornelius } else { 80159d709d503bab6e2b61931737e662dd293b40578ccornelius uprv_free(uMzID); 80259d709d503bab6e2b61931737e662dd293b40578ccornelius delete usMzID; 80359d709d503bab6e2b61931737e662dd293b40578ccornelius } 80459d709d503bab6e2b61931737e662dd293b40578ccornelius } 80559d709d503bab6e2b61931737e662dd293b40578ccornelius ures_close(&res); 80659d709d503bab6e2b61931737e662dd293b40578ccornelius ures_close(bundle); 80759d709d503bab6e2b61931737e662dd293b40578ccornelius ures_close(rb); 80859d709d503bab6e2b61931737e662dd293b40578ccornelius 80959d709d503bab6e2b61931737e662dd293b40578ccornelius if (U_FAILURE(status)) { 81059d709d503bab6e2b61931737e662dd293b40578ccornelius uhash_close(gMetaZoneIDTable); 81159d709d503bab6e2b61931737e662dd293b40578ccornelius delete gMetaZoneIDs; 81259d709d503bab6e2b61931737e662dd293b40578ccornelius gMetaZoneIDTable = NULL; 81359d709d503bab6e2b61931737e662dd293b40578ccornelius gMetaZoneIDs = NULL; 814b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 815b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 816b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 817b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UVector* 818b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZoneMeta::getAvailableMetazoneIDs() { 81959d709d503bab6e2b61931737e662dd293b40578ccornelius umtx_initOnce(gMetaZoneIDsInitOnce, &initAvailableMetaZoneIDs); 820b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return gMetaZoneIDs; 821b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 822b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 823b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UChar* 824b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZoneMeta::findMetaZoneID(const UnicodeString& mzid) { 82559d709d503bab6e2b61931737e662dd293b40578ccornelius umtx_initOnce(gMetaZoneIDsInitOnce, &initAvailableMetaZoneIDs); 82659d709d503bab6e2b61931737e662dd293b40578ccornelius if (gMetaZoneIDTable == NULL) { 82759d709d503bab6e2b61931737e662dd293b40578ccornelius return NULL; 82859d709d503bab6e2b61931737e662dd293b40578ccornelius } 829b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return (const UChar*)uhash_get(gMetaZoneIDTable, &mzid); 830b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 831b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 832b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UChar* 833b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZoneMeta::findTimeZoneID(const UnicodeString& tzid) { 834b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return TimeZone::findID(tzid); 835b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 836b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 837103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 838103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTimeZone* 839103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusZoneMeta::createCustomTimeZone(int32_t offset) { 840103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UBool negative = FALSE; 841103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius int32_t tmp = offset; 842103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (offset < 0) { 843103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius negative = TRUE; 844103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius tmp = -offset; 845103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 846103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius int32_t hour, min, sec; 847103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 848103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius tmp /= 1000; 849103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius sec = tmp % 60; 850103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius tmp /= 60; 851103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius min = tmp % 60; 852103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius hour = tmp / 60; 853103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 854103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UnicodeString zid; 855103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius formatCustomID(hour, min, sec, negative, zid); 856103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return new SimpleTimeZone(offset, zid); 857103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius} 858103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 859103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusUnicodeString& 860103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusZoneMeta::formatCustomID(uint8_t hour, uint8_t min, uint8_t sec, UBool negative, UnicodeString& id) { 861103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // Create normalized time zone ID - GMT[+|-]HH:mm[:ss] 862103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius id.setTo(gCustomTzPrefix, -1); 863103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (hour != 0 || min != 0) { 864103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (negative) { 86554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius id.append((UChar)0x2D); // '-' 866103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } else { 86754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius id.append((UChar)0x2B); // '+' 868103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 869103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // Always use US-ASCII digits 87054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius id.append((UChar)(0x30 + (hour%100)/10)); 87154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius id.append((UChar)(0x30 + (hour%10))); 87254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius id.append((UChar)0x3A); // ':' 87354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius id.append((UChar)(0x30 + (min%100)/10)); 87454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius id.append((UChar)(0x30 + (min%10))); 875103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (sec != 0) { 87654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius id.append((UChar)0x3A); // ':' 87754dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius id.append((UChar)(0x30 + (sec%100)/10)); 87854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius id.append((UChar)(0x30 + (sec%10))); 879103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 880103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 881103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return id; 882103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius} 883103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 8848393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusconst UChar* 8858393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusZoneMeta::getShortID(const TimeZone& tz) { 8868393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius const UChar* canonicalID = NULL; 8878393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (dynamic_cast<const OlsonTimeZone *>(&tz) != NULL) { 8888393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius // short cut for OlsonTimeZone 8898393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius const OlsonTimeZone *otz = (const OlsonTimeZone*)&tz; 8908393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius canonicalID = otz->getCanonicalID(); 8918393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } 8928393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (canonicalID == NULL) { 8938393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius return NULL; 8948393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } 8958393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius return getShortIDFromCanonical(canonicalID); 8968393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius} 8978393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius 8988393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusconst UChar* 8998393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusZoneMeta::getShortID(const UnicodeString& id) { 9008393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius UErrorCode status = U_ZERO_ERROR; 9018393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius const UChar* canonicalID = ZoneMeta::getCanonicalCLDRID(id, status); 9028393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (U_FAILURE(status) || canonicalID == NULL) { 9038393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius return NULL; 9048393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } 9058393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius return ZoneMeta::getShortIDFromCanonical(canonicalID); 9068393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius} 9078393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius 9088393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusconst UChar* 9098393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusZoneMeta::getShortIDFromCanonical(const UChar* canonicalID) { 9108393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius const UChar* shortID = NULL; 9118393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius int32_t len = u_strlen(canonicalID); 9128393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius char tzidKey[ZID_KEY_MAX + 1]; 9138393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius 9148393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius u_UCharsToChars(canonicalID, tzidKey, len); 9158393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius tzidKey[len] = (char) 0; // Make sure it is null terminated. 9168393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius 9178393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius // replace '/' with ':' 9188393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius char *p = tzidKey; 9198393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius while (*p++) { 9208393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (*p == '/') { 9218393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius *p = ':'; 9228393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } 9238393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } 9248393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius 9258393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius UErrorCode status = U_ZERO_ERROR; 9268393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius UResourceBundle *rb = ures_openDirect(NULL, gKeyTypeData, &status); 9278393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius ures_getByKey(rb, gTypeMapTag, rb, &status); 9288393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius ures_getByKey(rb, gTimezoneTag, rb, &status); 9298393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius shortID = ures_getStringByKey(rb, tzidKey, NULL, &status); 9308393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius ures_close(rb); 9318393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius 9328393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius return shortID; 9338393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius} 934103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_END 936b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_FORMATTING */ 938