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