10596faeddefbf198de137d5e893708495ab1584cFredrik Roubert// © 2016 and later: Unicode, Inc. and others.
264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html
3b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
4b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*******************************************************************************
564339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert* Copyright (C) 1997-2016, International Business Machines Corporation and
659d709d503bab6e2b61931737e662dd293b40578ccornelius* others. All Rights Reserved.
7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*******************************************************************************
8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* File TIMEZONE.CPP
10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Modification History:
12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   Date        Name        Description
14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   12/05/96    clhuang     Creation.
15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   04/21/97    aliu        General clean-up and bug fixing.
16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   05/08/97    aliu        Fixed Hashtable code per code review.
17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   07/09/97    helena      Changed createInstance to createDefault.
18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   07/29/97    aliu        Updated with all-new list of 96 UNIX-derived
19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                           TimeZones.  Changed mechanism to load from static
20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                           array rather than resource bundle.
21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   07/07/1998  srl         Bugfixes from the Java side: UTC GMT CAT NST
22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                           Added getDisplayName API
23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                           going to add custom parsing.
24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                           ISSUES:
26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                               - should getDisplayName cache something?
27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                               - should custom time zones be cached? [probably]
28b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*  08/10/98     stephen     Brought getDisplayName() API in-line w/ conventions
29b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*  08/19/98     stephen     Changed createTimeZone() to never return 0
30b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*  09/02/98     stephen     Added getOffset(monthLen) and hasSameRules()
31b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*  09/15/98     stephen     Added getStaticClassID()
32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*  02/22/99     stephen     Removed character literals for EBCDIC safety
33b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*  05/04/99     stephen     Changed initDefault() for Mutex issues
34b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*  07/12/99     helena      HPUX 11 CC Port.
35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*  12/03/99     aliu        Moved data out of static table into icudata.dll.
36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                           Substantial rewrite of zone lookup, default zone, and
37b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                           available IDs code.  Misc. cleanup.
38b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*********************************************************************************/
39b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
4054dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#include "utypeinfo.h"  // for 'typeid' to work
4127f654740f2a26ad62a5c155af9199af9e69b889claireho
42b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/utypes.h"
43b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/ustring.h"
4459d709d503bab6e2b61931737e662dd293b40578ccornelius#include "uassert.h"
45b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "ustr_imp.h"
46b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
47b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef U_DEBUG_TZ
48b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru# include <stdio.h>
49b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru# include "uresimp.h" // for debugging
50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
51b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void debug_tz_loc(const char *f, int32_t l)
52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
53b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  fprintf(stderr, "%s:%d: ", f, l);
54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void debug_tz_msg(const char *pat, ...)
57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
58b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  va_list ap;
59b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  va_start(ap, pat);
60b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  vfprintf(stderr, pat, ap);
61b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  fflush(stderr);
62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic char gStrBuf[256];
64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define U_DEBUG_TZ_STR(x) u_austrncpy(gStrBuf,x,sizeof(gStrBuf)-1)
65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// must use double parens, i.e.:  U_DEBUG_TZ_MSG(("four is: %d",4));
66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define U_DEBUG_TZ_MSG(x) {debug_tz_loc(__FILE__,__LINE__);debug_tz_msg x;}
67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define U_DEBUG_TZ_MSG(x)
69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_FORMATTING
72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/simpletz.h"
74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/calendar.h"
75b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/gregocal.h"
76b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/ures.h"
77103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "unicode/tzfmt.h"
78103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "unicode/numfmt.h"
79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "gregoimp.h"
80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uresimp.h" // struct UResourceBundle
81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "olsontz.h"
82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "mutex.h"
83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/udata.h"
84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ucln_in.h"
85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cstring.h"
86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cmemory.h"
87b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/strenum.h"
88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uassert.h"
89c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#include "zonemeta.h"
90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
9150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define kZONEINFO "zoneinfo64"
92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define kREGIONS  "Regions"
93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define kZONES    "Zones"
94b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define kRULES    "Rules"
95b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define kNAMES    "Names"
9650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define kTZVERSION  "TZVersion"
9750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define kLINKS    "links"
98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define kMAX_CUSTOM_HOUR    23
99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define kMAX_CUSTOM_MIN     59
100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define kMAX_CUSTOM_SEC     59
101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define MINUS 0x002D
102b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define PLUS 0x002B
103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ZERO_DIGIT 0x0030
104b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define COLON 0x003A
105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
106b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Static data and constants
107b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
10850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const UChar         WORLD[] = {0x30, 0x30, 0x31, 0x00}; /* "001" */
10950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const UChar         GMT_ID[] = {0x47, 0x4D, 0x54, 0x00}; /* "GMT" */
111b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar         UNKNOWN_ZONE_ID[] = {0x45, 0x74, 0x63, 0x2F, 0x55, 0x6E, 0x6B, 0x6E, 0x6F, 0x77, 0x6E, 0x00}; /* "Etc/Unknown" */
112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const int32_t       GMT_ID_LENGTH = 3;
113b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const int32_t       UNKNOWN_ZONE_ID_LENGTH = 11;
114b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
115103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic icu::TimeZone* DEFAULT_ZONE = NULL;
11659d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic icu::UInitOnce gDefaultZoneInitOnce = U_INITONCE_INITIALIZER;
11759d709d503bab6e2b61931737e662dd293b40578ccornelius
118103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic icu::TimeZone* _GMT = NULL;
119103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic icu::TimeZone* _UNKNOWN_ZONE = NULL;
12059d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic icu::UInitOnce gStaticZonesInitOnce = U_INITONCE_INITIALIZER;
121b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
122c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querustatic char TZDATA_VERSION[16];
12359d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic icu::UInitOnce gTZDataVersionInitOnce = U_INITONCE_INITIALIZER;
124b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
125b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic int32_t* MAP_SYSTEM_ZONES = NULL;
126b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic int32_t* MAP_CANONICAL_SYSTEM_ZONES = NULL;
127b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic int32_t* MAP_CANONICAL_SYSTEM_LOCATION_ZONES = NULL;
128b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
129103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic int32_t LEN_SYSTEM_ZONES = 0;
130103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic int32_t LEN_CANONICAL_SYSTEM_ZONES = 0;
131103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic int32_t LEN_CANONICAL_SYSTEM_LOCATION_ZONES = 0;
132b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
13359d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic icu::UInitOnce gSystemZonesInitOnce = U_INITONCE_INITIALIZER;
13459d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic icu::UInitOnce gCanonicalZonesInitOnce = U_INITONCE_INITIALIZER;
13559d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic icu::UInitOnce gCanonicalLocationZonesInitOnce = U_INITONCE_INITIALIZER;
13659d709d503bab6e2b61931737e662dd293b40578ccornelius
137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_BEGIN
138b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool U_CALLCONV timeZone_cleanup(void)
139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
14059d709d503bab6e2b61931737e662dd293b40578ccornelius    U_NAMESPACE_USE
141b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete DEFAULT_ZONE;
142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DEFAULT_ZONE = NULL;
14359d709d503bab6e2b61931737e662dd293b40578ccornelius    gDefaultZoneInitOnce.reset();
144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete _GMT;
146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    _GMT = NULL;
147103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    delete _UNKNOWN_ZONE;
148103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    _UNKNOWN_ZONE = NULL;
14959d709d503bab6e2b61931737e662dd293b40578ccornelius    gStaticZonesInitOnce.reset();
150103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_memset(TZDATA_VERSION, 0, sizeof(TZDATA_VERSION));
15259d709d503bab6e2b61931737e662dd293b40578ccornelius    gTZDataVersionInitOnce.reset();
153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
154b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    LEN_SYSTEM_ZONES = 0;
155b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uprv_free(MAP_SYSTEM_ZONES);
156b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    MAP_SYSTEM_ZONES = 0;
15759d709d503bab6e2b61931737e662dd293b40578ccornelius    gSystemZonesInitOnce.reset();
158b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
159b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    LEN_CANONICAL_SYSTEM_ZONES = 0;
160b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uprv_free(MAP_CANONICAL_SYSTEM_ZONES);
161b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    MAP_CANONICAL_SYSTEM_ZONES = 0;
16259d709d503bab6e2b61931737e662dd293b40578ccornelius    gCanonicalZonesInitOnce.reset();
163b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
164b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    LEN_CANONICAL_SYSTEM_LOCATION_ZONES = 0;
165b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uprv_free(MAP_CANONICAL_SYSTEM_LOCATION_ZONES);
166b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    MAP_CANONICAL_SYSTEM_LOCATION_ZONES = 0;
16759d709d503bab6e2b61931737e662dd293b40578ccornelius    gCanonicalLocationZonesInitOnce.reset();
168b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_END
172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_BEGIN
174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t findInStringArray(UResourceBundle* array, const UnicodeString& id, UErrorCode &status)
176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString copy;
178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const UChar *u;
179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t len;
180b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t start = 0;
182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t limit = ures_getSize(array);
183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t mid;
184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t lastMid = INT32_MAX;
185b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(U_FAILURE(status) || (limit < 1)) {
186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return -1;
187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_DEBUG_TZ_MSG(("fisa: Looking for %s, between %d and %d\n", U_DEBUG_TZ_STR(UnicodeString(id).getTerminatedBuffer()), start, limit));
189b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (;;) {
191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        mid = (int32_t)((start + limit) / 2);
192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (lastMid == mid) {   /* Have we moved? */
193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;  /* We haven't moved, and it wasn't found. */
194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        lastMid = mid;
196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        u = ures_getStringByIndex(array, mid, &len, &status);
197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_FAILURE(status)) {
198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        U_DEBUG_TZ_MSG(("tz: compare to %s, %d .. [%d] .. %d\n", U_DEBUG_TZ_STR(u), start, mid, limit));
201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        copy.setTo(TRUE, u, len);
202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int r = id.compare(copy);
203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(r==0) {
204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            U_DEBUG_TZ_MSG(("fisa: found at %d\n", mid));
205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return mid;
206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else if(r<0) {
207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            limit = mid;
208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            start = mid;
210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_DEBUG_TZ_MSG(("fisa: not found\n"));
213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
215b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
217b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * Fetch a specific zone by name.  Replaces the getByKey call.
218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param top Top timezone resource
219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param id Time zone ID
220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param oldbundle Bundle for reuse (or NULL).   see 'ures_open()'
221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @return the zone's bundle if found, or undefined if error.  Reuses oldbundle.
222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UResourceBundle* getZoneByName(const UResourceBundle* top, const UnicodeString& id, UResourceBundle *oldbundle, UErrorCode& status) {
224b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // load the Rules object
225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UResourceBundle *tmp = ures_getByKey(top, kNAMES, NULL, &status);
226b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
227b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // search for the string
228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t idx = findInStringArray(tmp, id, status);
229b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if((idx == -1) && U_SUCCESS(status)) {
231b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // not found
232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        status = U_MISSING_RESOURCE_ERROR;
233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        //ures_close(oldbundle);
234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        //oldbundle = NULL;
235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
236b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        U_DEBUG_TZ_MSG(("gzbn: oldbundle= size %d, type %d, %s\n", ures_getSize(tmp), ures_getType(tmp), u_errorName(status)));
237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        tmp = ures_getByKey(top, kZONES, tmp, &status); // get Zones object from top
238b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        U_DEBUG_TZ_MSG(("gzbn: loaded ZONES, size %d, type %d, path %s %s\n", ures_getSize(tmp), ures_getType(tmp), ures_getPath(tmp), u_errorName(status)));
239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        oldbundle = ures_getByIndex(tmp, idx, oldbundle, &status); // get nth Zone object
240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        U_DEBUG_TZ_MSG(("gzbn: loaded z#%d, size %d, type %d, path %s, %s\n", idx, ures_getSize(oldbundle), ures_getType(oldbundle), ures_getPath(oldbundle),  u_errorName(status)));
241b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_close(tmp);
243b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(U_FAILURE(status)) {
244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        //ures_close(oldbundle);
245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return oldbundle;
248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUResourceBundle* TimeZone::loadRule(const UResourceBundle* top, const UnicodeString& ruleid, UResourceBundle* oldbundle, UErrorCode& status) {
253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char key[64];
254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ruleid.extract(0, sizeof(key)-1, key, (int32_t)sizeof(key)-1, US_INV);
255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_DEBUG_TZ_MSG(("loadRule(%s)\n", key));
256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UResourceBundle *r = ures_getByKey(top, kRULES, oldbundle, &status);
257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_DEBUG_TZ_MSG(("loadRule(%s) -> kRULES [%s]\n", key, u_errorName(status)));
258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    r = ures_getByKey(r, key, r, &status);
259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_DEBUG_TZ_MSG(("loadRule(%s) -> item [%s]\n", key, u_errorName(status)));
260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return r;
261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Given an ID, open the appropriate resource for the given time zone.
265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Dereference aliases if necessary.
266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param id zone id
267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param res resource, which must be ready for use (initialized but not open)
268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param ec input-output error code
269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @return top-level resource bundle
270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UResourceBundle* openOlsonResource(const UnicodeString& id,
272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                          UResourceBundle& res,
273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                          UErrorCode& ec)
274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if U_DEBUG_TZ
276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char buf[128];
277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    id.extract(0, sizeof(buf)-1, buf, sizeof(buf), "");
278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UResourceBundle *top = ures_openDirect(0, kZONEINFO, &ec);
280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_DEBUG_TZ_MSG(("pre: res sz=%d\n", ures_getSize(&res)));
281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* &res = */ getZoneByName(top, id, &res, ec);
282b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Dereference if this is an alias.  Docs say result should be 1
283b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // but it is 0 in 2.8 (?).
284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_DEBUG_TZ_MSG(("Loading zone '%s' (%s, size %d) - %s\n", buf, ures_getKey((UResourceBundle*)&res), ures_getSize(&res), u_errorName(ec)));
285b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (ures_getType(&res) == URES_INT) {
286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t deref = ures_getInt(&res, &ec) + 0;
287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        U_DEBUG_TZ_MSG(("getInt: %s - type is %d\n", u_errorName(ec), ures_getType(&res)));
288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UResourceBundle *ares = ures_getByKey(top, kZONES, NULL, &ec); // dereference Zones section
289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ures_getByIndex(ares, deref, &res, &ec);
290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ures_close(ares);
291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        U_DEBUG_TZ_MSG(("alias to #%d (%s) - %s\n", deref, "??", u_errorName(ec)));
292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        U_DEBUG_TZ_MSG(("not an alias - size %d\n", ures_getSize(&res)));
294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_DEBUG_TZ_MSG(("%s - final status is %s\n", buf, u_errorName(ec)));
296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return top;
297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
301103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusnamespace {
302103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
30359d709d503bab6e2b61931737e662dd293b40578ccorneliusvoid U_CALLCONV initStaticTimeZones() {
304b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Initialize _GMT independently of other static data; it should
305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // be valid even if we can't load the time zone UDataMemory.
30659d709d503bab6e2b61931737e662dd293b40578ccornelius    ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
30759d709d503bab6e2b61931737e662dd293b40578ccornelius    _UNKNOWN_ZONE = new SimpleTimeZone(0, UnicodeString(TRUE, UNKNOWN_ZONE_ID, UNKNOWN_ZONE_ID_LENGTH));
30859d709d503bab6e2b61931737e662dd293b40578ccornelius    _GMT = new SimpleTimeZone(0, UnicodeString(TRUE, GMT_ID, GMT_ID_LENGTH));
309103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
310103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
311103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}  // anonymous namespace
312103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
313103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusconst TimeZone& U_EXPORT2
314103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTimeZone::getUnknown()
315103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius{
31659d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_initOnce(gStaticZonesInitOnce, &initStaticTimeZones);
317103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return *_UNKNOWN_ZONE;
318103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
319103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
320103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusconst TimeZone* U_EXPORT2
321103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTimeZone::getGMT(void)
322103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius{
32359d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_initOnce(gStaticZonesInitOnce, &initStaticTimeZones);
324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return _GMT;
325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// *****************************************************************************
328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// class TimeZone
329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// *****************************************************************************
330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUOBJECT_DEFINE_ABSTRACT_RTTI_IMPLEMENTATION(TimeZone)
332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::TimeZone()
334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    :   UObject(), fID()
335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::TimeZone(const UnicodeString &id)
341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    :   UObject(), fID(id)
342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::~TimeZone()
348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::TimeZone(const TimeZone &source)
354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    :   UObject(source), fID(source.fID)
355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone &
361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::operator=(const TimeZone &right)
362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (this != &right) fID = right.fID;
364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::operator==(const TimeZone& that) const
371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
37227f654740f2a26ad62a5c155af9199af9e69b889claireho    return typeid(*this) == typeid(that) &&
373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fID == that.fID;
374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
37859d709d503bab6e2b61931737e662dd293b40578ccorneliusnamespace {
379b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZone*
38059d709d503bab6e2b61931737e662dd293b40578ccorneliuscreateSystemTimeZone(const UnicodeString& id, UErrorCode& ec) {
381b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(ec)) {
382b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
383b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
384b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TimeZone* z = 0;
385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UResourceBundle res;
386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_initStackObject(&res);
387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_DEBUG_TZ_MSG(("pre-err=%s\n", u_errorName(ec)));
388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UResourceBundle *top = openOlsonResource(id, res, ec);
389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_DEBUG_TZ_MSG(("post-err=%s\n", u_errorName(ec)));
390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_SUCCESS(ec)) {
391b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        z = new OlsonTimeZone(top, &res, id, ec);
392b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (z == NULL) {
393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          U_DEBUG_TZ_MSG(("cstz: olson time zone failed to initialize - err %s\n", u_errorName(ec)));
394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_close(&res);
397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_close(top);
398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(ec)) {
399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        U_DEBUG_TZ_MSG(("cstz: failed to create, err %s\n", u_errorName(ec)));
400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete z;
401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        z = 0;
402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return z;
404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
40659d709d503bab6e2b61931737e662dd293b40578ccornelius/**
40759d709d503bab6e2b61931737e662dd293b40578ccornelius * Lookup the given name in our system zone table.  If found,
40859d709d503bab6e2b61931737e662dd293b40578ccornelius * instantiate a new zone of that name and return it.  If not
40959d709d503bab6e2b61931737e662dd293b40578ccornelius * found, return 0.
41059d709d503bab6e2b61931737e662dd293b40578ccornelius */
41159d709d503bab6e2b61931737e662dd293b40578ccorneliusTimeZone*
41259d709d503bab6e2b61931737e662dd293b40578ccorneliuscreateSystemTimeZone(const UnicodeString& id) {
41359d709d503bab6e2b61931737e662dd293b40578ccornelius    UErrorCode ec = U_ZERO_ERROR;
41459d709d503bab6e2b61931737e662dd293b40578ccornelius    return createSystemTimeZone(id, ec);
41559d709d503bab6e2b61931737e662dd293b40578ccornelius}
41659d709d503bab6e2b61931737e662dd293b40578ccornelius
41759d709d503bab6e2b61931737e662dd293b40578ccornelius}
41859d709d503bab6e2b61931737e662dd293b40578ccornelius
41959d709d503bab6e2b61931737e662dd293b40578ccorneliusTimeZone* U_EXPORT2
42059d709d503bab6e2b61931737e662dd293b40578ccorneliusTimeZone::createTimeZone(const UnicodeString& ID)
42159d709d503bab6e2b61931737e662dd293b40578ccornelius{
42259d709d503bab6e2b61931737e662dd293b40578ccornelius    /* We first try to lookup the zone ID in our system list.  If this
42359d709d503bab6e2b61931737e662dd293b40578ccornelius     * fails, we try to parse it as a custom string GMT[+-]hh:mm.  If
42459d709d503bab6e2b61931737e662dd293b40578ccornelius     * all else fails, we return GMT, which is probably not what the
42559d709d503bab6e2b61931737e662dd293b40578ccornelius     * user wants, but at least is a functioning TimeZone object.
42659d709d503bab6e2b61931737e662dd293b40578ccornelius     *
42759d709d503bab6e2b61931737e662dd293b40578ccornelius     * We cannot return NULL, because that would break compatibility
42859d709d503bab6e2b61931737e662dd293b40578ccornelius     * with the JDK.
42959d709d503bab6e2b61931737e662dd293b40578ccornelius     */
43059d709d503bab6e2b61931737e662dd293b40578ccornelius    TimeZone* result = createSystemTimeZone(ID);
43159d709d503bab6e2b61931737e662dd293b40578ccornelius
4321b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    if (result == NULL) {
43359d709d503bab6e2b61931737e662dd293b40578ccornelius        U_DEBUG_TZ_MSG(("failed to load system time zone with id - falling to custom"));
43459d709d503bab6e2b61931737e662dd293b40578ccornelius        result = createCustomTimeZone(ID);
43559d709d503bab6e2b61931737e662dd293b40578ccornelius    }
4361b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    if (result == NULL) {
43759d709d503bab6e2b61931737e662dd293b40578ccornelius        U_DEBUG_TZ_MSG(("failed to load time zone with id - falling to Etc/Unknown(GMT)"));
4381b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        const TimeZone& unknown = getUnknown();
4391b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        if (_UNKNOWN_ZONE == NULL) {                   // Cannot test (&unknown == NULL) because the
4401b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          U_DEBUG_TZ_MSG(("failed to getUnknown()"));  // behavior of NULL references is undefined.
4411b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        } else {
4421b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          result = unknown.clone();
4431b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        }
44459d709d503bab6e2b61931737e662dd293b40578ccornelius    }
44559d709d503bab6e2b61931737e662dd293b40578ccornelius    return result;
44659d709d503bab6e2b61931737e662dd293b40578ccornelius}
44759d709d503bab6e2b61931737e662dd293b40578ccornelius
448b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
4501b7d32f919554dda9c193b32188251337bc756f1Fredrik RoubertTimeZone* U_EXPORT2
4511b7d32f919554dda9c193b32188251337bc756f1Fredrik RoubertTimeZone::detectHostTimeZone()
452b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho{
453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // We access system timezone data through TPlatformUtilities,
454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // including tzset(), timezone, and tzname[].
455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t rawOffset = 0;
456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *hostID;
457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // First, try to create a system timezone, based
459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // on the string ID in tzname[0].
460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
46159d709d503bab6e2b61931737e662dd293b40578ccornelius    uprv_tzset(); // Initialize tz... system data
462b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
46364339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert    uprv_tzname_clear_cache();
46464339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert
46559d709d503bab6e2b61931737e662dd293b40578ccornelius    // Get the timezone ID from the host.  This function should do
46659d709d503bab6e2b61931737e662dd293b40578ccornelius    // any required host-specific remapping; e.g., on Windows this
46759d709d503bab6e2b61931737e662dd293b40578ccornelius    // function maps the Date and Time control panel setting to an
46859d709d503bab6e2b61931737e662dd293b40578ccornelius    // ICU timezone ID.
46959d709d503bab6e2b61931737e662dd293b40578ccornelius    hostID = uprv_tzname(0);
470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
47159d709d503bab6e2b61931737e662dd293b40578ccornelius    // Invert sign because UNIX semantics are backwards
47259d709d503bab6e2b61931737e662dd293b40578ccornelius    rawOffset = uprv_timezone() * -U_MILLIS_PER_SECOND;
473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
4741b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    TimeZone* hostZone = NULL;
475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Make sure that the string is NULL terminated to prevent BoundsChecker/Purify warnings. */
477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString hostStrID(hostID, -1, US_INV);
478b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    hostStrID.append((UChar)0);
479b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    hostStrID.truncate(hostStrID.length()-1);
4801b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    hostZone = createSystemTimeZone(hostStrID);
481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
482103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if U_PLATFORM_USES_ONLY_WIN32_API
48350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    // hostID points to a heap-allocated location on Windows.
48450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    uprv_free(const_cast<char *>(hostID));
48550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif
48650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t hostIDLen = hostStrID.length();
4881b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    if (hostZone != NULL && rawOffset != hostZone->getRawOffset()
489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        && (3 <= hostIDLen && hostIDLen <= 4))
490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Uh oh. This probably wasn't a good id.
492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // It was probably an ambiguous abbreviation
4931b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        delete hostZone;
4941b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        hostZone = NULL;
495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Construct a fixed standard zone with the host's ID
498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // and raw offset.
4991b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    if (hostZone == NULL) {
5001b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        hostZone = new SimpleTimeZone(rawOffset, hostStrID);
501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // If we _still_ don't have a time zone, use GMT.
5041b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    //
5051b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    // Note: This is extremely unlikely situation. If
5061b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    // new SimpleTimeZone(...) above fails, the following
5071b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    // code may also fail.
5081b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    if (hostZone == NULL) {
50959d709d503bab6e2b61931737e662dd293b40578ccornelius        const TimeZone* temptz = TimeZone::getGMT();
510c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // If we can't use GMT, get out.
511c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (temptz == NULL) {
5121b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert            return NULL;
513c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
5141b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        hostZone = temptz->clone();
5151b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    }
5161b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
5171b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    return hostZone;
5181b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert}
5191b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
5201b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert// -------------------------------------
5211b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
5221b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert/**
5231b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert * Initialize DEFAULT_ZONE from the system default time zone.
5241b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert * Upon return, DEFAULT_ZONE will not be NULL, unless operator new()
5251b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert * returns NULL.
5261b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert */
5271b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubertstatic void U_CALLCONV initDefault()
5281b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert{
5291b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
5301b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
5311b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    // If setDefault() has already been called we can skip getting the
5321b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    // default zone information from the system.
5331b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    if (DEFAULT_ZONE != NULL) {
5341b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        return;
535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
5361b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
5371b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    // NOTE:  this code is safely single threaded, being only
5381b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    // run via umtx_initOnce().
5391b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    //
5401b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    // Some of the locale/timezone OS functions may not be thread safe,
5411b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    //
5421b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    // The operating system might actually use ICU to implement timezones.
5431b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    // So we may have ICU calling ICU here, like on AIX.
5441b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    // There shouldn't be a problem with this; initOnce does not hold a mutex
5451b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    // while the init function is being run.
5461b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
5471b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    // The code detecting the host time zone was separated from this
5481b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    // and implemented as TimeZone::detectHostTimeZone()
5491b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
5501b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    TimeZone *default_zone = TimeZone::detectHostTimeZone();
551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
55259d709d503bab6e2b61931737e662dd293b40578ccornelius    // The only way for DEFAULT_ZONE to be non-null at this point is if the user
55359d709d503bab6e2b61931737e662dd293b40578ccornelius    // made a thread-unsafe call to setDefault() or adoptDefault() in another
55459d709d503bab6e2b61931737e662dd293b40578ccornelius    // thread while this thread was doing something that required getting the default.
55559d709d503bab6e2b61931737e662dd293b40578ccornelius    U_ASSERT(DEFAULT_ZONE == NULL);
556b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
55759d709d503bab6e2b61931737e662dd293b40578ccornelius    DEFAULT_ZONE = default_zone;
558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone* U_EXPORT2
563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::createDefault()
564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
56559d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_initOnce(gDefaultZoneInitOnce, initDefault);
566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (DEFAULT_ZONE != NULL) ? DEFAULT_ZONE->clone() : NULL;
567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid U_EXPORT2
572b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::adoptDefault(TimeZone* zone)
573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (zone != NULL)
575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
57659d709d503bab6e2b61931737e662dd293b40578ccornelius        TimeZone *old = DEFAULT_ZONE;
577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        DEFAULT_ZONE = zone;
578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete old;
579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid U_EXPORT2
585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::setDefault(const TimeZone& zone)
586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    adoptDefault(zone.clone());
588b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
589b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
590b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//----------------------------------------------------------------------
591b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
59259d709d503bab6e2b61931737e662dd293b40578ccornelius
59359d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic void U_CALLCONV initMap(USystemTimeZoneType type, UErrorCode& ec) {
59459d709d503bab6e2b61931737e662dd293b40578ccornelius    ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
59559d709d503bab6e2b61931737e662dd293b40578ccornelius
59659d709d503bab6e2b61931737e662dd293b40578ccornelius    UResourceBundle *res = ures_openDirect(0, kZONEINFO, &ec);
59759d709d503bab6e2b61931737e662dd293b40578ccornelius    res = ures_getByKey(res, kNAMES, res, &ec); // dereference Zones section
59859d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_SUCCESS(ec)) {
59959d709d503bab6e2b61931737e662dd293b40578ccornelius        int32_t size = ures_getSize(res);
60059d709d503bab6e2b61931737e662dd293b40578ccornelius        int32_t *m = (int32_t *)uprv_malloc(size * sizeof(int32_t));
60159d709d503bab6e2b61931737e662dd293b40578ccornelius        if (m == NULL) {
60259d709d503bab6e2b61931737e662dd293b40578ccornelius            ec = U_MEMORY_ALLOCATION_ERROR;
60359d709d503bab6e2b61931737e662dd293b40578ccornelius        } else {
60459d709d503bab6e2b61931737e662dd293b40578ccornelius            int32_t numEntries = 0;
60559d709d503bab6e2b61931737e662dd293b40578ccornelius            for (int32_t i = 0; i < size; i++) {
60659d709d503bab6e2b61931737e662dd293b40578ccornelius                UnicodeString id = ures_getUnicodeStringByIndex(res, i, &ec);
60759d709d503bab6e2b61931737e662dd293b40578ccornelius                if (U_FAILURE(ec)) {
60859d709d503bab6e2b61931737e662dd293b40578ccornelius                    break;
60959d709d503bab6e2b61931737e662dd293b40578ccornelius                }
61059d709d503bab6e2b61931737e662dd293b40578ccornelius                if (0 == id.compare(UNKNOWN_ZONE_ID, UNKNOWN_ZONE_ID_LENGTH)) {
61159d709d503bab6e2b61931737e662dd293b40578ccornelius                    // exclude Etc/Unknown
61259d709d503bab6e2b61931737e662dd293b40578ccornelius                    continue;
61359d709d503bab6e2b61931737e662dd293b40578ccornelius                }
61459d709d503bab6e2b61931737e662dd293b40578ccornelius                if (type == UCAL_ZONE_TYPE_CANONICAL || type == UCAL_ZONE_TYPE_CANONICAL_LOCATION) {
61559d709d503bab6e2b61931737e662dd293b40578ccornelius                    UnicodeString canonicalID;
61659d709d503bab6e2b61931737e662dd293b40578ccornelius                    ZoneMeta::getCanonicalCLDRID(id, canonicalID, ec);
61759d709d503bab6e2b61931737e662dd293b40578ccornelius                    if (U_FAILURE(ec)) {
61859d709d503bab6e2b61931737e662dd293b40578ccornelius                        break;
61959d709d503bab6e2b61931737e662dd293b40578ccornelius                    }
62059d709d503bab6e2b61931737e662dd293b40578ccornelius                    if (canonicalID != id) {
62159d709d503bab6e2b61931737e662dd293b40578ccornelius                        // exclude aliases
62259d709d503bab6e2b61931737e662dd293b40578ccornelius                        continue;
62359d709d503bab6e2b61931737e662dd293b40578ccornelius                    }
62459d709d503bab6e2b61931737e662dd293b40578ccornelius                }
62559d709d503bab6e2b61931737e662dd293b40578ccornelius                if (type == UCAL_ZONE_TYPE_CANONICAL_LOCATION) {
62659d709d503bab6e2b61931737e662dd293b40578ccornelius                    const UChar *region = TimeZone::getRegion(id, ec);
62759d709d503bab6e2b61931737e662dd293b40578ccornelius                    if (U_FAILURE(ec)) {
62859d709d503bab6e2b61931737e662dd293b40578ccornelius                        break;
62959d709d503bab6e2b61931737e662dd293b40578ccornelius                    }
63059d709d503bab6e2b61931737e662dd293b40578ccornelius                    if (u_strcmp(region, WORLD) == 0) {
63159d709d503bab6e2b61931737e662dd293b40578ccornelius                       // exclude non-location ("001")
63259d709d503bab6e2b61931737e662dd293b40578ccornelius                        continue;
63359d709d503bab6e2b61931737e662dd293b40578ccornelius                    }
63459d709d503bab6e2b61931737e662dd293b40578ccornelius                }
63559d709d503bab6e2b61931737e662dd293b40578ccornelius                m[numEntries++] = i;
63659d709d503bab6e2b61931737e662dd293b40578ccornelius            }
63759d709d503bab6e2b61931737e662dd293b40578ccornelius            if (U_SUCCESS(ec)) {
63859d709d503bab6e2b61931737e662dd293b40578ccornelius                int32_t *tmp = m;
63959d709d503bab6e2b61931737e662dd293b40578ccornelius                m = (int32_t *)uprv_realloc(tmp, numEntries * sizeof(int32_t));
64059d709d503bab6e2b61931737e662dd293b40578ccornelius                if (m == NULL) {
64159d709d503bab6e2b61931737e662dd293b40578ccornelius                    // realloc failed.. use the original one even it has unused
64259d709d503bab6e2b61931737e662dd293b40578ccornelius                    // area at the end
64359d709d503bab6e2b61931737e662dd293b40578ccornelius                    m = tmp;
64459d709d503bab6e2b61931737e662dd293b40578ccornelius                }
64559d709d503bab6e2b61931737e662dd293b40578ccornelius
64659d709d503bab6e2b61931737e662dd293b40578ccornelius                switch(type) {
64759d709d503bab6e2b61931737e662dd293b40578ccornelius                case UCAL_ZONE_TYPE_ANY:
64859d709d503bab6e2b61931737e662dd293b40578ccornelius                    U_ASSERT(MAP_SYSTEM_ZONES == NULL);
64959d709d503bab6e2b61931737e662dd293b40578ccornelius                    MAP_SYSTEM_ZONES = m;
65059d709d503bab6e2b61931737e662dd293b40578ccornelius                    LEN_SYSTEM_ZONES = numEntries;
65159d709d503bab6e2b61931737e662dd293b40578ccornelius                    break;
65259d709d503bab6e2b61931737e662dd293b40578ccornelius                case UCAL_ZONE_TYPE_CANONICAL:
65359d709d503bab6e2b61931737e662dd293b40578ccornelius                    U_ASSERT(MAP_CANONICAL_SYSTEM_ZONES == NULL);
65459d709d503bab6e2b61931737e662dd293b40578ccornelius                    MAP_CANONICAL_SYSTEM_ZONES = m;
65559d709d503bab6e2b61931737e662dd293b40578ccornelius                    LEN_CANONICAL_SYSTEM_ZONES = numEntries;
65659d709d503bab6e2b61931737e662dd293b40578ccornelius                    break;
65759d709d503bab6e2b61931737e662dd293b40578ccornelius                case UCAL_ZONE_TYPE_CANONICAL_LOCATION:
65859d709d503bab6e2b61931737e662dd293b40578ccornelius                    U_ASSERT(MAP_CANONICAL_SYSTEM_LOCATION_ZONES == NULL);
65959d709d503bab6e2b61931737e662dd293b40578ccornelius                    MAP_CANONICAL_SYSTEM_LOCATION_ZONES = m;
66059d709d503bab6e2b61931737e662dd293b40578ccornelius                    LEN_CANONICAL_SYSTEM_LOCATION_ZONES = numEntries;
66159d709d503bab6e2b61931737e662dd293b40578ccornelius                    break;
66259d709d503bab6e2b61931737e662dd293b40578ccornelius                }
66359d709d503bab6e2b61931737e662dd293b40578ccornelius            }
66459d709d503bab6e2b61931737e662dd293b40578ccornelius        }
66559d709d503bab6e2b61931737e662dd293b40578ccornelius    }
66659d709d503bab6e2b61931737e662dd293b40578ccornelius    ures_close(res);
66759d709d503bab6e2b61931737e662dd293b40578ccornelius}
66859d709d503bab6e2b61931737e662dd293b40578ccornelius
66959d709d503bab6e2b61931737e662dd293b40578ccornelius
670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * This is the default implementation for subclasses that do not
672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * override this method.  This implementation calls through to the
673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * 8-argument getOffset() method after suitable computations, and
674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * correctly adjusts GMT millis to local millis when necessary.
675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid TimeZone::getOffset(UDate date, UBool local, int32_t& rawOffset,
677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         int32_t& dstOffset, UErrorCode& ec) const {
678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(ec)) {
679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    rawOffset = getRawOffset();
683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (!local) {
684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        date += rawOffset; // now in local standard millis
685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // When local == TRUE, date might not be in local standard
688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // millis.  getOffset taking 7 parameters used here assume
689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // the given time in day is local standard time.
690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // At STD->DST transition, there is a range of time which
691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // does not exist.  When 'date' is in this time range
692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // (and local == TRUE), this method interprets the specified
693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // local time as DST.  At DST->STD transition, there is a
694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // range of time which occurs twice.  In this case, this
695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // method interprets the specified local time as STD.
696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // To support the behavior above, we need to call getOffset
697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // (with 7 args) twice when local == true and DST is
698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // detected in the initial call.
699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (int32_t pass=0; ; ++pass) {
700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t year, month, dom, dow;
701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        double day = uprv_floor(date / U_MILLIS_PER_DAY);
702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t millis = (int32_t) (date - day * U_MILLIS_PER_DAY);
703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Grego::dayToFields(day, year, month, dom, dow);
705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        dstOffset = getOffset(GregorianCalendar::AD, year, month, dom,
707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                              (uint8_t) dow, millis,
708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                              Grego::monthLength(year, month),
709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                              ec) - rawOffset;
710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Recompute if local==TRUE, dstOffset!=0.
712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (pass!=0 || !local || dstOffset == 0) {
713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // adjust to local standard millis
716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        date -= dstOffset;
717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// New available IDs API as of ICU 2.4.  Uses StringEnumeration API.
723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass TZEnumeration : public StringEnumeration {
725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruprivate:
726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Map into to zones.  Our results are zone[map[i]] for
728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // i=0..len-1, where zone[i] is the i-th Olson zone.  If map==NULL
729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // then our results are zone[i] for i=0..len-1.  Len will be zero
730b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // if the zone data could not be loaded.
731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t* map;
732b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t* localMap;
733b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t  len;
734b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t  pos;
735b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
736b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TZEnumeration(int32_t* mapData, int32_t mapLen, UBool adoptMapData) : pos(0) {
737b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        map = mapData;
738b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        localMap = adoptMapData ? mapData : NULL;
739b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        len = mapLen;
740b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
741b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool getID(int32_t i) {
743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UErrorCode ec = U_ZERO_ERROR;
744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t idLen = 0;
745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const UChar* id = NULL;
746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UResourceBundle *top = ures_openDirect(0, kZONEINFO, &ec);
747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        top = ures_getByKey(top, kNAMES, top, &ec); // dereference Zones section
748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        id = ures_getStringByIndex(top, i, &idLen, &ec);
749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(U_FAILURE(ec)) {
750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            unistr.truncate(0);
751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else {
753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            unistr.fastCopyFrom(UnicodeString(TRUE, id, idLen));
754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
755b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ures_close(top);
756b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return U_SUCCESS(ec);
757b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
758b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
759b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    static int32_t* getMap(USystemTimeZoneType type, int32_t& len, UErrorCode& ec) {
760b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        len = 0;
761b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_FAILURE(ec)) {
762b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return NULL;
763b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
764b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t* m = NULL;
765b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        switch (type) {
766b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        case UCAL_ZONE_TYPE_ANY:
76759d709d503bab6e2b61931737e662dd293b40578ccornelius            umtx_initOnce(gSystemZonesInitOnce, &initMap, type, ec);
768b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            m = MAP_SYSTEM_ZONES;
769b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            len = LEN_SYSTEM_ZONES;
770b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
771b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        case UCAL_ZONE_TYPE_CANONICAL:
77259d709d503bab6e2b61931737e662dd293b40578ccornelius            umtx_initOnce(gCanonicalZonesInitOnce, &initMap, type, ec);
773b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            m = MAP_CANONICAL_SYSTEM_ZONES;
774b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            len = LEN_CANONICAL_SYSTEM_ZONES;
775b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
776b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        case UCAL_ZONE_TYPE_CANONICAL_LOCATION:
77759d709d503bab6e2b61931737e662dd293b40578ccornelius            umtx_initOnce(gCanonicalLocationZonesInitOnce, &initMap, type, ec);
778b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            m = MAP_CANONICAL_SYSTEM_LOCATION_ZONES;
779b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            len = LEN_CANONICAL_SYSTEM_LOCATION_ZONES;
780b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
78159d709d503bab6e2b61931737e662dd293b40578ccornelius        default:
78259d709d503bab6e2b61931737e662dd293b40578ccornelius            ec = U_ILLEGAL_ARGUMENT_ERROR;
78359d709d503bab6e2b61931737e662dd293b40578ccornelius            m = NULL;
78459d709d503bab6e2b61931737e662dd293b40578ccornelius            len = 0;
78559d709d503bab6e2b61931737e662dd293b40578ccornelius            break;
786b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
787b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return m;
788b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
789b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
790b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehopublic:
791b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
792b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#define DEFAULT_FILTERED_MAP_SIZE 8
793b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#define MAP_INCREMENT_SIZE 8
794b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
795b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    static TZEnumeration* create(USystemTimeZoneType type, const char* region, const int32_t* rawOffset, UErrorCode& ec) {
796b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_FAILURE(ec)) {
797b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return NULL;
798b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
799b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
800b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t baseLen;
801b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t *baseMap = getMap(type, baseLen, ec);
802b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
803b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_FAILURE(ec)) {
804b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return NULL;
805b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
806b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
807b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // If any additional conditions are available,
808b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // create instance local map filtered by the conditions.
809b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
810b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t *filteredMap = NULL;
811b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t numEntries = 0;
812b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
813b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (region != NULL || rawOffset != NULL) {
814b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            int32_t filteredMapSize = DEFAULT_FILTERED_MAP_SIZE;
815b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            filteredMap = (int32_t *)uprv_malloc(filteredMapSize * sizeof(int32_t));
816b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (filteredMap == NULL) {
817b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                ec = U_MEMORY_ALLOCATION_ERROR;
818b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return NULL;
81950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            }
82050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
821b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Walk through the base map
822b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            UResourceBundle *res = ures_openDirect(0, kZONEINFO, &ec);
823b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            res = ures_getByKey(res, kNAMES, res, &ec); // dereference Zones section
824b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            for (int32_t i = 0; i < baseLen; i++) {
825b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                int32_t zidx = baseMap[i];
826103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                UnicodeString id = ures_getUnicodeStringByIndex(res, zidx, &ec);
82750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                if (U_FAILURE(ec)) {
82850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    break;
82950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                }
830b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (region != NULL) {
831b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    // Filter by region
832b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    char tzregion[4]; // max 3 letters + null term
833b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    TimeZone::getRegion(id, tzregion, sizeof(tzregion), ec);
834b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (U_FAILURE(ec)) {
835b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        break;
836b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    }
837b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (uprv_stricmp(tzregion, region) != 0) {
838b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        // region does not match
839b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        continue;
840b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    }
84150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                }
842b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (rawOffset != NULL) {
843b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    // Filter by raw offset
844b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    // Note: This is VERY inefficient
84559d709d503bab6e2b61931737e662dd293b40578ccornelius                    TimeZone *z = createSystemTimeZone(id, ec);
846b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (U_FAILURE(ec)) {
847b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        break;
848b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    }
849b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    int32_t tzoffset = z->getRawOffset();
850b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    delete z;
85150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
852b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (tzoffset != *rawOffset) {
853b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        continue;
85450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    }
855b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
856b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
857b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (filteredMapSize <= numEntries) {
858b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    filteredMapSize += MAP_INCREMENT_SIZE;
859b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    int32_t *tmp = (int32_t *)uprv_realloc(filteredMap, filteredMapSize * sizeof(int32_t));
860b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (tmp == NULL) {
861b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        ec = U_MEMORY_ALLOCATION_ERROR;
862b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        break;
86350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    } else {
864b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        filteredMap = tmp;
865b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
866b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
867b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
868b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                filteredMap[numEntries++] = zidx;
869b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
870b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
871b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (U_FAILURE(ec)) {
872b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                uprv_free(filteredMap);
873b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                filteredMap = NULL;
874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
875b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
876b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            ures_close(res);
877b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
878b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
879b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        TZEnumeration *result = NULL;
880b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_SUCCESS(ec)) {
881b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Finally, create a new enumeration instance
882b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (filteredMap == NULL) {
883b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                result = new TZEnumeration(baseMap, baseLen, FALSE);
884b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
885b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                result = new TZEnumeration(filteredMap, numEntries, TRUE);
886b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                filteredMap = NULL;
887b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
888b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (result == NULL) {
889b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                ec = U_MEMORY_ALLOCATION_ERROR;
890b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
891b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
892b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
893b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (filteredMap != NULL) {
894b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            uprv_free(filteredMap);
895b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
896b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
897b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return result;
898b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
899b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
900b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TZEnumeration(const TZEnumeration &other) : StringEnumeration(), map(NULL), localMap(NULL), len(0), pos(0) {
901b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (other.localMap != NULL) {
902b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            localMap = (int32_t *)uprv_malloc(other.len * sizeof(int32_t));
903b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (localMap != NULL) {
904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                len = other.len;
905b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                uprv_memcpy(localMap, other.localMap, len * sizeof(int32_t));
906b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pos = other.pos;
907b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                map = localMap;
908b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else {
909b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                len = 0;
910b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                pos = 0;
911b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                map = NULL;
912b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
913b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else {
914b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            map = other.map;
915b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            localMap = NULL;
916b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            len = other.len;
917b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            pos = other.pos;
918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
921103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    virtual ~TZEnumeration();
922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    virtual StringEnumeration *clone() const {
924b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return new TZEnumeration(*this);
925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
926b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    virtual int32_t count(UErrorCode& status) const {
928b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return U_FAILURE(status) ? 0 : len;
929b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    virtual const UnicodeString* snext(UErrorCode& status) {
932b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_SUCCESS(status) && map != NULL && pos < len) {
933b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            getID(map[pos]);
934b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ++pos;
935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return &unistr;
936b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
939b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    virtual void reset(UErrorCode& /*status*/) {
941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pos = 0;
942b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
944b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querupublic:
945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    static UClassID U_EXPORT2 getStaticClassID(void);
946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    virtual UClassID getDynamicClassID(void) const;
947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
948b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
949103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTZEnumeration::~TZEnumeration() {
950103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (localMap != NULL) {
951103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        uprv_free(localMap);
952103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    }
953103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
954103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
955b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUOBJECT_DEFINE_RTTI_IMPLEMENTATION(TZEnumeration)
956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruStringEnumeration* U_EXPORT2
958b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZone::createTimeZoneIDEnumeration(
959b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            USystemTimeZoneType zoneType,
960b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            const char* region,
961b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            const int32_t* rawOffset,
962b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            UErrorCode& ec) {
963b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return TZEnumeration::create(zoneType, region, rawOffset, ec);
964b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
965b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
966b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoStringEnumeration* U_EXPORT2
967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::createEnumeration() {
968b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode ec = U_ZERO_ERROR;
969b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return TZEnumeration::create(UCAL_ZONE_TYPE_ANY, NULL, NULL, ec);
970b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
971b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
972b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruStringEnumeration* U_EXPORT2
973b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::createEnumeration(int32_t rawOffset) {
974b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode ec = U_ZERO_ERROR;
975b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return TZEnumeration::create(UCAL_ZONE_TYPE_ANY, NULL, &rawOffset, ec);
976b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
977b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
978b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruStringEnumeration* U_EXPORT2
979b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::createEnumeration(const char* country) {
980b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode ec = U_ZERO_ERROR;
981b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return TZEnumeration::create(UCAL_ZONE_TYPE_ANY, country, NULL, ec);
982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
983b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ---------------------------------------
985b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
986b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t U_EXPORT2
987b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::countEquivalentIDs(const UnicodeString& id) {
988b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t result = 0;
989b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode ec = U_ZERO_ERROR;
990b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UResourceBundle res;
991b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_initStackObject(&res);
992b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_DEBUG_TZ_MSG(("countEquivalentIDs..\n"));
993b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UResourceBundle *top = openOlsonResource(id, res, ec);
994b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_SUCCESS(ec)) {
99550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        UResourceBundle r;
99650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        ures_initStackObject(&r);
99750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        ures_getByKey(&res, kLINKS, &r, &ec);
99850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        ures_getIntVector(&r, &result, &ec);
99950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        ures_close(&r);
1000b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1001b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_close(&res);
1002b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_close(top);
1003b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
1004b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1005b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1006b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ---------------------------------------
1007b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1008b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst UnicodeString U_EXPORT2
1009b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::getEquivalentID(const UnicodeString& id, int32_t index) {
1010b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_DEBUG_TZ_MSG(("gEI(%d)\n", index));
1011b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString result;
1012b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode ec = U_ZERO_ERROR;
1013b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UResourceBundle res;
1014b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_initStackObject(&res);
1015b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UResourceBundle *top = openOlsonResource(id, res, ec);
1016b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t zone = -1;
1017b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_SUCCESS(ec)) {
101850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        UResourceBundle r;
101950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        ures_initStackObject(&r);
102050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        int32_t size;
102150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        ures_getByKey(&res, kLINKS, &r, &ec);
102250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        const int32_t* v = ures_getIntVector(&r, &size, &ec);
102350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if (U_SUCCESS(ec)) {
1024b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (index >= 0 && index < size) {
1025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                zone = v[index];
1026b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1027b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
102850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        ures_close(&r);
1029b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1030b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_close(&res);
1031b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (zone >= 0) {
1032b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UResourceBundle *ares = ures_getByKey(top, kNAMES, NULL, &ec); // dereference Zones section
1033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_SUCCESS(ec)) {
1034b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t idLen = 0;
1035b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            const UChar* id = ures_getStringByIndex(ares, zone, &idLen, &ec);
1036b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            result.fastCopyFrom(UnicodeString(TRUE, id, idLen));
1037b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            U_DEBUG_TZ_MSG(("gei(%d) -> %d, len%d, %s\n", index, zone, result.length(), u_errorName(ec)));
1038b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1039b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ures_close(ares);
1040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_close(top);
1042b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined(U_DEBUG_TZ)
1043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(result.length() ==0) {
1044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      U_DEBUG_TZ_MSG(("equiv [__, #%d] -> 0 (%s)\n", index, u_errorName(ec)));
1045b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1046b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
1047b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
1048b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1049b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1050b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ---------------------------------------
1051b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1052b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// These methods are used by ZoneMeta class only.
1053b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1054b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UChar*
1055b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZone::findID(const UnicodeString& id) {
1056b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar *result = NULL;
1057b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode ec = U_ZERO_ERROR;
1058b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UResourceBundle *rb = ures_openDirect(NULL, kZONEINFO, &ec);
1059b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1060b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // resolve zone index by name
1061b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UResourceBundle *names = ures_getByKey(rb, kNAMES, NULL, &ec);
1062b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t idx = findInStringArray(names, id, ec);
1063b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    result = ures_getStringByIndex(names, idx, NULL, &ec);
1064b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(ec)) {
1065b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        result = NULL;
1066b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1067b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ures_close(names);
1068b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ures_close(rb);
1069b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return result;
1070b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1071b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
107250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
107350294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoconst UChar*
107450294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoTimeZone::dereferOlsonLink(const UnicodeString& id) {
107550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    const UChar *result = NULL;
1076b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode ec = U_ZERO_ERROR;
107750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    UResourceBundle *rb = ures_openDirect(NULL, kZONEINFO, &ec);
107850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
107950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    // resolve zone index by name
108050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    UResourceBundle *names = ures_getByKey(rb, kNAMES, NULL, &ec);
108150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t idx = findInStringArray(names, id, ec);
108250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    result = ures_getStringByIndex(names, idx, NULL, &ec);
108350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
108450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    // open the zone bundle by index
108550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    ures_getByKey(rb, kZONES, rb, &ec);
108650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    ures_getByIndex(rb, idx, rb, &ec);
108750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
1088b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_SUCCESS(ec)) {
108950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if (ures_getType(rb) == URES_INT) {
109050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            // this is a link - dereference the link
109150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            int32_t deref = ures_getInt(rb, &ec);
109250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            const UChar* tmp = ures_getStringByIndex(names, deref, NULL, &ec);
1093b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (U_SUCCESS(ec)) {
109450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                result = tmp;
1095b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1096b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1097b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
109850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
109950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    ures_close(names);
110050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    ures_close(rb);
110150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
110250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    return result;
110350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
110450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
110550294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoconst UChar*
110650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoTimeZone::getRegion(const UnicodeString& id) {
1107b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode status = U_ZERO_ERROR;
1108b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return getRegion(id, status);
1109b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1110b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1111b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UChar*
1112b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZone::getRegion(const UnicodeString& id, UErrorCode& status) {
1113b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
1114b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
1115b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1116b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar *result = NULL;
1117b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UResourceBundle *rb = ures_openDirect(NULL, kZONEINFO, &status);
111850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
111950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    // resolve zone index by name
1120b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UResourceBundle *res = ures_getByKey(rb, kNAMES, NULL, &status);
1121b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t idx = findInStringArray(res, id, status);
112250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
112350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    // get region mapping
1124b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ures_getByKey(rb, kREGIONS, res, &status);
1125b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar *tmp = ures_getStringByIndex(res, idx, NULL, &status);
1126b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_SUCCESS(status)) {
112750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        result = tmp;
112850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
112950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
1130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_close(res);
113150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    ures_close(rb);
113250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
113350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    return result;
1134b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1136b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1137b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------
1138b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoint32_t
1139b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZone::getRegion(const UnicodeString& id, char *region, int32_t capacity, UErrorCode& status)
1140b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho{
1141b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t resultLen = 0;
1142b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    *region = 0;
1143b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
1144b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return 0;
1145b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1146b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1147b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar *uregion = NULL;
1148b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // "Etc/Unknown" is not a system zone ID,
1149b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // but in the zone data
1150b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (id.compare(UNKNOWN_ZONE_ID, UNKNOWN_ZONE_ID_LENGTH) != 0) {
1151b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        uregion = getRegion(id);
1152b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1153b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (uregion == NULL) {
1154b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        status = U_ILLEGAL_ARGUMENT_ERROR;
1155b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return 0;
1156b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1157b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    resultLen = u_strlen(uregion);
1158b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // A region code is represented by invariant characters
1159b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    u_UCharsToChars(uregion, region, uprv_min(resultLen, capacity));
1160b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1161b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (capacity < resultLen) {
1162b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        status = U_BUFFER_OVERFLOW_ERROR;
1163b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return resultLen;
1164b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1165b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1166b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return u_terminateChars(region, capacity, resultLen, &status);
1167b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1168b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ---------------------------------------
1170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString&
1173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::getDisplayName(UnicodeString& result) const
1174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return getDisplayName(FALSE,LONG,Locale::getDefault(), result);
1176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString&
1179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::getDisplayName(const Locale& locale, UnicodeString& result) const
1180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return getDisplayName(FALSE, LONG, locale, result);
1182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString&
1185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::getDisplayName(UBool daylight, EDisplayType style, UnicodeString& result)  const
1186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return getDisplayName(daylight,style, Locale::getDefault(), result);
1188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//--------------------------------------
1190b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoint32_t
1191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::getDSTSavings()const {
1192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (useDaylightTime()) {
1193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 3600000;
1194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return 0;
1196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//---------------------------------------
1198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString&
1199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::getDisplayName(UBool daylight, EDisplayType style, const Locale& locale, UnicodeString& result) const
1200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
1202103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    UDate date = Calendar::getNow();
1203103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    UTimeZoneFormatTimeType timeType;
1204103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    int32_t offset;
1205b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1206103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (style == GENERIC_LOCATION || style == LONG_GENERIC || style == SHORT_GENERIC) {
1207103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        LocalPointer<TimeZoneFormat> tzfmt(TimeZoneFormat::createInstance(locale, status));
1208c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (U_FAILURE(status)) {
1209103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            result.remove();
1210103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            return result;
1211c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1212103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        // Generic format
1213103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        switch (style) {
1214103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        case GENERIC_LOCATION:
1215103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            tzfmt->format(UTZFMT_STYLE_GENERIC_LOCATION, *this, date, result, &timeType);
1216103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            break;
1217103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        case LONG_GENERIC:
1218103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            tzfmt->format(UTZFMT_STYLE_GENERIC_LONG, *this, date, result, &timeType);
1219103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            break;
1220103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        case SHORT_GENERIC:
1221103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            tzfmt->format(UTZFMT_STYLE_GENERIC_SHORT, *this, date, result, &timeType);
1222103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            break;
1223103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        default:
1224103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            U_ASSERT(FALSE);
1225103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        }
1226103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        // Generic format many use Localized GMT as the final fallback.
1227103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        // When Localized GMT format is used, the result might not be
1228103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        // appropriate for the requested daylight value.
1229103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        if ((daylight && timeType == UTZFMT_TIME_TYPE_STANDARD) || (!daylight && timeType == UTZFMT_TIME_TYPE_DAYLIGHT)) {
1230103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            offset = daylight ? getRawOffset() + getDSTSavings() : getRawOffset();
12318393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            if (style == SHORT_GENERIC) {
12328393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                tzfmt->formatOffsetShortLocalizedGMT(offset, result, status);
12338393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            } else {
12348393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                tzfmt->formatOffsetLocalizedGMT(offset, result, status);
12358393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            }
1236c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1237103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    } else if (style == LONG_GMT || style == SHORT_GMT) {
1238103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        LocalPointer<TimeZoneFormat> tzfmt(TimeZoneFormat::createInstance(locale, status));
1239103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        if (U_FAILURE(status)) {
1240103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            result.remove();
1241103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            return result;
1242103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        }
1243103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        offset = daylight && useDaylightTime() ? getRawOffset() + getDSTSavings() : getRawOffset();
1244103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        switch (style) {
1245103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        case LONG_GMT:
1246103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            tzfmt->formatOffsetLocalizedGMT(offset, result, status);
1247103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            break;
1248103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        case SHORT_GMT:
12498393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            tzfmt->formatOffsetISO8601Basic(offset, FALSE, FALSE, FALSE, result, status);
1250103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            break;
1251103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        default:
1252103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            U_ASSERT(FALSE);
1253103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        }
1254103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
1255c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else {
1256103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        U_ASSERT(style == LONG || style == SHORT || style == SHORT_COMMONLY_USED);
1257103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        UTimeZoneNameType nameType = UTZNM_UNKNOWN;
1258103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        switch (style) {
1259103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        case LONG:
1260103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            nameType = daylight ? UTZNM_LONG_DAYLIGHT : UTZNM_LONG_STANDARD;
1261103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            break;
1262103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        case SHORT:
1263103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        case SHORT_COMMONLY_USED:
1264103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            nameType = daylight ? UTZNM_SHORT_DAYLIGHT : UTZNM_SHORT_STANDARD;
1265103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            break;
1266103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        default:
1267103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            U_ASSERT(FALSE);
1268103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        }
1269103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        LocalPointer<TimeZoneNames> tznames(TimeZoneNames::createInstance(locale, status));
1270103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        if (U_FAILURE(status)) {
1271103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            result.remove();
1272103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            return result;
1273103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        }
1274103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        UnicodeString canonicalID(ZoneMeta::getCanonicalCLDRID(*this));
1275103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        tznames->getDisplayName(canonicalID, nameType, date, result);
1276103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        if (result.isEmpty()) {
1277103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            // Fallback to localized GMT
1278103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            LocalPointer<TimeZoneFormat> tzfmt(TimeZoneFormat::createInstance(locale, status));
1279103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            offset = daylight && useDaylightTime() ? getRawOffset() + getDSTSavings() : getRawOffset();
12808393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            if (style == LONG) {
12818393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                tzfmt->formatOffsetLocalizedGMT(offset, result, status);
12828393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            } else {
12838393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                tzfmt->formatOffsetShortLocalizedGMT(offset, result, status);
12848393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            }
1285c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1286c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1287103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (U_FAILURE(status)) {
1288103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        result.remove();
1289103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    }
1290c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return  result;
1291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
1294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Parse a custom time zone identifier and return a corresponding zone.
1295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param id a string of the form GMT[+-]hh:mm, GMT[+-]hhmm, or
1296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * GMT[+-]hh.
1297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @return a newly created SimpleTimeZone with the given offset and
1298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * no Daylight Savings Time, or null if the id cannot be parsed.
1299b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
1300b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone*
1301b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::createCustomTimeZone(const UnicodeString& id)
1302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1303c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t sign, hour, min, sec;
1304c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (parseCustomID(id, sign, hour, min, sec)) {
1305c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UnicodeString customID;
1306c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        formatCustomID(hour, min, sec, (sign < 0), customID);
1307c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        int32_t offset = sign * ((hour * 60 + min) * 60 + sec) * 1000;
1308c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return new SimpleTimeZone(offset, customID);
1309c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1310c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return NULL;
1311c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1312c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1313c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruUnicodeString&
1314c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruTimeZone::getCustomID(const UnicodeString& id, UnicodeString& normalized, UErrorCode& status) {
1315c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    normalized.remove();
1316c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (U_FAILURE(status)) {
1317c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return normalized;
1318c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1319c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t sign, hour, min, sec;
1320c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (parseCustomID(id, sign, hour, min, sec)) {
1321c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        formatCustomID(hour, min, sec, (sign < 0), normalized);
1322fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    } else {
1323fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        status = U_ILLEGAL_ARGUMENT_ERROR;
1324c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1325c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return normalized;
1326c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1327c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1328c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruUBool
1329c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruTimeZone::parseCustomID(const UnicodeString& id, int32_t& sign,
1330c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                        int32_t& hour, int32_t& min, int32_t& sec) {
1331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    static const int32_t         kParseFailed = -99999;
1332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    NumberFormat* numberFormat = 0;
1334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString idUppercase = id;
1335103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    idUppercase.toUpper("");
1336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (id.length() > GMT_ID_LENGTH &&
1338103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        idUppercase.startsWith(GMT_ID, GMT_ID_LENGTH))
1339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ParsePosition pos(GMT_ID_LENGTH);
1341c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        sign = 1;
1342c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        hour = 0;
1343c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        min = 0;
1344c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        sec = 0;
1345c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1346c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (id[pos.getIndex()] == MINUS /*'-'*/) {
1347c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            sign = -1;
1348c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        } else if (id[pos.getIndex()] != PLUS /*'+'*/) {
1349c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return FALSE;
1350c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pos.setIndex(pos.getIndex() + 1);
1352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UErrorCode success = U_ZERO_ERROR;
1354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        numberFormat = NumberFormat::createInstance(success);
1355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(U_FAILURE(success)){
1356c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return FALSE;
1357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        numberFormat->setParseIntegerOnly(TRUE);
1359b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        //numberFormat->setLenient(TRUE); // TODO: May need to set this, depends on latest timezone parsing
1360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Look for either hh:mm, hhmm, or hh
1362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t start = pos.getIndex();
1363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Formattable n(kParseFailed);
1364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        numberFormat->parse(id, n, pos);
1365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (pos.getIndex() == start) {
1366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            delete numberFormat;
1367c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return FALSE;
1368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        hour = n.getLong();
1370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (pos.getIndex() < id.length()) {
1372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (pos.getIndex() - start > 2
1373b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                || id[pos.getIndex()] != COLON) {
1374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                delete numberFormat;
1375c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                return FALSE;
1376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // hh:mm
1378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            pos.setIndex(pos.getIndex() + 1);
1379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t oldPos = pos.getIndex();
1380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            n.setLong(kParseFailed);
1381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            numberFormat->parse(id, n, pos);
1382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if ((pos.getIndex() - oldPos) != 2) {
1383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // must be 2 digits
1384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                delete numberFormat;
1385c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                return FALSE;
1386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            min = n.getLong();
1388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (pos.getIndex() < id.length()) {
1389b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                if (id[pos.getIndex()] != COLON) {
1390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    delete numberFormat;
1391c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                    return FALSE;
1392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // [:ss]
1394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pos.setIndex(pos.getIndex() + 1);
1395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                oldPos = pos.getIndex();
1396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                n.setLong(kParseFailed);
1397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                numberFormat->parse(id, n, pos);
1398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (pos.getIndex() != id.length()
1399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        || (pos.getIndex() - oldPos) != 2) {
1400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    delete numberFormat;
1401c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                    return FALSE;
1402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                sec = n.getLong();
1404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
1406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Supported formats are below -
1407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            //
1408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // HHmmss
1409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Hmmss
1410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // HHmm
1411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Hmm
1412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // HH
1413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // H
1414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t length = pos.getIndex() - start;
1416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (length <= 0 || 6 < length) {
1417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // invalid length
1418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                delete numberFormat;
1419c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                return FALSE;
1420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            switch (length) {
1422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                case 1:
1423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                case 2:
1424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // already set to hour
1425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    break;
1426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                case 3:
1427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                case 4:
1428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    min = hour % 100;
1429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    hour /= 100;
1430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    break;
1431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                case 5:
1432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                case 6:
1433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    sec = hour % 100;
1434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    min = (hour/100) % 100;
1435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    hour /= 10000;
1436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    break;
1437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1439b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete numberFormat;
1441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (hour > kMAX_CUSTOM_HOUR || min > kMAX_CUSTOM_MIN || sec > kMAX_CUSTOM_SEC) {
1443c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return FALSE;
1444b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1445c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return TRUE;
1446c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1447c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return FALSE;
1448c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1450c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruUnicodeString&
1451c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruTimeZone::formatCustomID(int32_t hour, int32_t min, int32_t sec,
1452c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                         UBool negative, UnicodeString& id) {
1453c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // Create time zone ID - GMT[+|-]hhmm[ss]
1454103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    id.setTo(GMT_ID, GMT_ID_LENGTH);
1455c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (hour | min | sec) {
1456c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (negative) {
1457c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            id += (UChar)MINUS;
1458c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        } else {
1459c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            id += (UChar)PLUS;
1460c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1462c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (hour < 10) {
1463c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            id += (UChar)ZERO_DIGIT;
1464c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        } else {
1465c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            id += (UChar)(ZERO_DIGIT + hour/10);
1466c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1467c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        id += (UChar)(ZERO_DIGIT + hour%10);
1468b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        id += (UChar)COLON;
1469c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (min < 10) {
1470c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            id += (UChar)ZERO_DIGIT;
1471c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        } else {
1472c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            id += (UChar)(ZERO_DIGIT + min/10);
1473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1474c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        id += (UChar)(ZERO_DIGIT + min%10);
1475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1476c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (sec) {
1477b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            id += (UChar)COLON;
1478c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            if (sec < 10) {
1479c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                id += (UChar)ZERO_DIGIT;
1480c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            } else {
1481c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                id += (UChar)(ZERO_DIGIT + sec/10);
1482c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
1483c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            id += (UChar)(ZERO_DIGIT + sec%10);
1484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1486c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return id;
1487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1490b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUBool
1491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::hasSameRules(const TimeZone& other) const
1492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1493b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return (getRawOffset() == other.getRawOffset() &&
1494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            useDaylightTime() == other.useDaylightTime());
1495b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1496b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
149759d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic void U_CALLCONV initTZDataVersion(UErrorCode &status) {
149859d709d503bab6e2b61931737e662dd293b40578ccornelius    ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
149959d709d503bab6e2b61931737e662dd293b40578ccornelius    int32_t len = 0;
150059d709d503bab6e2b61931737e662dd293b40578ccornelius    UResourceBundle *bundle = ures_openDirect(NULL, kZONEINFO, &status);
150159d709d503bab6e2b61931737e662dd293b40578ccornelius    const UChar *tzver = ures_getStringByKey(bundle, kTZVERSION, &len, &status);
1502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
150359d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_SUCCESS(status)) {
150459d709d503bab6e2b61931737e662dd293b40578ccornelius        if (len >= (int32_t)sizeof(TZDATA_VERSION)) {
150559d709d503bab6e2b61931737e662dd293b40578ccornelius            // Ensure that there is always space for a trailing nul in TZDATA_VERSION
150659d709d503bab6e2b61931737e662dd293b40578ccornelius            len = sizeof(TZDATA_VERSION) - 1;
1507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
150859d709d503bab6e2b61931737e662dd293b40578ccornelius        u_UCharsToChars(tzver, TZDATA_VERSION, len);
1509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
151059d709d503bab6e2b61931737e662dd293b40578ccornelius    ures_close(bundle);
151159d709d503bab6e2b61931737e662dd293b40578ccornelius
151259d709d503bab6e2b61931737e662dd293b40578ccornelius}
151359d709d503bab6e2b61931737e662dd293b40578ccornelius
151459d709d503bab6e2b61931737e662dd293b40578ccorneliusconst char*
151559d709d503bab6e2b61931737e662dd293b40578ccorneliusTimeZone::getTZDataVersion(UErrorCode& status)
151659d709d503bab6e2b61931737e662dd293b40578ccornelius{
151759d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_initOnce(gTZDataVersionInitOnce, &initTZDataVersion, status);
1518b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (const char*)TZDATA_VERSION;
1519b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1520b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1521c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruUnicodeString&
1522c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruTimeZone::getCanonicalID(const UnicodeString& id, UnicodeString& canonicalID, UErrorCode& status)
1523c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru{
1524c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UBool isSystemID = FALSE;
1525c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return getCanonicalID(id, canonicalID, isSystemID, status);
1526c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1527c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1528c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruUnicodeString&
1529c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruTimeZone::getCanonicalID(const UnicodeString& id, UnicodeString& canonicalID, UBool& isSystemID,
1530c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                         UErrorCode& status)
1531c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru{
1532c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    canonicalID.remove();
1533c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    isSystemID = FALSE;
1534c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (U_FAILURE(status)) {
1535c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return canonicalID;
1536c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1537b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (id.compare(UNKNOWN_ZONE_ID, UNKNOWN_ZONE_ID_LENGTH) == 0) {
1538b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // special case - Etc/Unknown is a canonical ID, but not system ID
1539b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        canonicalID.fastCopyFrom(id);
1540b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        isSystemID = FALSE;
1541c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else {
1542b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ZoneMeta::getCanonicalCLDRID(id, canonicalID, status);
1543b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_SUCCESS(status)) {
1544b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            isSystemID = TRUE;
1545b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else {
1546b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Not a system ID
1547b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            status = U_ZERO_ERROR;
1548b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            getCustomID(id, canonicalID, status);
1549b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1550c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1551c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return canonicalID;
1552c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1553c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
155459d709d503bab6e2b61931737e662dd293b40578ccorneliusUnicodeString&
155559d709d503bab6e2b61931737e662dd293b40578ccorneliusTimeZone::getWindowsID(const UnicodeString& id, UnicodeString& winid, UErrorCode& status) {
155659d709d503bab6e2b61931737e662dd293b40578ccornelius    winid.remove();
155759d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_FAILURE(status)) {
155859d709d503bab6e2b61931737e662dd293b40578ccornelius        return winid;
155959d709d503bab6e2b61931737e662dd293b40578ccornelius    }
156059d709d503bab6e2b61931737e662dd293b40578ccornelius
156159d709d503bab6e2b61931737e662dd293b40578ccornelius    // canonicalize the input ID
156259d709d503bab6e2b61931737e662dd293b40578ccornelius    UnicodeString canonicalID;
156359d709d503bab6e2b61931737e662dd293b40578ccornelius    UBool isSystemID = FALSE;
156459d709d503bab6e2b61931737e662dd293b40578ccornelius
156559d709d503bab6e2b61931737e662dd293b40578ccornelius    getCanonicalID(id, canonicalID, isSystemID, status);
156659d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_FAILURE(status) || !isSystemID) {
156759d709d503bab6e2b61931737e662dd293b40578ccornelius        // mapping data is only applicable to tz database IDs
1568fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if (status == U_ILLEGAL_ARGUMENT_ERROR) {
1569fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // getWindowsID() sets an empty string where
1570fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // getCanonicalID() sets a U_ILLEGAL_ARGUMENT_ERROR.
1571fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            status = U_ZERO_ERROR;
1572fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
157359d709d503bab6e2b61931737e662dd293b40578ccornelius        return winid;
157459d709d503bab6e2b61931737e662dd293b40578ccornelius    }
157559d709d503bab6e2b61931737e662dd293b40578ccornelius
157659d709d503bab6e2b61931737e662dd293b40578ccornelius    UResourceBundle *mapTimezones = ures_openDirect(NULL, "windowsZones", &status);
157759d709d503bab6e2b61931737e662dd293b40578ccornelius    ures_getByKey(mapTimezones, "mapTimezones", mapTimezones, &status);
157859d709d503bab6e2b61931737e662dd293b40578ccornelius
157959d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_FAILURE(status)) {
158059d709d503bab6e2b61931737e662dd293b40578ccornelius        return winid;
158159d709d503bab6e2b61931737e662dd293b40578ccornelius    }
158259d709d503bab6e2b61931737e662dd293b40578ccornelius
158359d709d503bab6e2b61931737e662dd293b40578ccornelius    UResourceBundle *winzone = NULL;
158459d709d503bab6e2b61931737e662dd293b40578ccornelius    UBool found = FALSE;
158559d709d503bab6e2b61931737e662dd293b40578ccornelius    while (ures_hasNext(mapTimezones) && !found) {
158659d709d503bab6e2b61931737e662dd293b40578ccornelius        winzone = ures_getNextResource(mapTimezones, winzone, &status);
158759d709d503bab6e2b61931737e662dd293b40578ccornelius        if (U_FAILURE(status)) {
158859d709d503bab6e2b61931737e662dd293b40578ccornelius            break;
158959d709d503bab6e2b61931737e662dd293b40578ccornelius        }
159059d709d503bab6e2b61931737e662dd293b40578ccornelius        if (ures_getType(winzone) != URES_TABLE) {
159159d709d503bab6e2b61931737e662dd293b40578ccornelius            continue;
159259d709d503bab6e2b61931737e662dd293b40578ccornelius        }
159359d709d503bab6e2b61931737e662dd293b40578ccornelius        UResourceBundle *regionalData = NULL;
159459d709d503bab6e2b61931737e662dd293b40578ccornelius        while (ures_hasNext(winzone) && !found) {
159559d709d503bab6e2b61931737e662dd293b40578ccornelius            regionalData = ures_getNextResource(winzone, regionalData, &status);
159659d709d503bab6e2b61931737e662dd293b40578ccornelius            if (U_FAILURE(status)) {
159759d709d503bab6e2b61931737e662dd293b40578ccornelius                break;
159859d709d503bab6e2b61931737e662dd293b40578ccornelius            }
159959d709d503bab6e2b61931737e662dd293b40578ccornelius            if (ures_getType(regionalData) != URES_STRING) {
160059d709d503bab6e2b61931737e662dd293b40578ccornelius                continue;
160159d709d503bab6e2b61931737e662dd293b40578ccornelius            }
160259d709d503bab6e2b61931737e662dd293b40578ccornelius            int32_t len;
160359d709d503bab6e2b61931737e662dd293b40578ccornelius            const UChar *tzids = ures_getString(regionalData, &len, &status);
160459d709d503bab6e2b61931737e662dd293b40578ccornelius            if (U_FAILURE(status)) {
160559d709d503bab6e2b61931737e662dd293b40578ccornelius                break;
160659d709d503bab6e2b61931737e662dd293b40578ccornelius            }
160759d709d503bab6e2b61931737e662dd293b40578ccornelius
160859d709d503bab6e2b61931737e662dd293b40578ccornelius            const UChar *start = tzids;
160959d709d503bab6e2b61931737e662dd293b40578ccornelius            UBool hasNext = TRUE;
161059d709d503bab6e2b61931737e662dd293b40578ccornelius            while (hasNext) {
161159d709d503bab6e2b61931737e662dd293b40578ccornelius                const UChar *end = u_strchr(start, (UChar)0x20);
161259d709d503bab6e2b61931737e662dd293b40578ccornelius                if (end == NULL) {
161359d709d503bab6e2b61931737e662dd293b40578ccornelius                    end = tzids + len;
161459d709d503bab6e2b61931737e662dd293b40578ccornelius                    hasNext = FALSE;
161559d709d503bab6e2b61931737e662dd293b40578ccornelius                }
161659d709d503bab6e2b61931737e662dd293b40578ccornelius                if (canonicalID.compare(start, end - start) == 0) {
161759d709d503bab6e2b61931737e662dd293b40578ccornelius                    winid = UnicodeString(ures_getKey(winzone), -1 , US_INV);
161859d709d503bab6e2b61931737e662dd293b40578ccornelius                    found = TRUE;
161959d709d503bab6e2b61931737e662dd293b40578ccornelius                    break;
162059d709d503bab6e2b61931737e662dd293b40578ccornelius                }
162159d709d503bab6e2b61931737e662dd293b40578ccornelius                start = end + 1;
162259d709d503bab6e2b61931737e662dd293b40578ccornelius            }
162359d709d503bab6e2b61931737e662dd293b40578ccornelius        }
162459d709d503bab6e2b61931737e662dd293b40578ccornelius        ures_close(regionalData);
162559d709d503bab6e2b61931737e662dd293b40578ccornelius    }
162659d709d503bab6e2b61931737e662dd293b40578ccornelius    ures_close(winzone);
162759d709d503bab6e2b61931737e662dd293b40578ccornelius    ures_close(mapTimezones);
162859d709d503bab6e2b61931737e662dd293b40578ccornelius
162959d709d503bab6e2b61931737e662dd293b40578ccornelius    return winid;
163059d709d503bab6e2b61931737e662dd293b40578ccornelius}
163159d709d503bab6e2b61931737e662dd293b40578ccornelius
163259d709d503bab6e2b61931737e662dd293b40578ccornelius#define MAX_WINDOWS_ID_SIZE 128
163359d709d503bab6e2b61931737e662dd293b40578ccornelius
163459d709d503bab6e2b61931737e662dd293b40578ccorneliusUnicodeString&
163559d709d503bab6e2b61931737e662dd293b40578ccorneliusTimeZone::getIDForWindowsID(const UnicodeString& winid, const char* region, UnicodeString& id, UErrorCode& status) {
163659d709d503bab6e2b61931737e662dd293b40578ccornelius    id.remove();
163759d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_FAILURE(status)) {
163859d709d503bab6e2b61931737e662dd293b40578ccornelius        return id;
163959d709d503bab6e2b61931737e662dd293b40578ccornelius    }
164059d709d503bab6e2b61931737e662dd293b40578ccornelius
164159d709d503bab6e2b61931737e662dd293b40578ccornelius    UResourceBundle *zones = ures_openDirect(NULL, "windowsZones", &status);
164259d709d503bab6e2b61931737e662dd293b40578ccornelius    ures_getByKey(zones, "mapTimezones", zones, &status);
164359d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_FAILURE(status)) {
164459d709d503bab6e2b61931737e662dd293b40578ccornelius        ures_close(zones);
164559d709d503bab6e2b61931737e662dd293b40578ccornelius        return id;
164659d709d503bab6e2b61931737e662dd293b40578ccornelius    }
164759d709d503bab6e2b61931737e662dd293b40578ccornelius
164859d709d503bab6e2b61931737e662dd293b40578ccornelius    UErrorCode tmperr = U_ZERO_ERROR;
164959d709d503bab6e2b61931737e662dd293b40578ccornelius    char winidKey[MAX_WINDOWS_ID_SIZE];
165059d709d503bab6e2b61931737e662dd293b40578ccornelius    int32_t winKeyLen = winid.extract(0, winid.length(), winidKey, sizeof(winidKey) - 1, US_INV);
165159d709d503bab6e2b61931737e662dd293b40578ccornelius
165259d709d503bab6e2b61931737e662dd293b40578ccornelius    if (winKeyLen == 0 || winKeyLen >= (int32_t)sizeof(winidKey)) {
165359d709d503bab6e2b61931737e662dd293b40578ccornelius        ures_close(zones);
165459d709d503bab6e2b61931737e662dd293b40578ccornelius        return id;
165559d709d503bab6e2b61931737e662dd293b40578ccornelius    }
165659d709d503bab6e2b61931737e662dd293b40578ccornelius    winidKey[winKeyLen] = 0;
165759d709d503bab6e2b61931737e662dd293b40578ccornelius
165859d709d503bab6e2b61931737e662dd293b40578ccornelius    ures_getByKey(zones, winidKey, zones, &tmperr); // use tmperr, because windows mapping might not
165959d709d503bab6e2b61931737e662dd293b40578ccornelius                                                    // be avaiable by design
166059d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_FAILURE(tmperr)) {
166159d709d503bab6e2b61931737e662dd293b40578ccornelius        ures_close(zones);
166259d709d503bab6e2b61931737e662dd293b40578ccornelius        return id;
166359d709d503bab6e2b61931737e662dd293b40578ccornelius    }
166459d709d503bab6e2b61931737e662dd293b40578ccornelius
166559d709d503bab6e2b61931737e662dd293b40578ccornelius    const UChar *tzid = NULL;
166659d709d503bab6e2b61931737e662dd293b40578ccornelius    int32_t len = 0;
166759d709d503bab6e2b61931737e662dd293b40578ccornelius    UBool gotID = FALSE;
166859d709d503bab6e2b61931737e662dd293b40578ccornelius    if (region) {
166959d709d503bab6e2b61931737e662dd293b40578ccornelius        const UChar *tzids = ures_getStringByKey(zones, region, &len, &tmperr); // use tmperr, because
167059d709d503bab6e2b61931737e662dd293b40578ccornelius                                                                                // regional mapping is optional
167159d709d503bab6e2b61931737e662dd293b40578ccornelius        if (U_SUCCESS(tmperr)) {
167259d709d503bab6e2b61931737e662dd293b40578ccornelius            // first ID delimited by space is the defasult one
167359d709d503bab6e2b61931737e662dd293b40578ccornelius            const UChar *end = u_strchr(tzids, (UChar)0x20);
167459d709d503bab6e2b61931737e662dd293b40578ccornelius            if (end == NULL) {
167559d709d503bab6e2b61931737e662dd293b40578ccornelius                id.setTo(tzids, -1);
167659d709d503bab6e2b61931737e662dd293b40578ccornelius            } else {
167759d709d503bab6e2b61931737e662dd293b40578ccornelius                id.setTo(tzids, end - tzids);
167859d709d503bab6e2b61931737e662dd293b40578ccornelius            }
167959d709d503bab6e2b61931737e662dd293b40578ccornelius            gotID = TRUE;
168059d709d503bab6e2b61931737e662dd293b40578ccornelius        }
168159d709d503bab6e2b61931737e662dd293b40578ccornelius    }
168259d709d503bab6e2b61931737e662dd293b40578ccornelius
168359d709d503bab6e2b61931737e662dd293b40578ccornelius    if (!gotID) {
168459d709d503bab6e2b61931737e662dd293b40578ccornelius        tzid = ures_getStringByKey(zones, "001", &len, &status);    // using status, because "001" must be
168559d709d503bab6e2b61931737e662dd293b40578ccornelius                                                                // available at this point
168659d709d503bab6e2b61931737e662dd293b40578ccornelius        if (U_SUCCESS(status)) {
168759d709d503bab6e2b61931737e662dd293b40578ccornelius            id.setTo(tzid, len);
168859d709d503bab6e2b61931737e662dd293b40578ccornelius        }
168959d709d503bab6e2b61931737e662dd293b40578ccornelius    }
169059d709d503bab6e2b61931737e662dd293b40578ccornelius
169159d709d503bab6e2b61931737e662dd293b40578ccornelius    ures_close(zones);
169259d709d503bab6e2b61931737e662dd293b40578ccornelius    return id;
169359d709d503bab6e2b61931737e662dd293b40578ccornelius}
169459d709d503bab6e2b61931737e662dd293b40578ccornelius
169559d709d503bab6e2b61931737e662dd293b40578ccornelius
1696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_END
1697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_FORMATTING */
1699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//eof
1701