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 3054dcd9b6a06071f647dac967e9e267abb9410720Craig Corneliusstatic UMutex gZoneMetaLock = U_MUTEX_INITIALIZER; 3150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 32b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// CLDR Canonical ID mapping table 33b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic UHashtable *gCanonicalIDCache = NULL; 3459d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic icu::UInitOnce gCanonicalIDCacheInitOnce = U_INITONCE_INITIALIZER; 35b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 3650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// Metazone mapping table 37b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UHashtable *gOlsonToMeta = NULL; 3859d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic icu::UInitOnce gOlsonToMetaInitOnce = U_INITONCE_INITIALIZER; 39b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 40b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// Available metazone IDs vector and table 41103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic icu::UVector *gMetaZoneIDs = NULL; 42b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic UHashtable *gMetaZoneIDTable = NULL; 4359d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic icu::UInitOnce gMetaZoneIDsInitOnce = U_INITONCE_INITIALIZER; 44b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 4550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho// Country info vectors 46103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic icu::UVector *gSingleZoneCountries = NULL; 47103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic icu::UVector *gMultiZonesCountries = NULL; 4859d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic icu::UInitOnce gCountryInfoVectorsInitOnce = U_INITONCE_INITIALIZER; 49b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 5050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CDECL_BEGIN 51b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 53b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Cleanup callback func 54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool U_CALLCONV zoneMeta_cleanup(void) 56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{ 57b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (gCanonicalIDCache != NULL) { 58b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uhash_close(gCanonicalIDCache); 59b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho gCanonicalIDCache = NULL; 60b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 6159d709d503bab6e2b61931737e662dd293b40578ccornelius gCanonicalIDCacheInitOnce.reset(); 62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (gOlsonToMeta != NULL) { 64b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uhash_close(gOlsonToMeta); 65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru gOlsonToMeta = NULL; 66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 6759d709d503bab6e2b61931737e662dd293b40578ccornelius gOlsonToMetaInitOnce.reset(); 68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 69b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (gMetaZoneIDTable != NULL) { 70b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho uhash_close(gMetaZoneIDTable); 7159d709d503bab6e2b61931737e662dd293b40578ccornelius gMetaZoneIDTable = NULL; 72b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 73b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // delete after closing gMetaZoneIDTable, because it holds 74b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // value objects held by the hashtable 75b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho delete gMetaZoneIDs; 7659d709d503bab6e2b61931737e662dd293b40578ccornelius gMetaZoneIDs = NULL; 7759d709d503bab6e2b61931737e662dd293b40578ccornelius gMetaZoneIDsInitOnce.reset(); 78b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 7950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho delete gSingleZoneCountries; 8059d709d503bab6e2b61931737e662dd293b40578ccornelius gSingleZoneCountries = NULL; 8150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho delete gMultiZonesCountries; 8259d709d503bab6e2b61931737e662dd293b40578ccornelius gMultiZonesCountries = NULL; 8359d709d503bab6e2b61931737e662dd293b40578ccornelius gCountryInfoVectorsInitOnce.reset(); 84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return TRUE; 86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 89b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * Deleter for UChar* string 90b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */ 91b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic void U_CALLCONV 92b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QuerudeleteUCharString(void *obj) { 93b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UChar *entry = (UChar*)obj; 94b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru uprv_free(entry); 95b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 96b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 97b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/** 98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Deleter for UVector 99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void U_CALLCONV 101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerudeleteUVector(void *obj) { 102103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius delete (icu::UVector*) obj; 103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/** 106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Deleter for OlsonToMetaMappingEntry 107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void U_CALLCONV 109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QuerudeleteOlsonToMetaMappingEntry(void *obj) { 110103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius icu::OlsonToMetaMappingEntry *entry = (icu::OlsonToMetaMappingEntry*)obj; 111b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru uprv_free(entry); 112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 113b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_END 115b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 116b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_BEGIN 117b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 118b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ZID_KEY_MAX 128 119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 12050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const char gMetaZones[] = "metaZones"; 12150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const char gMetazoneInfo[] = "metazoneInfo"; 122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const char gMapTimezonesTag[] = "mapTimezones"; 123b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1248393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusstatic const char gKeyTypeData[] = "keyTypeData"; 12550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const char gTypeAliasTag[] = "typeAlias"; 12627f654740f2a26ad62a5c155af9199af9e69b889clairehostatic const char gTypeMapTag[] = "typeMap"; 12750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const char gTimezoneTag[] = "timezone"; 128b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 1298393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusstatic const char gPrimaryZonesTag[] = "primaryZones"; 1308393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius 13150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const char gWorldTag[] = "001"; 132b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 133b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const UChar gWorld[] = {0x30, 0x30, 0x31, 0x00}; // "001" 134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 13550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const UChar gDefaultFrom[] = {0x31, 0x39, 0x37, 0x30, 0x2D, 0x30, 0x31, 0x2D, 0x30, 0x31, 13650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 0x20, 0x30, 0x30, 0x3A, 0x30, 0x30, 0x00}; // "1970-01-01 00:00" 13750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const UChar gDefaultTo[] = {0x39, 0x39, 0x39, 0x39, 0x2D, 0x31, 0x32, 0x2D, 0x33, 0x31, 13850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 0x20, 0x32, 0x33, 0x3A, 0x35, 0x39, 0x00}; // "9999-12-31 23:59" 13950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 140103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic const UChar gCustomTzPrefix[] = {0x47, 0x4D, 0x54, 0}; // "GMT" 141103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ASCII_DIGIT(c) (((c)>=0x30 && (c)<=0x39) ? (c)-0x30 : -1) 143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/* 145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Convert a date string used by metazone mappings to UDate. 146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * The format used by CLDR metazone mapping is "yyyy-MM-dd HH:mm". 147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */ 148c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querustatic UDate 149c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruparseDate (const UChar *text, UErrorCode &status) { 150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_FAILURE(status)) { 151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t len = u_strlen(text); 154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (len != 16 && len != 10) { 155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // It must be yyyy-MM-dd HH:mm (length 16) or yyyy-MM-dd (length 10) 156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_INVALID_FORMAT_ERROR; 157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t year = 0, month = 0, day = 0, hour = 0, min = 0, n; 161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru int32_t idx; 162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // "yyyy" (0 - 3) 164b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (idx = 0; idx <= 3 && U_SUCCESS(status); idx++) { 165b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru n = ASCII_DIGIT((int32_t)text[idx]); 166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (n >= 0) { 167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru year = 10*year + n; 168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_INVALID_FORMAT_ERROR; 170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // "MM" (5 - 6) 173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (idx = 5; idx <= 6 && U_SUCCESS(status); idx++) { 174b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru n = ASCII_DIGIT((int32_t)text[idx]); 175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (n >= 0) { 176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru month = 10*month + n; 177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_INVALID_FORMAT_ERROR; 179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // "dd" (8 - 9) 182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (idx = 8; idx <= 9 && U_SUCCESS(status); idx++) { 183b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru n = ASCII_DIGIT((int32_t)text[idx]); 184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (n >= 0) { 185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru day = 10*day + n; 186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_INVALID_FORMAT_ERROR; 188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (len == 16) { 191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // "HH" (11 - 12) 192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (idx = 11; idx <= 12 && U_SUCCESS(status); idx++) { 193b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru n = ASCII_DIGIT((int32_t)text[idx]); 194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (n >= 0) { 195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru hour = 10*hour + n; 196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_INVALID_FORMAT_ERROR; 198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru // "mm" (14 - 15) 201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru for (idx = 14; idx <= 15 && U_SUCCESS(status); idx++) { 202b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru n = ASCII_DIGIT((int32_t)text[idx]); 203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (n >= 0) { 204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru min = 10*min + n; 205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } else { 206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru status = U_INVALID_FORMAT_ERROR; 207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru if (U_SUCCESS(status)) { 212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UDate date = Grego::fieldsToDay(year, month - 1, day) * U_MILLIS_PER_DAY 213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru + hour * U_MILLIS_PER_HOUR + min * U_MILLIS_PER_MINUTE; 214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return date; 215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return 0; 217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 21959d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic void U_CALLCONV initCanonicalIDCache(UErrorCode &status) { 22059d709d503bab6e2b61931737e662dd293b40578ccornelius gCanonicalIDCache = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status); 22159d709d503bab6e2b61931737e662dd293b40578ccornelius if (gCanonicalIDCache == NULL) { 22259d709d503bab6e2b61931737e662dd293b40578ccornelius status = U_MEMORY_ALLOCATION_ERROR; 22359d709d503bab6e2b61931737e662dd293b40578ccornelius } 22459d709d503bab6e2b61931737e662dd293b40578ccornelius if (U_FAILURE(status)) { 22559d709d503bab6e2b61931737e662dd293b40578ccornelius gCanonicalIDCache = NULL; 22659d709d503bab6e2b61931737e662dd293b40578ccornelius } 22759d709d503bab6e2b61931737e662dd293b40578ccornelius // No key/value deleters - keys/values are from a resource bundle 22859d709d503bab6e2b61931737e662dd293b40578ccornelius ucln_i18n_registerCleanup(UCLN_I18N_ZONEMETA, zoneMeta_cleanup); 22959d709d503bab6e2b61931737e662dd293b40578ccornelius} 23059d709d503bab6e2b61931737e662dd293b40578ccornelius 23159d709d503bab6e2b61931737e662dd293b40578ccornelius 232b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UChar* U_EXPORT2 233b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZoneMeta::getCanonicalCLDRID(const UnicodeString &tzid, UErrorCode& status) { 234b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_FAILURE(status)) { 235b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return NULL; 236b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 237b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 238fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (tzid.isBogus() || tzid.length() > ZID_KEY_MAX) { 23927f654740f2a26ad62a5c155af9199af9e69b889claireho status = U_ILLEGAL_ARGUMENT_ERROR; 240b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return NULL; 241b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 242b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 243b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Checking the cached results 24459d709d503bab6e2b61931737e662dd293b40578ccornelius umtx_initOnce(gCanonicalIDCacheInitOnce, &initCanonicalIDCache, status); 24559d709d503bab6e2b61931737e662dd293b40578ccornelius if (U_FAILURE(status)) { 24659d709d503bab6e2b61931737e662dd293b40578ccornelius return NULL; 247b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 248b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 249b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UChar *canonicalID = NULL; 250b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 251b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UErrorCode tmpStatus = U_ZERO_ERROR; 252b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UChar utzid[ZID_KEY_MAX + 1]; 253b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho tzid.extract(utzid, ZID_KEY_MAX + 1, tmpStatus); 254b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho U_ASSERT(tmpStatus == U_ZERO_ERROR); // we checked the length of tzid already 255b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 256b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Check if it was already cached 257b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho umtx_lock(&gZoneMetaLock); 258b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho { 259b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho canonicalID = (const UChar *)uhash_get(gCanonicalIDCache, utzid); 26027f654740f2a26ad62a5c155af9199af9e69b889claireho } 261b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho umtx_unlock(&gZoneMetaLock); 262c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru 263b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (canonicalID != NULL) { 264b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return canonicalID; 265b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 266b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 267b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // If not, resolve CLDR canonical ID with resource data 268b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UBool isInputCanonical = FALSE; 269b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho char id[ZID_KEY_MAX + 1]; 270f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius tzid.extract(0, 0x7fffffff, id, UPRV_LENGTHOF(id), US_INV); 27127f654740f2a26ad62a5c155af9199af9e69b889claireho 27227f654740f2a26ad62a5c155af9199af9e69b889claireho // replace '/' with ':' 27327f654740f2a26ad62a5c155af9199af9e69b889claireho char *p = id; 27427f654740f2a26ad62a5c155af9199af9e69b889claireho while (*p++) { 27527f654740f2a26ad62a5c155af9199af9e69b889claireho if (*p == '/') { 27627f654740f2a26ad62a5c155af9199af9e69b889claireho *p = ':'; 27750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 27927f654740f2a26ad62a5c155af9199af9e69b889claireho 2808393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius UResourceBundle *top = ures_openDirect(NULL, gKeyTypeData, &tmpStatus); 28127f654740f2a26ad62a5c155af9199af9e69b889claireho UResourceBundle *rb = ures_getByKey(top, gTypeMapTag, NULL, &tmpStatus); 28227f654740f2a26ad62a5c155af9199af9e69b889claireho ures_getByKey(rb, gTimezoneTag, rb, &tmpStatus); 28327f654740f2a26ad62a5c155af9199af9e69b889claireho ures_getByKey(rb, id, rb, &tmpStatus); 28427f654740f2a26ad62a5c155af9199af9e69b889claireho if (U_SUCCESS(tmpStatus)) { 285b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // type entry (canonical) found 286b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // the input is the canonical ID. resolve to const UChar* 287b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho canonicalID = TimeZone::findID(tzid); 288b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho isInputCanonical = TRUE; 28927f654740f2a26ad62a5c155af9199af9e69b889claireho } 29027f654740f2a26ad62a5c155af9199af9e69b889claireho 291b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (canonicalID == NULL) { 292b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // If a map element not found, then look for an alias 293b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho tmpStatus = U_ZERO_ERROR; 294b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho ures_getByKey(top, gTypeAliasTag, rb, &tmpStatus); 295b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho ures_getByKey(rb, gTimezoneTag, rb, &tmpStatus); 296b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UChar *canonical = ures_getStringByKey(rb,id,NULL,&tmpStatus); 297b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_SUCCESS(tmpStatus)) { 298b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // canonical map found 299b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho canonicalID = canonical; 300b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 30127f654740f2a26ad62a5c155af9199af9e69b889claireho 302b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (canonicalID == NULL) { 303b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Dereference the input ID using the tz data 304b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UChar *derefer = TimeZone::dereferOlsonLink(tzid); 305b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (derefer == NULL) { 306b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho status = U_ILLEGAL_ARGUMENT_ERROR; 307b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 308fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t len = u_strlen(derefer); 309b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho u_UCharsToChars(derefer,id,len); 310b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho id[len] = (char) 0; // Make sure it is null terminated. 311b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 312b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // replace '/' with ':' 313b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho char *p = id; 314b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho while (*p++) { 315b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (*p == '/') { 316b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho *p = ':'; 317b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 318b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 31927f654740f2a26ad62a5c155af9199af9e69b889claireho 320b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // If a dereference turned something up then look for an alias. 321b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // rb still points to the alias table, so we don't have to go looking 322b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // for it. 323b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho tmpStatus = U_ZERO_ERROR; 324b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho canonical = ures_getStringByKey(rb,id,NULL,&tmpStatus); 325b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_SUCCESS(tmpStatus)) { 326b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // canonical map for the dereferenced ID found 327b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho canonicalID = canonical; 328b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } else { 329b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho canonicalID = derefer; 330b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho isInputCanonical = TRUE; 331b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 33227f654740f2a26ad62a5c155af9199af9e69b889claireho } 33327f654740f2a26ad62a5c155af9199af9e69b889claireho } 334b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 335b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho ures_close(rb); 336b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho ures_close(top); 33727f654740f2a26ad62a5c155af9199af9e69b889claireho 338b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_SUCCESS(status)) { 339b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho U_ASSERT(canonicalID != NULL); // canocanilD must be non-NULL here 340b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 341b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Put the resolved canonical ID to the cache 342b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho umtx_lock(&gZoneMetaLock); 343b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho { 344b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UChar* idInCache = (const UChar *)uhash_get(gCanonicalIDCache, utzid); 345b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (idInCache == NULL) { 346b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UChar* key = ZoneMeta::findTimeZoneID(tzid); 347b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho U_ASSERT(key != NULL); 348b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (key != NULL) { 349b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho idInCache = (const UChar *)uhash_put(gCanonicalIDCache, (void *)key, (void *)canonicalID, &status); 350b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho U_ASSERT(idInCache == NULL); 351b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 352b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 353b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_SUCCESS(status) && isInputCanonical) { 354b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // Also put canonical ID itself into the cache if not exist 355b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UChar *canonicalInCache = (const UChar*)uhash_get(gCanonicalIDCache, canonicalID); 356b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (canonicalInCache == NULL) { 357b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho canonicalInCache = (const UChar *)uhash_put(gCanonicalIDCache, (void *)canonicalID, (void *)canonicalID, &status); 358b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho U_ASSERT(canonicalInCache == NULL); 359b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 360b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 36127f654740f2a26ad62a5c155af9199af9e69b889claireho } 362b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho umtx_unlock(&gZoneMetaLock); 363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 365b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return canonicalID; 36650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho} 367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 36850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUnicodeString& U_EXPORT2 369b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZoneMeta::getCanonicalCLDRID(const UnicodeString &tzid, UnicodeString &systemID, UErrorCode& status) { 370b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const UChar *canonicalID = getCanonicalCLDRID(tzid, status); 371b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (U_FAILURE(status) || canonicalID == NULL) { 372b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho systemID.setToBogus(); 373b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return systemID; 374b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 375b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho systemID.setTo(TRUE, canonicalID, -1); 376b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return systemID; 377b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 378b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 379b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UChar* U_EXPORT2 380b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZoneMeta::getCanonicalCLDRID(const TimeZone& tz) { 381b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (dynamic_cast<const OlsonTimeZone *>(&tz) != NULL) { 382b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho // short cut for OlsonTimeZone 383b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho const OlsonTimeZone *otz = (const OlsonTimeZone*)&tz; 384b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return otz->getCanonicalID(); 385b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 386b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UErrorCode status = U_ZERO_ERROR; 387b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UnicodeString tzID; 388b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return getCanonicalCLDRID(tz.getID(tzID), status); 389b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 390b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 39159d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic void U_CALLCONV countryInfoVectorsInit(UErrorCode &status) { 39259d709d503bab6e2b61931737e662dd293b40578ccornelius // Create empty vectors 39359d709d503bab6e2b61931737e662dd293b40578ccornelius // No deleters for these UVectors, it's a reference to a resource bundle string. 39459d709d503bab6e2b61931737e662dd293b40578ccornelius gSingleZoneCountries = new UVector(NULL, uhash_compareUChars, status); 39559d709d503bab6e2b61931737e662dd293b40578ccornelius if (gSingleZoneCountries == NULL) { 39659d709d503bab6e2b61931737e662dd293b40578ccornelius status = U_MEMORY_ALLOCATION_ERROR; 39759d709d503bab6e2b61931737e662dd293b40578ccornelius } 39859d709d503bab6e2b61931737e662dd293b40578ccornelius gMultiZonesCountries = new UVector(NULL, uhash_compareUChars, status); 39959d709d503bab6e2b61931737e662dd293b40578ccornelius if (gMultiZonesCountries == NULL) { 40059d709d503bab6e2b61931737e662dd293b40578ccornelius status = U_MEMORY_ALLOCATION_ERROR; 40159d709d503bab6e2b61931737e662dd293b40578ccornelius } 40259d709d503bab6e2b61931737e662dd293b40578ccornelius 40359d709d503bab6e2b61931737e662dd293b40578ccornelius if (U_FAILURE(status)) { 40459d709d503bab6e2b61931737e662dd293b40578ccornelius delete gSingleZoneCountries; 40559d709d503bab6e2b61931737e662dd293b40578ccornelius delete gMultiZonesCountries; 40659d709d503bab6e2b61931737e662dd293b40578ccornelius gSingleZoneCountries = NULL; 40759d709d503bab6e2b61931737e662dd293b40578ccornelius gMultiZonesCountries = NULL; 40859d709d503bab6e2b61931737e662dd293b40578ccornelius } 40959d709d503bab6e2b61931737e662dd293b40578ccornelius ucln_i18n_registerCleanup(UCLN_I18N_ZONEMETA, zoneMeta_cleanup); 41059d709d503bab6e2b61931737e662dd293b40578ccornelius} 41159d709d503bab6e2b61931737e662dd293b40578ccornelius 41259d709d503bab6e2b61931737e662dd293b40578ccornelius 413b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUnicodeString& U_EXPORT2 4148393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusZoneMeta::getCanonicalCountry(const UnicodeString &tzid, UnicodeString &country, UBool *isPrimary /* = NULL */) { 4158393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (isPrimary != NULL) { 4168393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius *isPrimary = FALSE; 41750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 418b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 41950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UChar *region = TimeZone::getRegion(tzid); 4208393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (region != NULL && u_strcmp(gWorld, region) != 0) { 4218393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius country.setTo(region, -1); 4228393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } else { 423b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho country.setToBogus(); 42450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return country; 42550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 4278393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (isPrimary != NULL) { 4288393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius char regionBuf[] = {0, 0, 0}; 4298393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius 4308393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius // Checking the cached results 4318393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius UErrorCode status = U_ZERO_ERROR; 43259d709d503bab6e2b61931737e662dd293b40578ccornelius umtx_initOnce(gCountryInfoVectorsInitOnce, &countryInfoVectorsInit, status); 43359d709d503bab6e2b61931737e662dd293b40578ccornelius if (U_FAILURE(status)) { 43459d709d503bab6e2b61931737e662dd293b40578ccornelius return country; 435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 4378393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius // Check if it was already cached 4388393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius UBool cached = FALSE; 4398393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius UBool singleZone = FALSE; 4408393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius umtx_lock(&gZoneMetaLock); 4418393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius { 4428393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius singleZone = cached = gSingleZoneCountries->contains((void*)region); 4438393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (!cached) { 4448393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius cached = gMultiZonesCountries->contains((void*)region); 4458393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } 446c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru } 4478393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius umtx_unlock(&gZoneMetaLock); 448c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru 4498393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (!cached) { 4508393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius // We need to go through all zones associated with the region. 4518393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius // This is relatively heavy operation. 45250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 4538393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius U_ASSERT(u_strlen(region) == 2); 45450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 4558393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius u_UCharsToChars(region, regionBuf, 2); 45650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 4578393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius StringEnumeration *ids = TimeZone::createTimeZoneIDEnumeration(UCAL_ZONE_TYPE_CANONICAL_LOCATION, regionBuf, NULL, status); 4588393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius int32_t idsLen = ids->count(status); 4598393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (U_SUCCESS(status) && idsLen == 1) { 4608393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius // only the single zone is available for the region 4618393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius singleZone = TRUE; 4628393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } 4638393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius delete ids; 4648393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius 4658393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius // Cache the result 4668393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius umtx_lock(&gZoneMetaLock); 4678393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius { 4688393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius UErrorCode ec = U_ZERO_ERROR; 4698393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (singleZone) { 4708393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (!gSingleZoneCountries->contains((void*)region)) { 4718393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius gSingleZoneCountries->addElement((void*)region, ec); 4728393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } 4738393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } else { 4748393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (!gMultiZonesCountries->contains((void*)region)) { 4758393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius gMultiZonesCountries->addElement((void*)region, ec); 4768393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } 4778393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } 4788393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } 4798393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius umtx_unlock(&gZoneMetaLock); 48050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 48150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 4828393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (singleZone) { 4838393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius *isPrimary = TRUE; 4848393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } else { 4858393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius // Note: We may cache the primary zone map in future. 4868393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius 4878393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius // Even a country has multiple zones, one of them might be 4888393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius // dominant and treated as a primary zone 4898393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius int32_t idLen = 0; 4908393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (regionBuf[0] == 0) { 4918393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius u_UCharsToChars(region, regionBuf, 2); 4928393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } 4938393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius 4948393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius UResourceBundle *rb = ures_openDirect(NULL, gMetaZones, &status); 4958393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius ures_getByKey(rb, gPrimaryZonesTag, rb, &status); 4968393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius const UChar *primaryZone = ures_getStringByKey(rb, regionBuf, &idLen, &status); 4978393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (U_SUCCESS(status)) { 4988393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (tzid.compare(primaryZone, idLen) == 0) { 4998393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius *isPrimary = TRUE; 5008393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } else { 5018393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius // The given ID might not be a canonical ID 5028393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius UnicodeString canonicalID; 5038393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius TimeZone::getCanonicalID(tzid, canonicalID, status); 5048393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (U_SUCCESS(status) && canonicalID.compare(primaryZone, idLen) == 0) { 5058393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius *isPrimary = TRUE; 5068393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } 50750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 5098393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius ures_close(rb); 510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 51350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return country; 514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 51650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUnicodeString& U_EXPORT2 51750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoZoneMeta::getMetazoneID(const UnicodeString &tzid, UDate date, UnicodeString &result) { 51850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UBool isSet = FALSE; 51950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UVector *mappings = getMetazoneMappings(tzid); 52050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (mappings != NULL) { 52150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho for (int32_t i = 0; i < mappings->size(); i++) { 52250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho OlsonToMetaMappingEntry *mzm = (OlsonToMetaMappingEntry*)mappings->elementAt(i); 52350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (mzm->from <= date && mzm->to > date) { 52450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result.setTo(mzm->mzid, -1); 52550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho isSet = TRUE; 526b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 527b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 528b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 529b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 53050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (!isSet) { 531b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho result.setToBogus(); 532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 53350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return result; 534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 53659d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic void U_CALLCONV olsonToMetaInit(UErrorCode &status) { 53759d709d503bab6e2b61931737e662dd293b40578ccornelius U_ASSERT(gOlsonToMeta == NULL); 53859d709d503bab6e2b61931737e662dd293b40578ccornelius ucln_i18n_registerCleanup(UCLN_I18N_ZONEMETA, zoneMeta_cleanup); 53959d709d503bab6e2b61931737e662dd293b40578ccornelius gOlsonToMeta = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status); 54059d709d503bab6e2b61931737e662dd293b40578ccornelius if (U_FAILURE(status)) { 54159d709d503bab6e2b61931737e662dd293b40578ccornelius gOlsonToMeta = NULL; 54259d709d503bab6e2b61931737e662dd293b40578ccornelius } else { 54359d709d503bab6e2b61931737e662dd293b40578ccornelius uhash_setKeyDeleter(gOlsonToMeta, deleteUCharString); 54459d709d503bab6e2b61931737e662dd293b40578ccornelius uhash_setValueDeleter(gOlsonToMeta, deleteUVector); 54559d709d503bab6e2b61931737e662dd293b40578ccornelius } 54659d709d503bab6e2b61931737e662dd293b40578ccornelius} 54759d709d503bab6e2b61931737e662dd293b40578ccornelius 54859d709d503bab6e2b61931737e662dd293b40578ccornelius 54950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoconst UVector* U_EXPORT2 55050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoZoneMeta::getMetazoneMappings(const UnicodeString &tzid) { 551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru UErrorCode status = U_ZERO_ERROR; 552b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho UChar tzidUChars[ZID_KEY_MAX + 1]; 553b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho tzid.extract(tzidUChars, ZID_KEY_MAX + 1, status); 55450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(status) || status == U_STRING_NOT_TERMINATED_WARNING) { 555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return NULL; 556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 55859d709d503bab6e2b61931737e662dd293b40578ccornelius umtx_initOnce(gOlsonToMetaInitOnce, &olsonToMetaInit, status); 55959d709d503bab6e2b61931737e662dd293b40578ccornelius if (U_FAILURE(status)) { 56059d709d503bab6e2b61931737e662dd293b40578ccornelius return NULL; 561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 56350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // get the mapping from cache 56450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UVector *result = NULL; 565b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 566b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru umtx_lock(&gZoneMetaLock); 56750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho { 56850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result = (UVector*) uhash_get(gOlsonToMeta, tzidUChars); 569b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 570b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru umtx_unlock(&gZoneMetaLock); 571b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 57250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (result != NULL) { 57350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return result; 574b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 575c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru 57650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // miss the cache - create new one 57750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UVector *tmpResult = createMetazoneMappings(tzid); 57850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (tmpResult == NULL) { 57950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // not available 58050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return NULL; 581b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 582c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru 58350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // put the new one into the cache 584c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru umtx_lock(&gZoneMetaLock); 58550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho { 58650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // make sure it's already created 58750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result = (UVector*) uhash_get(gOlsonToMeta, tzidUChars); 58850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (result == NULL) { 58950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // add the one just created 59050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t tzidLen = tzid.length() + 1; 59150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UChar *key = (UChar*)uprv_malloc(tzidLen * sizeof(UChar)); 59250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (key == NULL) { 59350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // memory allocation error.. just return NULL 59450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result = NULL; 59550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho delete tmpResult; 59650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 59750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho tzid.extract(key, tzidLen, status); 59850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uhash_put(gOlsonToMeta, key, tmpResult, &status); 59950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(status)) { 60050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // delete the mapping 60150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result = NULL; 60250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho delete tmpResult; 60350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 60450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result = tmpResult; 60550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 60650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 60750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 60850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // another thread already put the one 60950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho delete tmpResult; 61050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 611b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 612b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru umtx_unlock(&gZoneMetaLock); 613b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 61450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return result; 615c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru} 616c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru 61750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoUVector* 61850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoZoneMeta::createMetazoneMappings(const UnicodeString &tzid) { 61950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UVector *mzMappings = NULL; 62050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode status = U_ZERO_ERROR; 621b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 62250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UnicodeString canonicalID; 62350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UResourceBundle *rb = ures_openDirect(NULL, gMetaZones, &status); 62450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_getByKey(rb, gMetazoneInfo, rb, &status); 625b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho getCanonicalCLDRID(tzid, canonicalID, status); 626b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 62750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_SUCCESS(status)) { 628b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho char tzKey[ZID_KEY_MAX + 1]; 629b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho int32_t tzKeyLen = canonicalID.extract(0, canonicalID.length(), tzKey, sizeof(tzKey), US_INV); 630b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho tzKey[tzKeyLen] = 0; 63150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 63250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // tzid keys are using ':' as separators 63350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho char *p = tzKey; 63450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho while (*p) { 63550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (*p == '/') { 63650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho *p = ':'; 63750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 63850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho p++; 639b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 640b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 64150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_getByKey(rb, tzKey, rb, &status); 642b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 64350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_SUCCESS(status)) { 64450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UResourceBundle *mz = NULL; 64550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho while (ures_hasNext(rb)) { 64650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mz = ures_getNextResource(rb, mz, &status); 647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 64850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UChar *mz_name = ures_getStringByIndex(mz, 0, NULL, &status); 64950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UChar *mz_from = gDefaultFrom; 65050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UChar *mz_to = gDefaultTo; 651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 65250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (ures_getSize(mz) == 3) { 65350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mz_from = ures_getStringByIndex(mz, 1, NULL, &status); 65450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mz_to = ures_getStringByIndex(mz, 2, NULL, &status); 65550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 65650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 65750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if(U_FAILURE(status)){ 65850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status = U_ZERO_ERROR; 65950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; 66050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 66150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // We do not want to use SimpleDateformat to parse boundary dates, 66250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // because this code could be triggered by the initialization code 66350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // used by SimpleDateFormat. 66450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UDate from = parseDate(mz_from, status); 66550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UDate to = parseDate(mz_to, status); 66650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(status)) { 66750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status = U_ZERO_ERROR; 66850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho continue; 66950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 67050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 67150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho OlsonToMetaMappingEntry *entry = (OlsonToMetaMappingEntry*)uprv_malloc(sizeof(OlsonToMetaMappingEntry)); 67250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (entry == NULL) { 67350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status = U_MEMORY_ALLOCATION_ERROR; 674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru break; 675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 67650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho entry->mzid = mz_name; 67750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho entry->from = from; 67850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho entry->to = to; 67950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 68050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (mzMappings == NULL) { 68150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mzMappings = new UVector(deleteOlsonToMetaMappingEntry, NULL, status); 68250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(status)) { 68350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho delete mzMappings; 68450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho deleteOlsonToMetaMappingEntry(entry); 68550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho uprv_free(entry); 68650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 68750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 68850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 68950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 69050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mzMappings->addElement(entry, status); 69150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(status)) { 69250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho break; 69350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 69450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 69550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_close(mz); 69650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_FAILURE(status)) { 69750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (mzMappings != NULL) { 69850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho delete mzMappings; 69950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho mzMappings = NULL; 70050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 70450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_close(rb); 70550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return mzMappings; 706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 708c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruUnicodeString& U_EXPORT2 70950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoZoneMeta::getZoneIdByMetazone(const UnicodeString &mzid, const UnicodeString ®ion, UnicodeString &result) { 71050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UErrorCode status = U_ZERO_ERROR; 71150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho const UChar *tzid = NULL; 71250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t tzidLen = 0; 71350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho char keyBuf[ZID_KEY_MAX + 1]; 71450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho int32_t keyLen = 0; 71550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 716fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (mzid.isBogus() || mzid.length() > ZID_KEY_MAX) { 717b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho result.setToBogus(); 71850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho return result; 719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 721b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho keyLen = mzid.extract(0, mzid.length(), keyBuf, ZID_KEY_MAX + 1, US_INV); 722b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho keyBuf[keyLen] = 0; 723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 72450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UResourceBundle *rb = ures_openDirect(NULL, gMetaZones, &status); 72550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_getByKey(rb, gMapTimezonesTag, rb, &status); 72650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_getByKey(rb, keyBuf, rb, &status); 72750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 72850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_SUCCESS(status)) { 72950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // check region mapping 73050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (region.length() == 2 || region.length() == 3) { 731b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho keyLen = region.extract(0, region.length(), keyBuf, ZID_KEY_MAX + 1, US_INV); 732b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho keyBuf[keyLen] = 0; 73350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho tzid = ures_getStringByKey(rb, keyBuf, &tzidLen, &status); 73450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (status == U_MISSING_RESOURCE_ERROR) { 73550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho status = U_ZERO_ERROR; 736b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 737b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 73850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (U_SUCCESS(status) && tzid == NULL) { 73950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho // try "001" 74050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho tzid = ures_getStringByKey(rb, gWorldTag, &tzidLen, &status); 74150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 74350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_close(rb); 74450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 74550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (tzid == NULL) { 746b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho result.setToBogus(); 74750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } else { 74850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho result.setTo(tzid, tzidLen); 749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru } 75050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho 751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru return result; 752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru} 753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 75459d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic void U_CALLCONV initAvailableMetaZoneIDs () { 75559d709d503bab6e2b61931737e662dd293b40578ccornelius U_ASSERT(gMetaZoneIDs == NULL); 75659d709d503bab6e2b61931737e662dd293b40578ccornelius U_ASSERT(gMetaZoneIDTable == NULL); 75759d709d503bab6e2b61931737e662dd293b40578ccornelius ucln_i18n_registerCleanup(UCLN_I18N_ZONEMETA, zoneMeta_cleanup); 75859d709d503bab6e2b61931737e662dd293b40578ccornelius 75959d709d503bab6e2b61931737e662dd293b40578ccornelius UErrorCode status = U_ZERO_ERROR; 76059d709d503bab6e2b61931737e662dd293b40578ccornelius gMetaZoneIDTable = uhash_open(uhash_hashUnicodeString, uhash_compareUnicodeString, NULL, &status); 76159d709d503bab6e2b61931737e662dd293b40578ccornelius if (U_FAILURE(status) || gMetaZoneIDTable == NULL) { 76259d709d503bab6e2b61931737e662dd293b40578ccornelius gMetaZoneIDTable = NULL; 76359d709d503bab6e2b61931737e662dd293b40578ccornelius return; 76459d709d503bab6e2b61931737e662dd293b40578ccornelius } 76559d709d503bab6e2b61931737e662dd293b40578ccornelius uhash_setKeyDeleter(gMetaZoneIDTable, uprv_deleteUObject); 76659d709d503bab6e2b61931737e662dd293b40578ccornelius // No valueDeleter, because the vector maintain the value objects 76759d709d503bab6e2b61931737e662dd293b40578ccornelius gMetaZoneIDs = new UVector(NULL, uhash_compareUChars, status); 76859d709d503bab6e2b61931737e662dd293b40578ccornelius if (U_FAILURE(status) || gMetaZoneIDs == NULL) { 76959d709d503bab6e2b61931737e662dd293b40578ccornelius gMetaZoneIDs = NULL; 77059d709d503bab6e2b61931737e662dd293b40578ccornelius uhash_close(gMetaZoneIDTable); 77159d709d503bab6e2b61931737e662dd293b40578ccornelius gMetaZoneIDTable = NULL; 77259d709d503bab6e2b61931737e662dd293b40578ccornelius return; 77359d709d503bab6e2b61931737e662dd293b40578ccornelius } 77459d709d503bab6e2b61931737e662dd293b40578ccornelius gMetaZoneIDs->setDeleter(uprv_free); 77559d709d503bab6e2b61931737e662dd293b40578ccornelius 77659d709d503bab6e2b61931737e662dd293b40578ccornelius UResourceBundle *rb = ures_openDirect(NULL, gMetaZones, &status); 77759d709d503bab6e2b61931737e662dd293b40578ccornelius UResourceBundle *bundle = ures_getByKey(rb, gMapTimezonesTag, NULL, &status); 77859d709d503bab6e2b61931737e662dd293b40578ccornelius UResourceBundle res; 77959d709d503bab6e2b61931737e662dd293b40578ccornelius ures_initStackObject(&res); 78059d709d503bab6e2b61931737e662dd293b40578ccornelius while (U_SUCCESS(status) && ures_hasNext(bundle)) { 78159d709d503bab6e2b61931737e662dd293b40578ccornelius ures_getNextResource(bundle, &res, &status); 78259d709d503bab6e2b61931737e662dd293b40578ccornelius if (U_FAILURE(status)) { 78359d709d503bab6e2b61931737e662dd293b40578ccornelius break; 784b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 78559d709d503bab6e2b61931737e662dd293b40578ccornelius const char *mzID = ures_getKey(&res); 78659d709d503bab6e2b61931737e662dd293b40578ccornelius int32_t len = uprv_strlen(mzID); 78759d709d503bab6e2b61931737e662dd293b40578ccornelius UChar *uMzID = (UChar*)uprv_malloc(sizeof(UChar) * (len + 1)); 78859d709d503bab6e2b61931737e662dd293b40578ccornelius if (uMzID == NULL) { 78959d709d503bab6e2b61931737e662dd293b40578ccornelius status = U_MEMORY_ALLOCATION_ERROR; 79059d709d503bab6e2b61931737e662dd293b40578ccornelius break; 79159d709d503bab6e2b61931737e662dd293b40578ccornelius } 79259d709d503bab6e2b61931737e662dd293b40578ccornelius u_charsToUChars(mzID, uMzID, len); 79359d709d503bab6e2b61931737e662dd293b40578ccornelius uMzID[len] = 0; 79459d709d503bab6e2b61931737e662dd293b40578ccornelius UnicodeString *usMzID = new UnicodeString(uMzID); 79559d709d503bab6e2b61931737e662dd293b40578ccornelius if (uhash_get(gMetaZoneIDTable, usMzID) == NULL) { 79659d709d503bab6e2b61931737e662dd293b40578ccornelius gMetaZoneIDs->addElement((void *)uMzID, status); 79759d709d503bab6e2b61931737e662dd293b40578ccornelius uhash_put(gMetaZoneIDTable, (void *)usMzID, (void *)uMzID, &status); 79859d709d503bab6e2b61931737e662dd293b40578ccornelius } else { 79959d709d503bab6e2b61931737e662dd293b40578ccornelius uprv_free(uMzID); 80059d709d503bab6e2b61931737e662dd293b40578ccornelius delete usMzID; 80159d709d503bab6e2b61931737e662dd293b40578ccornelius } 80259d709d503bab6e2b61931737e662dd293b40578ccornelius } 80359d709d503bab6e2b61931737e662dd293b40578ccornelius ures_close(&res); 80459d709d503bab6e2b61931737e662dd293b40578ccornelius ures_close(bundle); 80559d709d503bab6e2b61931737e662dd293b40578ccornelius ures_close(rb); 80659d709d503bab6e2b61931737e662dd293b40578ccornelius 80759d709d503bab6e2b61931737e662dd293b40578ccornelius if (U_FAILURE(status)) { 80859d709d503bab6e2b61931737e662dd293b40578ccornelius uhash_close(gMetaZoneIDTable); 80959d709d503bab6e2b61931737e662dd293b40578ccornelius delete gMetaZoneIDs; 81059d709d503bab6e2b61931737e662dd293b40578ccornelius gMetaZoneIDTable = NULL; 81159d709d503bab6e2b61931737e662dd293b40578ccornelius gMetaZoneIDs = NULL; 812b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 813b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 814b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 815b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UVector* 816b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZoneMeta::getAvailableMetazoneIDs() { 81759d709d503bab6e2b61931737e662dd293b40578ccornelius umtx_initOnce(gMetaZoneIDsInitOnce, &initAvailableMetaZoneIDs); 818b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return gMetaZoneIDs; 819b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 820b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 821b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UChar* 822b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZoneMeta::findMetaZoneID(const UnicodeString& mzid) { 82359d709d503bab6e2b61931737e662dd293b40578ccornelius umtx_initOnce(gMetaZoneIDsInitOnce, &initAvailableMetaZoneIDs); 82459d709d503bab6e2b61931737e662dd293b40578ccornelius if (gMetaZoneIDTable == NULL) { 82559d709d503bab6e2b61931737e662dd293b40578ccornelius return NULL; 82659d709d503bab6e2b61931737e662dd293b40578ccornelius } 827b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return (const UChar*)uhash_get(gMetaZoneIDTable, &mzid); 828b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 829b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 830b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UChar* 831b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoZoneMeta::findTimeZoneID(const UnicodeString& tzid) { 832b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return TimeZone::findID(tzid); 833b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho} 834b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho 835103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 836103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTimeZone* 837103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusZoneMeta::createCustomTimeZone(int32_t offset) { 838103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UBool negative = FALSE; 839103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius int32_t tmp = offset; 840103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (offset < 0) { 841103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius negative = TRUE; 842103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius tmp = -offset; 843103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 844103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius int32_t hour, min, sec; 845103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 846103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius tmp /= 1000; 847103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius sec = tmp % 60; 848103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius tmp /= 60; 849103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius min = tmp % 60; 850103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius hour = tmp / 60; 851103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 852103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius UnicodeString zid; 853103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius formatCustomID(hour, min, sec, negative, zid); 854103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return new SimpleTimeZone(offset, zid); 855103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius} 856103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 857103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusUnicodeString& 858103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusZoneMeta::formatCustomID(uint8_t hour, uint8_t min, uint8_t sec, UBool negative, UnicodeString& id) { 859103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // Create normalized time zone ID - GMT[+|-]HH:mm[:ss] 860103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius id.setTo(gCustomTzPrefix, -1); 861103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (hour != 0 || min != 0) { 862103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (negative) { 86354dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius id.append((UChar)0x2D); // '-' 864103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } else { 86554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius id.append((UChar)0x2B); // '+' 866103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 867103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius // Always use US-ASCII digits 86854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius id.append((UChar)(0x30 + (hour%100)/10)); 86954dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius id.append((UChar)(0x30 + (hour%10))); 87054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius id.append((UChar)0x3A); // ':' 87154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius id.append((UChar)(0x30 + (min%100)/10)); 87254dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius id.append((UChar)(0x30 + (min%10))); 873103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius if (sec != 0) { 87454dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius id.append((UChar)0x3A); // ':' 87554dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius id.append((UChar)(0x30 + (sec%100)/10)); 87654dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius id.append((UChar)(0x30 + (sec%10))); 877103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 878103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius } 879103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius return id; 880103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius} 881103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 8828393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusconst UChar* 8838393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusZoneMeta::getShortID(const TimeZone& tz) { 8848393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius const UChar* canonicalID = NULL; 8858393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (dynamic_cast<const OlsonTimeZone *>(&tz) != NULL) { 8868393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius // short cut for OlsonTimeZone 8878393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius const OlsonTimeZone *otz = (const OlsonTimeZone*)&tz; 8888393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius canonicalID = otz->getCanonicalID(); 8898393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } 8908393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (canonicalID == NULL) { 8918393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius return NULL; 8928393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } 8938393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius return getShortIDFromCanonical(canonicalID); 8948393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius} 8958393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius 8968393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusconst UChar* 8978393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusZoneMeta::getShortID(const UnicodeString& id) { 8988393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius UErrorCode status = U_ZERO_ERROR; 8998393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius const UChar* canonicalID = ZoneMeta::getCanonicalCLDRID(id, status); 9008393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (U_FAILURE(status) || canonicalID == NULL) { 9018393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius return NULL; 9028393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } 9038393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius return ZoneMeta::getShortIDFromCanonical(canonicalID); 9048393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius} 9058393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius 9068393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Corneliusconst UChar* 9078393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig CorneliusZoneMeta::getShortIDFromCanonical(const UChar* canonicalID) { 9088393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius const UChar* shortID = NULL; 9098393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius int32_t len = u_strlen(canonicalID); 9108393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius char tzidKey[ZID_KEY_MAX + 1]; 9118393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius 9128393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius u_UCharsToChars(canonicalID, tzidKey, len); 9138393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius tzidKey[len] = (char) 0; // Make sure it is null terminated. 9148393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius 9158393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius // replace '/' with ':' 9168393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius char *p = tzidKey; 9178393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius while (*p++) { 9188393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius if (*p == '/') { 9198393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius *p = ':'; 9208393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } 9218393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius } 9228393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius 9238393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius UErrorCode status = U_ZERO_ERROR; 9248393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius UResourceBundle *rb = ures_openDirect(NULL, gKeyTypeData, &status); 9258393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius ures_getByKey(rb, gTypeMapTag, rb, &status); 9268393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius ures_getByKey(rb, gTimezoneTag, rb, &status); 9278393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius shortID = ures_getStringByKey(rb, tzidKey, NULL, &status); 9288393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius ures_close(rb); 9298393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius 9308393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius return shortID; 9318393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius} 932103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius 933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_END 934b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru 935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_FORMATTING */ 936