1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*******************************************************************************
31b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert* Copyright (C) 1997-2015, International Business Machines Corporation and
459d709d503bab6e2b61931737e662dd293b40578ccornelius* others. All Rights Reserved.
5b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*******************************************************************************
6b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
7b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* File TIMEZONE.CPP
8b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
9b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru* Modification History:
10b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
11b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   Date        Name        Description
12b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   12/05/96    clhuang     Creation.
13b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   04/21/97    aliu        General clean-up and bug fixing.
14b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   05/08/97    aliu        Fixed Hashtable code per code review.
15b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   07/09/97    helena      Changed createInstance to createDefault.
16b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   07/29/97    aliu        Updated with all-new list of 96 UNIX-derived
17b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                           TimeZones.  Changed mechanism to load from static
18b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                           array rather than resource bundle.
19b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*   07/07/1998  srl         Bugfixes from the Java side: UTC GMT CAT NST
20b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                           Added getDisplayName API
21b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                           going to add custom parsing.
22b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*
23b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                           ISSUES:
24b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                               - should getDisplayName cache something?
25b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                               - should custom time zones be cached? [probably]
26b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*  08/10/98     stephen     Brought getDisplayName() API in-line w/ conventions
27b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*  08/19/98     stephen     Changed createTimeZone() to never return 0
28b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*  09/02/98     stephen     Added getOffset(monthLen) and hasSameRules()
29b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*  09/15/98     stephen     Added getStaticClassID()
30b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*  02/22/99     stephen     Removed character literals for EBCDIC safety
31b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*  05/04/99     stephen     Changed initDefault() for Mutex issues
32b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*  07/12/99     helena      HPUX 11 CC Port.
33b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*  12/03/99     aliu        Moved data out of static table into icudata.dll.
34b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                           Substantial rewrite of zone lookup, default zone, and
35b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*                           available IDs code.  Misc. cleanup.
36b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*********************************************************************************/
37b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
3854dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#include "utypeinfo.h"  // for 'typeid' to work
3927f654740f2a26ad62a5c155af9199af9e69b889claireho
40b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/utypes.h"
41b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/ustring.h"
4259d709d503bab6e2b61931737e662dd293b40578ccornelius#include "uassert.h"
43b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "ustr_imp.h"
44b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
45b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#ifdef U_DEBUG_TZ
46b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru# include <stdio.h>
47b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru# include "uresimp.h" // for debugging
48b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
49b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void debug_tz_loc(const char *f, int32_t l)
50b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
51b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  fprintf(stderr, "%s:%d: ", f, l);
52b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
53b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
54b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic void debug_tz_msg(const char *pat, ...)
55b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
56b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  va_list ap;
57b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  va_start(ap, pat);
58b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  vfprintf(stderr, pat, ap);
59b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru  fflush(stderr);
60b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
61b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic char gStrBuf[256];
62b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define U_DEBUG_TZ_STR(x) u_austrncpy(gStrBuf,x,sizeof(gStrBuf)-1)
63b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// must use double parens, i.e.:  U_DEBUG_TZ_MSG(("four is: %d",4));
64b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define U_DEBUG_TZ_MSG(x) {debug_tz_loc(__FILE__,__LINE__);debug_tz_msg x;}
65b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#else
66b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define U_DEBUG_TZ_MSG(x)
67b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
68b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
69b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if !UCONFIG_NO_FORMATTING
70b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
71b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/simpletz.h"
72b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/calendar.h"
73b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/gregocal.h"
74b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/ures.h"
75103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "unicode/tzfmt.h"
76103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#include "unicode/numfmt.h"
77b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "gregoimp.h"
78b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uresimp.h" // struct UResourceBundle
79b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "olsontz.h"
80b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "mutex.h"
81b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/udata.h"
82b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "ucln_in.h"
83b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cstring.h"
84b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "cmemory.h"
85b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "unicode/strenum.h"
86b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#include "uassert.h"
87c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru#include "zonemeta.h"
88b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
8950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define kZONEINFO "zoneinfo64"
90b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define kREGIONS  "Regions"
91b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define kZONES    "Zones"
92b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define kRULES    "Rules"
93b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define kNAMES    "Names"
9450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define kTZVERSION  "TZVersion"
9550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#define kLINKS    "links"
96b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define kMAX_CUSTOM_HOUR    23
97b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define kMAX_CUSTOM_MIN     59
98b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define kMAX_CUSTOM_SEC     59
99b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define MINUS 0x002D
100b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define PLUS 0x002B
101b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#define ZERO_DIGIT 0x0030
102b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#define COLON 0x003A
103b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// Static data and constants
105b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
10650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehostatic const UChar         WORLD[] = {0x30, 0x30, 0x31, 0x00}; /* "001" */
10750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const UChar         GMT_ID[] = {0x47, 0x4D, 0x54, 0x00}; /* "GMT" */
109b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const UChar         UNKNOWN_ZONE_ID[] = {0x45, 0x74, 0x63, 0x2F, 0x55, 0x6E, 0x6B, 0x6E, 0x6F, 0x77, 0x6E, 0x00}; /* "Etc/Unknown" */
110b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic const int32_t       GMT_ID_LENGTH = 3;
111b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic const int32_t       UNKNOWN_ZONE_ID_LENGTH = 11;
112b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
113103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic icu::TimeZone* DEFAULT_ZONE = NULL;
11459d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic icu::UInitOnce gDefaultZoneInitOnce = U_INITONCE_INITIALIZER;
11559d709d503bab6e2b61931737e662dd293b40578ccornelius
116103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic icu::TimeZone* _GMT = NULL;
117103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic icu::TimeZone* _UNKNOWN_ZONE = NULL;
11859d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic icu::UInitOnce gStaticZonesInitOnce = U_INITONCE_INITIALIZER;
119b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
120c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Querustatic char TZDATA_VERSION[16];
12159d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic icu::UInitOnce gTZDataVersionInitOnce = U_INITONCE_INITIALIZER;
122b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
123b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic int32_t* MAP_SYSTEM_ZONES = NULL;
124b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic int32_t* MAP_CANONICAL_SYSTEM_ZONES = NULL;
125b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehostatic int32_t* MAP_CANONICAL_SYSTEM_LOCATION_ZONES = NULL;
126b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
127103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic int32_t LEN_SYSTEM_ZONES = 0;
128103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic int32_t LEN_CANONICAL_SYSTEM_ZONES = 0;
129103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusstatic int32_t LEN_CANONICAL_SYSTEM_LOCATION_ZONES = 0;
130b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
13159d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic icu::UInitOnce gSystemZonesInitOnce = U_INITONCE_INITIALIZER;
13259d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic icu::UInitOnce gCanonicalZonesInitOnce = U_INITONCE_INITIALIZER;
13359d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic icu::UInitOnce gCanonicalLocationZonesInitOnce = U_INITONCE_INITIALIZER;
13459d709d503bab6e2b61931737e662dd293b40578ccornelius
135b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_BEGIN
136b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UBool U_CALLCONV timeZone_cleanup(void)
137b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
13859d709d503bab6e2b61931737e662dd293b40578ccornelius    U_NAMESPACE_USE
139b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete DEFAULT_ZONE;
140b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    DEFAULT_ZONE = NULL;
14159d709d503bab6e2b61931737e662dd293b40578ccornelius    gDefaultZoneInitOnce.reset();
142b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    delete _GMT;
144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    _GMT = NULL;
145103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    delete _UNKNOWN_ZONE;
146103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    _UNKNOWN_ZONE = NULL;
14759d709d503bab6e2b61931737e662dd293b40578ccornelius    gStaticZonesInitOnce.reset();
148103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    uprv_memset(TZDATA_VERSION, 0, sizeof(TZDATA_VERSION));
15059d709d503bab6e2b61931737e662dd293b40578ccornelius    gTZDataVersionInitOnce.reset();
151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
152b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    LEN_SYSTEM_ZONES = 0;
153b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uprv_free(MAP_SYSTEM_ZONES);
154b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    MAP_SYSTEM_ZONES = 0;
15559d709d503bab6e2b61931737e662dd293b40578ccornelius    gSystemZonesInitOnce.reset();
156b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
157b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    LEN_CANONICAL_SYSTEM_ZONES = 0;
158b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uprv_free(MAP_CANONICAL_SYSTEM_ZONES);
159b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    MAP_CANONICAL_SYSTEM_ZONES = 0;
16059d709d503bab6e2b61931737e662dd293b40578ccornelius    gCanonicalZonesInitOnce.reset();
161b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
162b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    LEN_CANONICAL_SYSTEM_LOCATION_ZONES = 0;
163b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    uprv_free(MAP_CANONICAL_SYSTEM_LOCATION_ZONES);
164b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    MAP_CANONICAL_SYSTEM_LOCATION_ZONES = 0;
16559d709d503bab6e2b61931737e662dd293b40578ccornelius    gCanonicalLocationZonesInitOnce.reset();
166b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return TRUE;
168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_CDECL_END
170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_BEGIN
172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic int32_t findInStringArray(UResourceBundle* array, const UnicodeString& id, UErrorCode &status)
174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString copy;
176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const UChar *u;
177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t len;
178b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t start = 0;
180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t limit = ures_getSize(array);
181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t mid;
182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t lastMid = INT32_MAX;
183b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(U_FAILURE(status) || (limit < 1)) {
184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return -1;
185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
186b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_DEBUG_TZ_MSG(("fisa: Looking for %s, between %d and %d\n", U_DEBUG_TZ_STR(UnicodeString(id).getTerminatedBuffer()), start, limit));
187b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (;;) {
189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        mid = (int32_t)((start + limit) / 2);
190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (lastMid == mid) {   /* Have we moved? */
191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;  /* We haven't moved, and it wasn't found. */
192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        lastMid = mid;
194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        u = ures_getStringByIndex(array, mid, &len, &status);
195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_FAILURE(status)) {
196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
198b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        U_DEBUG_TZ_MSG(("tz: compare to %s, %d .. [%d] .. %d\n", U_DEBUG_TZ_STR(u), start, mid, limit));
199b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        copy.setTo(TRUE, u, len);
200b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int r = id.compare(copy);
201b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(r==0) {
202b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            U_DEBUG_TZ_MSG(("fisa: found at %d\n", mid));
203b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return mid;
204b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else if(r<0) {
205b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            limit = mid;
206b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
207b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            start = mid;
208b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
209b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
210b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_DEBUG_TZ_MSG(("fisa: not found\n"));
211b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return -1;
212b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
213b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
214b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
215b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * Fetch a specific zone by name.  Replaces the getByKey call.
216b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param top Top timezone resource
217b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param id Time zone ID
218b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param oldbundle Bundle for reuse (or NULL).   see 'ures_open()'
219b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @return the zone's bundle if found, or undefined if error.  Reuses oldbundle.
220b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
221b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UResourceBundle* getZoneByName(const UResourceBundle* top, const UnicodeString& id, UResourceBundle *oldbundle, UErrorCode& status) {
222b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // load the Rules object
223b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UResourceBundle *tmp = ures_getByKey(top, kNAMES, NULL, &status);
224b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
225b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // search for the string
226b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t idx = findInStringArray(tmp, id, status);
227b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
228b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if((idx == -1) && U_SUCCESS(status)) {
229b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // not found
230b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        status = U_MISSING_RESOURCE_ERROR;
231b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        //ures_close(oldbundle);
232b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        //oldbundle = NULL;
233b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
234b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        U_DEBUG_TZ_MSG(("gzbn: oldbundle= size %d, type %d, %s\n", ures_getSize(tmp), ures_getType(tmp), u_errorName(status)));
235b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        tmp = ures_getByKey(top, kZONES, tmp, &status); // get Zones object from top
236b13da9df870a61b11249bf741347908dbea0edd8Jean-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)));
237b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        oldbundle = ures_getByIndex(tmp, idx, oldbundle, &status); // get nth Zone object
238b13da9df870a61b11249bf741347908dbea0edd8Jean-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)));
239b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
240b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_close(tmp);
241b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if(U_FAILURE(status)) {
242b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        //ures_close(oldbundle);
243b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return NULL;
244b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
245b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return oldbundle;
246b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
247b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
248b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
249b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
250b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUResourceBundle* TimeZone::loadRule(const UResourceBundle* top, const UnicodeString& ruleid, UResourceBundle* oldbundle, UErrorCode& status) {
251b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char key[64];
252b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ruleid.extract(0, sizeof(key)-1, key, (int32_t)sizeof(key)-1, US_INV);
253b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_DEBUG_TZ_MSG(("loadRule(%s)\n", key));
254b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UResourceBundle *r = ures_getByKey(top, kRULES, oldbundle, &status);
255b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_DEBUG_TZ_MSG(("loadRule(%s) -> kRULES [%s]\n", key, u_errorName(status)));
256b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    r = ures_getByKey(r, key, r, &status);
257b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_DEBUG_TZ_MSG(("loadRule(%s) -> item [%s]\n", key, u_errorName(status)));
258b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return r;
259b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
260b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
261b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
262b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Given an ID, open the appropriate resource for the given time zone.
263b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Dereference aliases if necessary.
264b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param id zone id
265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param res resource, which must be ready for use (initialized but not open)
266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param ec input-output error code
267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @return top-level resource bundle
268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querustatic UResourceBundle* openOlsonResource(const UnicodeString& id,
270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                          UResourceBundle& res,
271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                                          UErrorCode& ec)
272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if U_DEBUG_TZ
274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    char buf[128];
275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    id.extract(0, sizeof(buf)-1, buf, sizeof(buf), "");
276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
277b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UResourceBundle *top = ures_openDirect(0, kZONEINFO, &ec);
278b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_DEBUG_TZ_MSG(("pre: res sz=%d\n", ures_getSize(&res)));
279b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* &res = */ getZoneByName(top, id, &res, ec);
280b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Dereference if this is an alias.  Docs say result should be 1
281b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // but it is 0 in 2.8 (?).
282b13da9df870a61b11249bf741347908dbea0edd8Jean-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)));
283b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (ures_getType(&res) == URES_INT) {
284b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t deref = ures_getInt(&res, &ec) + 0;
285b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        U_DEBUG_TZ_MSG(("getInt: %s - type is %d\n", u_errorName(ec), ures_getType(&res)));
286b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UResourceBundle *ares = ures_getByKey(top, kZONES, NULL, &ec); // dereference Zones section
287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ures_getByIndex(ares, deref, &res, &ec);
288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ures_close(ares);
289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        U_DEBUG_TZ_MSG(("alias to #%d (%s) - %s\n", deref, "??", u_errorName(ec)));
290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    } else {
291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        U_DEBUG_TZ_MSG(("not an alias - size %d\n", ures_getSize(&res)));
292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_DEBUG_TZ_MSG(("%s - final status is %s\n", buf, u_errorName(ec)));
294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return top;
295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
299103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusnamespace {
300103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
30159d709d503bab6e2b61931737e662dd293b40578ccorneliusvoid U_CALLCONV initStaticTimeZones() {
302b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Initialize _GMT independently of other static data; it should
303b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // be valid even if we can't load the time zone UDataMemory.
30459d709d503bab6e2b61931737e662dd293b40578ccornelius    ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
30559d709d503bab6e2b61931737e662dd293b40578ccornelius    _UNKNOWN_ZONE = new SimpleTimeZone(0, UnicodeString(TRUE, UNKNOWN_ZONE_ID, UNKNOWN_ZONE_ID_LENGTH));
30659d709d503bab6e2b61931737e662dd293b40578ccornelius    _GMT = new SimpleTimeZone(0, UnicodeString(TRUE, GMT_ID, GMT_ID_LENGTH));
307103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
308103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
309103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}  // anonymous namespace
310103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
311103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusconst TimeZone& U_EXPORT2
312103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTimeZone::getUnknown()
313103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius{
31459d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_initOnce(gStaticZonesInitOnce, &initStaticTimeZones);
315103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    return *_UNKNOWN_ZONE;
316103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
317103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
318103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusconst TimeZone* U_EXPORT2
319103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTimeZone::getGMT(void)
320103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius{
32159d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_initOnce(gStaticZonesInitOnce, &initStaticTimeZones);
322b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return _GMT;
323b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
324b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// *****************************************************************************
326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// class TimeZone
327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// *****************************************************************************
328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUOBJECT_DEFINE_ABSTRACT_RTTI_IMPLEMENTATION(TimeZone)
330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::TimeZone()
332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    :   UObject(), fID()
333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::TimeZone(const UnicodeString &id)
339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    :   UObject(), fID(id)
340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
341b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::~TimeZone()
346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::TimeZone(const TimeZone &source)
352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    :   UObject(source), fID(source.fID)
353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone &
359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::operator=(const TimeZone &right)
360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (this != &right) fID = right.fID;
362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return *this;
363b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUBool
368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::operator==(const TimeZone& that) const
369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
37027f654740f2a26ad62a5c155af9199af9e69b889claireho    return typeid(*this) == typeid(that) &&
371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        fID == that.fID;
372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
37659d709d503bab6e2b61931737e662dd293b40578ccorneliusnamespace {
377b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZone*
37859d709d503bab6e2b61931737e662dd293b40578ccorneliuscreateSystemTimeZone(const UnicodeString& id, UErrorCode& ec) {
379b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(ec)) {
380b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
381b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
382b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TimeZone* z = 0;
383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UResourceBundle res;
384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_initStackObject(&res);
385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_DEBUG_TZ_MSG(("pre-err=%s\n", u_errorName(ec)));
386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UResourceBundle *top = openOlsonResource(id, res, ec);
387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_DEBUG_TZ_MSG(("post-err=%s\n", u_errorName(ec)));
388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_SUCCESS(ec)) {
389b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        z = new OlsonTimeZone(top, &res, id, ec);
390b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (z == NULL) {
391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru          U_DEBUG_TZ_MSG(("cstz: olson time zone failed to initialize - err %s\n", u_errorName(ec)));
392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_close(&res);
395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_close(top);
396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(ec)) {
397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        U_DEBUG_TZ_MSG(("cstz: failed to create, err %s\n", u_errorName(ec)));
398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete z;
399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        z = 0;
400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return z;
402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
40459d709d503bab6e2b61931737e662dd293b40578ccornelius/**
40559d709d503bab6e2b61931737e662dd293b40578ccornelius * Lookup the given name in our system zone table.  If found,
40659d709d503bab6e2b61931737e662dd293b40578ccornelius * instantiate a new zone of that name and return it.  If not
40759d709d503bab6e2b61931737e662dd293b40578ccornelius * found, return 0.
40859d709d503bab6e2b61931737e662dd293b40578ccornelius */
40959d709d503bab6e2b61931737e662dd293b40578ccorneliusTimeZone*
41059d709d503bab6e2b61931737e662dd293b40578ccorneliuscreateSystemTimeZone(const UnicodeString& id) {
41159d709d503bab6e2b61931737e662dd293b40578ccornelius    UErrorCode ec = U_ZERO_ERROR;
41259d709d503bab6e2b61931737e662dd293b40578ccornelius    return createSystemTimeZone(id, ec);
41359d709d503bab6e2b61931737e662dd293b40578ccornelius}
41459d709d503bab6e2b61931737e662dd293b40578ccornelius
41559d709d503bab6e2b61931737e662dd293b40578ccornelius}
41659d709d503bab6e2b61931737e662dd293b40578ccornelius
41759d709d503bab6e2b61931737e662dd293b40578ccorneliusTimeZone* U_EXPORT2
41859d709d503bab6e2b61931737e662dd293b40578ccorneliusTimeZone::createTimeZone(const UnicodeString& ID)
41959d709d503bab6e2b61931737e662dd293b40578ccornelius{
42059d709d503bab6e2b61931737e662dd293b40578ccornelius    /* We first try to lookup the zone ID in our system list.  If this
42159d709d503bab6e2b61931737e662dd293b40578ccornelius     * fails, we try to parse it as a custom string GMT[+-]hh:mm.  If
42259d709d503bab6e2b61931737e662dd293b40578ccornelius     * all else fails, we return GMT, which is probably not what the
42359d709d503bab6e2b61931737e662dd293b40578ccornelius     * user wants, but at least is a functioning TimeZone object.
42459d709d503bab6e2b61931737e662dd293b40578ccornelius     *
42559d709d503bab6e2b61931737e662dd293b40578ccornelius     * We cannot return NULL, because that would break compatibility
42659d709d503bab6e2b61931737e662dd293b40578ccornelius     * with the JDK.
42759d709d503bab6e2b61931737e662dd293b40578ccornelius     */
42859d709d503bab6e2b61931737e662dd293b40578ccornelius    TimeZone* result = createSystemTimeZone(ID);
42959d709d503bab6e2b61931737e662dd293b40578ccornelius
4301b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    if (result == NULL) {
43159d709d503bab6e2b61931737e662dd293b40578ccornelius        U_DEBUG_TZ_MSG(("failed to load system time zone with id - falling to custom"));
43259d709d503bab6e2b61931737e662dd293b40578ccornelius        result = createCustomTimeZone(ID);
43359d709d503bab6e2b61931737e662dd293b40578ccornelius    }
4341b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    if (result == NULL) {
43559d709d503bab6e2b61931737e662dd293b40578ccornelius        U_DEBUG_TZ_MSG(("failed to load time zone with id - falling to Etc/Unknown(GMT)"));
4361b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        const TimeZone& unknown = getUnknown();
4371b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        if (_UNKNOWN_ZONE == NULL) {                   // Cannot test (&unknown == NULL) because the
4381b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          U_DEBUG_TZ_MSG(("failed to getUnknown()"));  // behavior of NULL references is undefined.
4391b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        } else {
4401b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert          result = unknown.clone();
4411b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        }
44259d709d503bab6e2b61931737e662dd293b40578ccornelius    }
44359d709d503bab6e2b61931737e662dd293b40578ccornelius    return result;
44459d709d503bab6e2b61931737e662dd293b40578ccornelius}
44559d709d503bab6e2b61931737e662dd293b40578ccornelius
446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
4481b7d32f919554dda9c193b32188251337bc756f1Fredrik RoubertTimeZone* U_EXPORT2
4491b7d32f919554dda9c193b32188251337bc756f1Fredrik RoubertTimeZone::detectHostTimeZone()
450b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho{
451b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // We access system timezone data through TPlatformUtilities,
452b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // including tzset(), timezone, and tzname[].
453b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t rawOffset = 0;
454b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *hostID;
455b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
456b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // First, try to create a system timezone, based
457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // on the string ID in tzname[0].
458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
45959d709d503bab6e2b61931737e662dd293b40578ccornelius    uprv_tzset(); // Initialize tz... system data
460b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
46159d709d503bab6e2b61931737e662dd293b40578ccornelius    // Get the timezone ID from the host.  This function should do
46259d709d503bab6e2b61931737e662dd293b40578ccornelius    // any required host-specific remapping; e.g., on Windows this
46359d709d503bab6e2b61931737e662dd293b40578ccornelius    // function maps the Date and Time control panel setting to an
46459d709d503bab6e2b61931737e662dd293b40578ccornelius    // ICU timezone ID.
46559d709d503bab6e2b61931737e662dd293b40578ccornelius    hostID = uprv_tzname(0);
466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
46759d709d503bab6e2b61931737e662dd293b40578ccornelius    // Invert sign because UNIX semantics are backwards
46859d709d503bab6e2b61931737e662dd293b40578ccornelius    rawOffset = uprv_timezone() * -U_MILLIS_PER_SECOND;
469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
4701b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    TimeZone* hostZone = NULL;
471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
472b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Make sure that the string is NULL terminated to prevent BoundsChecker/Purify warnings. */
473b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString hostStrID(hostID, -1, US_INV);
474b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    hostStrID.append((UChar)0);
475b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    hostStrID.truncate(hostStrID.length()-1);
4761b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    hostZone = createSystemTimeZone(hostStrID);
477b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
478103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if U_PLATFORM_USES_ONLY_WIN32_API
47950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    // hostID points to a heap-allocated location on Windows.
48050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    uprv_free(const_cast<char *>(hostID));
48150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif
48250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t hostIDLen = hostStrID.length();
4841b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    if (hostZone != NULL && rawOffset != hostZone->getRawOffset()
485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        && (3 <= hostIDLen && hostIDLen <= 4))
486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Uh oh. This probably wasn't a good id.
488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // It was probably an ambiguous abbreviation
4891b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        delete hostZone;
4901b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        hostZone = NULL;
491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Construct a fixed standard zone with the host's ID
494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // and raw offset.
4951b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    if (hostZone == NULL) {
4961b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        hostZone = new SimpleTimeZone(rawOffset, hostStrID);
497b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
499b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // If we _still_ don't have a time zone, use GMT.
5001b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    //
5011b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    // Note: This is extremely unlikely situation. If
5021b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    // new SimpleTimeZone(...) above fails, the following
5031b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    // code may also fail.
5041b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    if (hostZone == NULL) {
50559d709d503bab6e2b61931737e662dd293b40578ccornelius        const TimeZone* temptz = TimeZone::getGMT();
506c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // If we can't use GMT, get out.
507c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (temptz == NULL) {
5081b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert            return NULL;
509c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
5101b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        hostZone = temptz->clone();
5111b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    }
5121b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
5131b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    return hostZone;
5141b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert}
5151b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
5161b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert// -------------------------------------
5171b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
5181b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert/**
5191b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert * Initialize DEFAULT_ZONE from the system default time zone.
5201b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert * Upon return, DEFAULT_ZONE will not be NULL, unless operator new()
5211b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert * returns NULL.
5221b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert */
5231b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubertstatic void U_CALLCONV initDefault()
5241b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert{
5251b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
5261b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
5271b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    // If setDefault() has already been called we can skip getting the
5281b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    // default zone information from the system.
5291b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    if (DEFAULT_ZONE != NULL) {
5301b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert        return;
531b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
5321b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
5331b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    // NOTE:  this code is safely single threaded, being only
5341b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    // run via umtx_initOnce().
5351b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    //
5361b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    // Some of the locale/timezone OS functions may not be thread safe,
5371b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    //
5381b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    // The operating system might actually use ICU to implement timezones.
5391b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    // So we may have ICU calling ICU here, like on AIX.
5401b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    // There shouldn't be a problem with this; initOnce does not hold a mutex
5411b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    // while the init function is being run.
5421b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
5431b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    // The code detecting the host time zone was separated from this
5441b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    // and implemented as TimeZone::detectHostTimeZone()
5451b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert
5461b7d32f919554dda9c193b32188251337bc756f1Fredrik Roubert    TimeZone *default_zone = TimeZone::detectHostTimeZone();
547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
54859d709d503bab6e2b61931737e662dd293b40578ccornelius    // The only way for DEFAULT_ZONE to be non-null at this point is if the user
54959d709d503bab6e2b61931737e662dd293b40578ccornelius    // made a thread-unsafe call to setDefault() or adoptDefault() in another
55059d709d503bab6e2b61931737e662dd293b40578ccornelius    // thread while this thread was doing something that required getting the default.
55159d709d503bab6e2b61931737e662dd293b40578ccornelius    U_ASSERT(DEFAULT_ZONE == NULL);
552b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
55359d709d503bab6e2b61931737e662dd293b40578ccornelius    DEFAULT_ZONE = default_zone;
554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone* U_EXPORT2
559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::createDefault()
560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
56159d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_initOnce(gDefaultZoneInitOnce, initDefault);
562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (DEFAULT_ZONE != NULL) ? DEFAULT_ZONE->clone() : NULL;
563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
566b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
567b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid U_EXPORT2
568b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::adoptDefault(TimeZone* zone)
569b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
570b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (zone != NULL)
571b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
57259d709d503bab6e2b61931737e662dd293b40578ccornelius        TimeZone *old = DEFAULT_ZONE;
573b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        DEFAULT_ZONE = zone;
574b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete old;
575b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
576b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
577b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
578b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
579b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
580b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid U_EXPORT2
581b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::setDefault(const TimeZone& zone)
582b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
583b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    adoptDefault(zone.clone());
584b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
585b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
586b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//----------------------------------------------------------------------
587b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
58859d709d503bab6e2b61931737e662dd293b40578ccornelius
58959d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic void U_CALLCONV initMap(USystemTimeZoneType type, UErrorCode& ec) {
59059d709d503bab6e2b61931737e662dd293b40578ccornelius    ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
59159d709d503bab6e2b61931737e662dd293b40578ccornelius
59259d709d503bab6e2b61931737e662dd293b40578ccornelius    UResourceBundle *res = ures_openDirect(0, kZONEINFO, &ec);
59359d709d503bab6e2b61931737e662dd293b40578ccornelius    res = ures_getByKey(res, kNAMES, res, &ec); // dereference Zones section
59459d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_SUCCESS(ec)) {
59559d709d503bab6e2b61931737e662dd293b40578ccornelius        int32_t size = ures_getSize(res);
59659d709d503bab6e2b61931737e662dd293b40578ccornelius        int32_t *m = (int32_t *)uprv_malloc(size * sizeof(int32_t));
59759d709d503bab6e2b61931737e662dd293b40578ccornelius        if (m == NULL) {
59859d709d503bab6e2b61931737e662dd293b40578ccornelius            ec = U_MEMORY_ALLOCATION_ERROR;
59959d709d503bab6e2b61931737e662dd293b40578ccornelius        } else {
60059d709d503bab6e2b61931737e662dd293b40578ccornelius            int32_t numEntries = 0;
60159d709d503bab6e2b61931737e662dd293b40578ccornelius            for (int32_t i = 0; i < size; i++) {
60259d709d503bab6e2b61931737e662dd293b40578ccornelius                UnicodeString id = ures_getUnicodeStringByIndex(res, i, &ec);
60359d709d503bab6e2b61931737e662dd293b40578ccornelius                if (U_FAILURE(ec)) {
60459d709d503bab6e2b61931737e662dd293b40578ccornelius                    break;
60559d709d503bab6e2b61931737e662dd293b40578ccornelius                }
60659d709d503bab6e2b61931737e662dd293b40578ccornelius                if (0 == id.compare(UNKNOWN_ZONE_ID, UNKNOWN_ZONE_ID_LENGTH)) {
60759d709d503bab6e2b61931737e662dd293b40578ccornelius                    // exclude Etc/Unknown
60859d709d503bab6e2b61931737e662dd293b40578ccornelius                    continue;
60959d709d503bab6e2b61931737e662dd293b40578ccornelius                }
61059d709d503bab6e2b61931737e662dd293b40578ccornelius                if (type == UCAL_ZONE_TYPE_CANONICAL || type == UCAL_ZONE_TYPE_CANONICAL_LOCATION) {
61159d709d503bab6e2b61931737e662dd293b40578ccornelius                    UnicodeString canonicalID;
61259d709d503bab6e2b61931737e662dd293b40578ccornelius                    ZoneMeta::getCanonicalCLDRID(id, canonicalID, ec);
61359d709d503bab6e2b61931737e662dd293b40578ccornelius                    if (U_FAILURE(ec)) {
61459d709d503bab6e2b61931737e662dd293b40578ccornelius                        break;
61559d709d503bab6e2b61931737e662dd293b40578ccornelius                    }
61659d709d503bab6e2b61931737e662dd293b40578ccornelius                    if (canonicalID != id) {
61759d709d503bab6e2b61931737e662dd293b40578ccornelius                        // exclude aliases
61859d709d503bab6e2b61931737e662dd293b40578ccornelius                        continue;
61959d709d503bab6e2b61931737e662dd293b40578ccornelius                    }
62059d709d503bab6e2b61931737e662dd293b40578ccornelius                }
62159d709d503bab6e2b61931737e662dd293b40578ccornelius                if (type == UCAL_ZONE_TYPE_CANONICAL_LOCATION) {
62259d709d503bab6e2b61931737e662dd293b40578ccornelius                    const UChar *region = TimeZone::getRegion(id, ec);
62359d709d503bab6e2b61931737e662dd293b40578ccornelius                    if (U_FAILURE(ec)) {
62459d709d503bab6e2b61931737e662dd293b40578ccornelius                        break;
62559d709d503bab6e2b61931737e662dd293b40578ccornelius                    }
62659d709d503bab6e2b61931737e662dd293b40578ccornelius                    if (u_strcmp(region, WORLD) == 0) {
62759d709d503bab6e2b61931737e662dd293b40578ccornelius                       // exclude non-location ("001")
62859d709d503bab6e2b61931737e662dd293b40578ccornelius                        continue;
62959d709d503bab6e2b61931737e662dd293b40578ccornelius                    }
63059d709d503bab6e2b61931737e662dd293b40578ccornelius                }
63159d709d503bab6e2b61931737e662dd293b40578ccornelius                m[numEntries++] = i;
63259d709d503bab6e2b61931737e662dd293b40578ccornelius            }
63359d709d503bab6e2b61931737e662dd293b40578ccornelius            if (U_SUCCESS(ec)) {
63459d709d503bab6e2b61931737e662dd293b40578ccornelius                int32_t *tmp = m;
63559d709d503bab6e2b61931737e662dd293b40578ccornelius                m = (int32_t *)uprv_realloc(tmp, numEntries * sizeof(int32_t));
63659d709d503bab6e2b61931737e662dd293b40578ccornelius                if (m == NULL) {
63759d709d503bab6e2b61931737e662dd293b40578ccornelius                    // realloc failed.. use the original one even it has unused
63859d709d503bab6e2b61931737e662dd293b40578ccornelius                    // area at the end
63959d709d503bab6e2b61931737e662dd293b40578ccornelius                    m = tmp;
64059d709d503bab6e2b61931737e662dd293b40578ccornelius                }
64159d709d503bab6e2b61931737e662dd293b40578ccornelius
64259d709d503bab6e2b61931737e662dd293b40578ccornelius                switch(type) {
64359d709d503bab6e2b61931737e662dd293b40578ccornelius                case UCAL_ZONE_TYPE_ANY:
64459d709d503bab6e2b61931737e662dd293b40578ccornelius                    U_ASSERT(MAP_SYSTEM_ZONES == NULL);
64559d709d503bab6e2b61931737e662dd293b40578ccornelius                    MAP_SYSTEM_ZONES = m;
64659d709d503bab6e2b61931737e662dd293b40578ccornelius                    LEN_SYSTEM_ZONES = numEntries;
64759d709d503bab6e2b61931737e662dd293b40578ccornelius                    break;
64859d709d503bab6e2b61931737e662dd293b40578ccornelius                case UCAL_ZONE_TYPE_CANONICAL:
64959d709d503bab6e2b61931737e662dd293b40578ccornelius                    U_ASSERT(MAP_CANONICAL_SYSTEM_ZONES == NULL);
65059d709d503bab6e2b61931737e662dd293b40578ccornelius                    MAP_CANONICAL_SYSTEM_ZONES = m;
65159d709d503bab6e2b61931737e662dd293b40578ccornelius                    LEN_CANONICAL_SYSTEM_ZONES = numEntries;
65259d709d503bab6e2b61931737e662dd293b40578ccornelius                    break;
65359d709d503bab6e2b61931737e662dd293b40578ccornelius                case UCAL_ZONE_TYPE_CANONICAL_LOCATION:
65459d709d503bab6e2b61931737e662dd293b40578ccornelius                    U_ASSERT(MAP_CANONICAL_SYSTEM_LOCATION_ZONES == NULL);
65559d709d503bab6e2b61931737e662dd293b40578ccornelius                    MAP_CANONICAL_SYSTEM_LOCATION_ZONES = m;
65659d709d503bab6e2b61931737e662dd293b40578ccornelius                    LEN_CANONICAL_SYSTEM_LOCATION_ZONES = numEntries;
65759d709d503bab6e2b61931737e662dd293b40578ccornelius                    break;
65859d709d503bab6e2b61931737e662dd293b40578ccornelius                }
65959d709d503bab6e2b61931737e662dd293b40578ccornelius            }
66059d709d503bab6e2b61931737e662dd293b40578ccornelius        }
66159d709d503bab6e2b61931737e662dd293b40578ccornelius    }
66259d709d503bab6e2b61931737e662dd293b40578ccornelius    ures_close(res);
66359d709d503bab6e2b61931737e662dd293b40578ccornelius}
66459d709d503bab6e2b61931737e662dd293b40578ccornelius
66559d709d503bab6e2b61931737e662dd293b40578ccornelius
666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * This is the default implementation for subclasses that do not
668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * override this method.  This implementation calls through to the
669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * 8-argument getOffset() method after suitable computations, and
670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * correctly adjusts GMT millis to local millis when necessary.
671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid TimeZone::getOffset(UDate date, UBool local, int32_t& rawOffset,
673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         int32_t& dstOffset, UErrorCode& ec) const {
674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(ec)) {
675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    rawOffset = getRawOffset();
679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (!local) {
680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        date += rawOffset; // now in local standard millis
681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // When local == TRUE, date might not be in local standard
684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // millis.  getOffset taking 7 parameters used here assume
685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // the given time in day is local standard time.
686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // At STD->DST transition, there is a range of time which
687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // does not exist.  When 'date' is in this time range
688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // (and local == TRUE), this method interprets the specified
689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // local time as DST.  At DST->STD transition, there is a
690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // range of time which occurs twice.  In this case, this
691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // method interprets the specified local time as STD.
692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // To support the behavior above, we need to call getOffset
693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // (with 7 args) twice when local == true and DST is
694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // detected in the initial call.
695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (int32_t pass=0; ; ++pass) {
696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t year, month, dom, dow;
697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        double day = uprv_floor(date / U_MILLIS_PER_DAY);
698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t millis = (int32_t) (date - day * U_MILLIS_PER_DAY);
699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Grego::dayToFields(day, year, month, dom, dow);
701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        dstOffset = getOffset(GregorianCalendar::AD, year, month, dom,
703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                              (uint8_t) dow, millis,
704b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                              Grego::monthLength(year, month),
705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                              ec) - rawOffset;
706b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Recompute if local==TRUE, dstOffset!=0.
708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (pass!=0 || !local || dstOffset == 0) {
709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
710b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
711b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // adjust to local standard millis
712b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        date -= dstOffset;
713b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
714b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
715b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// New available IDs API as of ICU 2.4.  Uses StringEnumeration API.
719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass TZEnumeration : public StringEnumeration {
721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruprivate:
722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Map into to zones.  Our results are zone[map[i]] for
724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // i=0..len-1, where zone[i] is the i-th Olson zone.  If map==NULL
725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // then our results are zone[i] for i=0..len-1.  Len will be zero
726b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // if the zone data could not be loaded.
727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t* map;
728b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t* localMap;
729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t  len;
730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t  pos;
731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
732b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TZEnumeration(int32_t* mapData, int32_t mapLen, UBool adoptMapData) : pos(0) {
733b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        map = mapData;
734b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        localMap = adoptMapData ? mapData : NULL;
735b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        len = mapLen;
736b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
737b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
738b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool getID(int32_t i) {
739b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UErrorCode ec = U_ZERO_ERROR;
740b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t idLen = 0;
741b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const UChar* id = NULL;
742b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UResourceBundle *top = ures_openDirect(0, kZONEINFO, &ec);
743b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        top = ures_getByKey(top, kNAMES, top, &ec); // dereference Zones section
744b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        id = ures_getStringByIndex(top, i, &idLen, &ec);
745b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(U_FAILURE(ec)) {
746b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            unistr.truncate(0);
747b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
748b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else {
749b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            unistr.fastCopyFrom(UnicodeString(TRUE, id, idLen));
750b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
751b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ures_close(top);
752b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return U_SUCCESS(ec);
753b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
754b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
755b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    static int32_t* getMap(USystemTimeZoneType type, int32_t& len, UErrorCode& ec) {
756b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        len = 0;
757b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_FAILURE(ec)) {
758b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return NULL;
759b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
760b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t* m = NULL;
761b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        switch (type) {
762b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        case UCAL_ZONE_TYPE_ANY:
76359d709d503bab6e2b61931737e662dd293b40578ccornelius            umtx_initOnce(gSystemZonesInitOnce, &initMap, type, ec);
764b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            m = MAP_SYSTEM_ZONES;
765b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            len = LEN_SYSTEM_ZONES;
766b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
767b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        case UCAL_ZONE_TYPE_CANONICAL:
76859d709d503bab6e2b61931737e662dd293b40578ccornelius            umtx_initOnce(gCanonicalZonesInitOnce, &initMap, type, ec);
769b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            m = MAP_CANONICAL_SYSTEM_ZONES;
770b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            len = LEN_CANONICAL_SYSTEM_ZONES;
771b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
772b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        case UCAL_ZONE_TYPE_CANONICAL_LOCATION:
77359d709d503bab6e2b61931737e662dd293b40578ccornelius            umtx_initOnce(gCanonicalLocationZonesInitOnce, &initMap, type, ec);
774b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            m = MAP_CANONICAL_SYSTEM_LOCATION_ZONES;
775b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            len = LEN_CANONICAL_SYSTEM_LOCATION_ZONES;
776b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
77759d709d503bab6e2b61931737e662dd293b40578ccornelius        default:
77859d709d503bab6e2b61931737e662dd293b40578ccornelius            ec = U_ILLEGAL_ARGUMENT_ERROR;
77959d709d503bab6e2b61931737e662dd293b40578ccornelius            m = NULL;
78059d709d503bab6e2b61931737e662dd293b40578ccornelius            len = 0;
78159d709d503bab6e2b61931737e662dd293b40578ccornelius            break;
782b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
783b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return m;
784b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
785b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
786b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehopublic:
787b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
788b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#define DEFAULT_FILTERED_MAP_SIZE 8
789b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#define MAP_INCREMENT_SIZE 8
790b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
791b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    static TZEnumeration* create(USystemTimeZoneType type, const char* region, const int32_t* rawOffset, UErrorCode& ec) {
792b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_FAILURE(ec)) {
793b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return NULL;
794b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
795b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
796b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t baseLen;
797b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t *baseMap = getMap(type, baseLen, ec);
798b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
799b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_FAILURE(ec)) {
800b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return NULL;
801b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
802b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
803b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // If any additional conditions are available,
804b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // create instance local map filtered by the conditions.
805b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
806b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t *filteredMap = NULL;
807b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t numEntries = 0;
808b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
809b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (region != NULL || rawOffset != NULL) {
810b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            int32_t filteredMapSize = DEFAULT_FILTERED_MAP_SIZE;
811b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            filteredMap = (int32_t *)uprv_malloc(filteredMapSize * sizeof(int32_t));
812b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (filteredMap == NULL) {
813b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                ec = U_MEMORY_ALLOCATION_ERROR;
814b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return NULL;
81550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            }
81650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
817b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Walk through the base map
818b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            UResourceBundle *res = ures_openDirect(0, kZONEINFO, &ec);
819b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            res = ures_getByKey(res, kNAMES, res, &ec); // dereference Zones section
820b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            for (int32_t i = 0; i < baseLen; i++) {
821b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                int32_t zidx = baseMap[i];
822103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                UnicodeString id = ures_getUnicodeStringByIndex(res, zidx, &ec);
82350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                if (U_FAILURE(ec)) {
82450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    break;
82550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                }
826b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (region != NULL) {
827b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    // Filter by region
828b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    char tzregion[4]; // max 3 letters + null term
829b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    TimeZone::getRegion(id, tzregion, sizeof(tzregion), ec);
830b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (U_FAILURE(ec)) {
831b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        break;
832b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    }
833b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (uprv_stricmp(tzregion, region) != 0) {
834b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        // region does not match
835b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        continue;
836b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    }
83750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                }
838b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (rawOffset != NULL) {
839b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    // Filter by raw offset
840b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    // Note: This is VERY inefficient
84159d709d503bab6e2b61931737e662dd293b40578ccornelius                    TimeZone *z = createSystemTimeZone(id, ec);
842b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (U_FAILURE(ec)) {
843b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        break;
844b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    }
845b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    int32_t tzoffset = z->getRawOffset();
846b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    delete z;
84750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
848b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (tzoffset != *rawOffset) {
849b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        continue;
85050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    }
851b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
852b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
853b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (filteredMapSize <= numEntries) {
854b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    filteredMapSize += MAP_INCREMENT_SIZE;
855b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    int32_t *tmp = (int32_t *)uprv_realloc(filteredMap, filteredMapSize * sizeof(int32_t));
856b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (tmp == NULL) {
857b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        ec = U_MEMORY_ALLOCATION_ERROR;
858b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        break;
85950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    } else {
860b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        filteredMap = tmp;
861b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
862b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
863b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
864b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                filteredMap[numEntries++] = zidx;
865b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
866b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
867b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (U_FAILURE(ec)) {
868b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                uprv_free(filteredMap);
869b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                filteredMap = NULL;
870b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
871b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
872b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            ures_close(res);
873b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
874b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
875b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        TZEnumeration *result = NULL;
876b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_SUCCESS(ec)) {
877b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Finally, create a new enumeration instance
878b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (filteredMap == NULL) {
879b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                result = new TZEnumeration(baseMap, baseLen, FALSE);
880b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
881b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                result = new TZEnumeration(filteredMap, numEntries, TRUE);
882b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                filteredMap = NULL;
883b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
884b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (result == NULL) {
885b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                ec = U_MEMORY_ALLOCATION_ERROR;
886b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
887b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
888b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
889b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (filteredMap != NULL) {
890b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            uprv_free(filteredMap);
891b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
892b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
893b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return result;
894b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
895b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
896b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TZEnumeration(const TZEnumeration &other) : StringEnumeration(), map(NULL), localMap(NULL), len(0), pos(0) {
897b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (other.localMap != NULL) {
898b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            localMap = (int32_t *)uprv_malloc(other.len * sizeof(int32_t));
899b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (localMap != NULL) {
900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                len = other.len;
901b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                uprv_memcpy(localMap, other.localMap, len * sizeof(int32_t));
902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pos = other.pos;
903b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                map = localMap;
904b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else {
905b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                len = 0;
906b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                pos = 0;
907b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                map = NULL;
908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
909b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else {
910b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            map = other.map;
911b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            localMap = NULL;
912b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            len = other.len;
913b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            pos = other.pos;
914b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
915b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
916b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
917103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    virtual ~TZEnumeration();
918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    virtual StringEnumeration *clone() const {
920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return new TZEnumeration(*this);
921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
923b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    virtual int32_t count(UErrorCode& status) const {
924b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return U_FAILURE(status) ? 0 : len;
925b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
926b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
927b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    virtual const UnicodeString* snext(UErrorCode& status) {
928b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_SUCCESS(status) && map != NULL && pos < len) {
929b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            getID(map[pos]);
930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ++pos;
931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return &unistr;
932b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
933b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
934b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
935b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
936b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    virtual void reset(UErrorCode& /*status*/) {
937b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pos = 0;
938b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
939b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
940b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querupublic:
941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    static UClassID U_EXPORT2 getStaticClassID(void);
942b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    virtual UClassID getDynamicClassID(void) const;
943b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
944b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
945103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTZEnumeration::~TZEnumeration() {
946103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (localMap != NULL) {
947103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        uprv_free(localMap);
948103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    }
949103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
950103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUOBJECT_DEFINE_RTTI_IMPLEMENTATION(TZEnumeration)
952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruStringEnumeration* U_EXPORT2
954b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZone::createTimeZoneIDEnumeration(
955b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            USystemTimeZoneType zoneType,
956b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            const char* region,
957b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            const int32_t* rawOffset,
958b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            UErrorCode& ec) {
959b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return TZEnumeration::create(zoneType, region, rawOffset, ec);
960b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
961b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
962b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoStringEnumeration* U_EXPORT2
963b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::createEnumeration() {
964b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode ec = U_ZERO_ERROR;
965b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return TZEnumeration::create(UCAL_ZONE_TYPE_ANY, NULL, NULL, ec);
966b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruStringEnumeration* U_EXPORT2
969b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::createEnumeration(int32_t rawOffset) {
970b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode ec = U_ZERO_ERROR;
971b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return TZEnumeration::create(UCAL_ZONE_TYPE_ANY, NULL, &rawOffset, ec);
972b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
973b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruStringEnumeration* U_EXPORT2
975b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::createEnumeration(const char* country) {
976b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode ec = U_ZERO_ERROR;
977b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return TZEnumeration::create(UCAL_ZONE_TYPE_ANY, country, NULL, ec);
978b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
979b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
980b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ---------------------------------------
981b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t U_EXPORT2
983b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::countEquivalentIDs(const UnicodeString& id) {
984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t result = 0;
985b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode ec = U_ZERO_ERROR;
986b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UResourceBundle res;
987b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_initStackObject(&res);
988b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_DEBUG_TZ_MSG(("countEquivalentIDs..\n"));
989b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UResourceBundle *top = openOlsonResource(id, res, ec);
990b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_SUCCESS(ec)) {
99150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        UResourceBundle r;
99250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        ures_initStackObject(&r);
99350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        ures_getByKey(&res, kLINKS, &r, &ec);
99450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        ures_getIntVector(&r, &result, &ec);
99550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        ures_close(&r);
996b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
997b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_close(&res);
998b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_close(top);
999b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
1000b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1001b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1002b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ---------------------------------------
1003b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1004b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst UnicodeString U_EXPORT2
1005b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::getEquivalentID(const UnicodeString& id, int32_t index) {
1006b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_DEBUG_TZ_MSG(("gEI(%d)\n", index));
1007b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString result;
1008b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode ec = U_ZERO_ERROR;
1009b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UResourceBundle res;
1010b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_initStackObject(&res);
1011b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UResourceBundle *top = openOlsonResource(id, res, ec);
1012b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t zone = -1;
1013b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_SUCCESS(ec)) {
101450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        UResourceBundle r;
101550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        ures_initStackObject(&r);
101650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        int32_t size;
101750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        ures_getByKey(&res, kLINKS, &r, &ec);
101850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        const int32_t* v = ures_getIntVector(&r, &size, &ec);
101950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if (U_SUCCESS(ec)) {
1020b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (index >= 0 && index < size) {
1021b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                zone = v[index];
1022b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1023b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
102450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        ures_close(&r);
1025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1026b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_close(&res);
1027b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (zone >= 0) {
1028b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UResourceBundle *ares = ures_getByKey(top, kNAMES, NULL, &ec); // dereference Zones section
1029b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_SUCCESS(ec)) {
1030b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t idLen = 0;
1031b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            const UChar* id = ures_getStringByIndex(ares, zone, &idLen, &ec);
1032b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            result.fastCopyFrom(UnicodeString(TRUE, id, idLen));
1033b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            U_DEBUG_TZ_MSG(("gei(%d) -> %d, len%d, %s\n", index, zone, result.length(), u_errorName(ec)));
1034b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1035b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ures_close(ares);
1036b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1037b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_close(top);
1038b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined(U_DEBUG_TZ)
1039b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(result.length() ==0) {
1040b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      U_DEBUG_TZ_MSG(("equiv [__, #%d] -> 0 (%s)\n", index, u_errorName(ec)));
1041b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1042b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
1043b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
1044b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1045b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1046b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ---------------------------------------
1047b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1048b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// These methods are used by ZoneMeta class only.
1049b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1050b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UChar*
1051b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZone::findID(const UnicodeString& id) {
1052b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar *result = NULL;
1053b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode ec = U_ZERO_ERROR;
1054b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UResourceBundle *rb = ures_openDirect(NULL, kZONEINFO, &ec);
1055b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1056b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // resolve zone index by name
1057b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UResourceBundle *names = ures_getByKey(rb, kNAMES, NULL, &ec);
1058b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t idx = findInStringArray(names, id, ec);
1059b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    result = ures_getStringByIndex(names, idx, NULL, &ec);
1060b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(ec)) {
1061b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        result = NULL;
1062b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1063b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ures_close(names);
1064b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ures_close(rb);
1065b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return result;
1066b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1067b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
106850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
106950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoconst UChar*
107050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoTimeZone::dereferOlsonLink(const UnicodeString& id) {
107150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    const UChar *result = NULL;
1072b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode ec = U_ZERO_ERROR;
107350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    UResourceBundle *rb = ures_openDirect(NULL, kZONEINFO, &ec);
107450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
107550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    // resolve zone index by name
107650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    UResourceBundle *names = ures_getByKey(rb, kNAMES, NULL, &ec);
107750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t idx = findInStringArray(names, id, ec);
107850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    result = ures_getStringByIndex(names, idx, NULL, &ec);
107950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
108050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    // open the zone bundle by index
108150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    ures_getByKey(rb, kZONES, rb, &ec);
108250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    ures_getByIndex(rb, idx, rb, &ec);
108350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
1084b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_SUCCESS(ec)) {
108550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if (ures_getType(rb) == URES_INT) {
108650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            // this is a link - dereference the link
108750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            int32_t deref = ures_getInt(rb, &ec);
108850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            const UChar* tmp = ures_getStringByIndex(names, deref, NULL, &ec);
1089b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (U_SUCCESS(ec)) {
109050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                result = tmp;
1091b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1092b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1093b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
109450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
109550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    ures_close(names);
109650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    ures_close(rb);
109750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
109850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    return result;
109950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
110050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
110150294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoconst UChar*
110250294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoTimeZone::getRegion(const UnicodeString& id) {
1103b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode status = U_ZERO_ERROR;
1104b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return getRegion(id, status);
1105b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1106b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1107b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UChar*
1108b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZone::getRegion(const UnicodeString& id, UErrorCode& status) {
1109b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
1110b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
1111b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1112b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar *result = NULL;
1113b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UResourceBundle *rb = ures_openDirect(NULL, kZONEINFO, &status);
111450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
111550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    // resolve zone index by name
1116b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UResourceBundle *res = ures_getByKey(rb, kNAMES, NULL, &status);
1117b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t idx = findInStringArray(res, id, status);
111850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
111950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    // get region mapping
1120b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ures_getByKey(rb, kREGIONS, res, &status);
1121b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar *tmp = ures_getStringByIndex(res, idx, NULL, &status);
1122b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_SUCCESS(status)) {
112350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        result = tmp;
112450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
112550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
1126b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_close(res);
112750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    ures_close(rb);
112850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
112950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    return result;
1130b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1131b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1132b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1133b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------
1134b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoint32_t
1135b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZone::getRegion(const UnicodeString& id, char *region, int32_t capacity, UErrorCode& status)
1136b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho{
1137b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t resultLen = 0;
1138b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    *region = 0;
1139b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
1140b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return 0;
1141b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1142b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1143b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar *uregion = NULL;
1144b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // "Etc/Unknown" is not a system zone ID,
1145b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // but in the zone data
1146b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (id.compare(UNKNOWN_ZONE_ID, UNKNOWN_ZONE_ID_LENGTH) != 0) {
1147b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        uregion = getRegion(id);
1148b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1149b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (uregion == NULL) {
1150b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        status = U_ILLEGAL_ARGUMENT_ERROR;
1151b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return 0;
1152b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1153b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    resultLen = u_strlen(uregion);
1154b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // A region code is represented by invariant characters
1155b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    u_UCharsToChars(uregion, region, uprv_min(resultLen, capacity));
1156b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1157b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (capacity < resultLen) {
1158b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        status = U_BUFFER_OVERFLOW_ERROR;
1159b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return resultLen;
1160b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1161b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1162b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return u_terminateChars(region, capacity, resultLen, &status);
1163b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1164b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ---------------------------------------
1166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString&
1169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::getDisplayName(UnicodeString& result) const
1170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return getDisplayName(FALSE,LONG,Locale::getDefault(), result);
1172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString&
1175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::getDisplayName(const Locale& locale, UnicodeString& result) const
1176b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1177b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return getDisplayName(FALSE, LONG, locale, result);
1178b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1179b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1180b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString&
1181b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::getDisplayName(UBool daylight, EDisplayType style, UnicodeString& result)  const
1182b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1183b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return getDisplayName(daylight,style, Locale::getDefault(), result);
1184b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1185b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//--------------------------------------
1186b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoint32_t
1187b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::getDSTSavings()const {
1188b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (useDaylightTime()) {
1189b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 3600000;
1190b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1191b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return 0;
1192b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1193b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//---------------------------------------
1194b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString&
1195b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::getDisplayName(UBool daylight, EDisplayType style, const Locale& locale, UnicodeString& result) const
1196b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1197b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
1198103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    UDate date = Calendar::getNow();
1199103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    UTimeZoneFormatTimeType timeType;
1200103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    int32_t offset;
1201b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1202103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (style == GENERIC_LOCATION || style == LONG_GENERIC || style == SHORT_GENERIC) {
1203103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        LocalPointer<TimeZoneFormat> tzfmt(TimeZoneFormat::createInstance(locale, status));
1204c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (U_FAILURE(status)) {
1205103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            result.remove();
1206103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            return result;
1207c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1208103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        // Generic format
1209103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        switch (style) {
1210103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        case GENERIC_LOCATION:
1211103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            tzfmt->format(UTZFMT_STYLE_GENERIC_LOCATION, *this, date, result, &timeType);
1212103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            break;
1213103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        case LONG_GENERIC:
1214103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            tzfmt->format(UTZFMT_STYLE_GENERIC_LONG, *this, date, result, &timeType);
1215103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            break;
1216103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        case SHORT_GENERIC:
1217103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            tzfmt->format(UTZFMT_STYLE_GENERIC_SHORT, *this, date, result, &timeType);
1218103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            break;
1219103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        default:
1220103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            U_ASSERT(FALSE);
1221103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        }
1222103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        // Generic format many use Localized GMT as the final fallback.
1223103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        // When Localized GMT format is used, the result might not be
1224103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        // appropriate for the requested daylight value.
1225103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        if ((daylight && timeType == UTZFMT_TIME_TYPE_STANDARD) || (!daylight && timeType == UTZFMT_TIME_TYPE_DAYLIGHT)) {
1226103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            offset = daylight ? getRawOffset() + getDSTSavings() : getRawOffset();
12278393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            if (style == SHORT_GENERIC) {
12288393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                tzfmt->formatOffsetShortLocalizedGMT(offset, result, status);
12298393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            } else {
12308393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                tzfmt->formatOffsetLocalizedGMT(offset, result, status);
12318393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            }
1232c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1233103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    } else if (style == LONG_GMT || style == SHORT_GMT) {
1234103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        LocalPointer<TimeZoneFormat> tzfmt(TimeZoneFormat::createInstance(locale, status));
1235103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        if (U_FAILURE(status)) {
1236103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            result.remove();
1237103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            return result;
1238103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        }
1239103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        offset = daylight && useDaylightTime() ? getRawOffset() + getDSTSavings() : getRawOffset();
1240103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        switch (style) {
1241103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        case LONG_GMT:
1242103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            tzfmt->formatOffsetLocalizedGMT(offset, result, status);
1243103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            break;
1244103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        case SHORT_GMT:
12458393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            tzfmt->formatOffsetISO8601Basic(offset, FALSE, FALSE, FALSE, result, status);
1246103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            break;
1247103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        default:
1248103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            U_ASSERT(FALSE);
1249103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        }
1250103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
1251c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else {
1252103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        U_ASSERT(style == LONG || style == SHORT || style == SHORT_COMMONLY_USED);
1253103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        UTimeZoneNameType nameType = UTZNM_UNKNOWN;
1254103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        switch (style) {
1255103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        case LONG:
1256103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            nameType = daylight ? UTZNM_LONG_DAYLIGHT : UTZNM_LONG_STANDARD;
1257103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            break;
1258103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        case SHORT:
1259103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        case SHORT_COMMONLY_USED:
1260103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            nameType = daylight ? UTZNM_SHORT_DAYLIGHT : UTZNM_SHORT_STANDARD;
1261103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            break;
1262103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        default:
1263103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            U_ASSERT(FALSE);
1264103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        }
1265103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        LocalPointer<TimeZoneNames> tznames(TimeZoneNames::createInstance(locale, status));
1266103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        if (U_FAILURE(status)) {
1267103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            result.remove();
1268103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            return result;
1269103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        }
1270103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        UnicodeString canonicalID(ZoneMeta::getCanonicalCLDRID(*this));
1271103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        tznames->getDisplayName(canonicalID, nameType, date, result);
1272103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        if (result.isEmpty()) {
1273103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            // Fallback to localized GMT
1274103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            LocalPointer<TimeZoneFormat> tzfmt(TimeZoneFormat::createInstance(locale, status));
1275103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            offset = daylight && useDaylightTime() ? getRawOffset() + getDSTSavings() : getRawOffset();
12768393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            if (style == LONG) {
12778393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                tzfmt->formatOffsetLocalizedGMT(offset, result, status);
12788393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            } else {
12798393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                tzfmt->formatOffsetShortLocalizedGMT(offset, result, status);
12808393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            }
1281c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1282c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1283103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (U_FAILURE(status)) {
1284103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        result.remove();
1285103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    }
1286c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return  result;
1287b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1288b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1289b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
1290b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Parse a custom time zone identifier and return a corresponding zone.
1291b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param id a string of the form GMT[+-]hh:mm, GMT[+-]hhmm, or
1292b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * GMT[+-]hh.
1293b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @return a newly created SimpleTimeZone with the given offset and
1294b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * no Daylight Savings Time, or null if the id cannot be parsed.
1295b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
1296b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone*
1297b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::createCustomTimeZone(const UnicodeString& id)
1298b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1299c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t sign, hour, min, sec;
1300c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (parseCustomID(id, sign, hour, min, sec)) {
1301c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UnicodeString customID;
1302c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        formatCustomID(hour, min, sec, (sign < 0), customID);
1303c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        int32_t offset = sign * ((hour * 60 + min) * 60 + sec) * 1000;
1304c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return new SimpleTimeZone(offset, customID);
1305c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1306c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return NULL;
1307c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1308c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1309c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruUnicodeString&
1310c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruTimeZone::getCustomID(const UnicodeString& id, UnicodeString& normalized, UErrorCode& status) {
1311c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    normalized.remove();
1312c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (U_FAILURE(status)) {
1313c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return normalized;
1314c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1315c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t sign, hour, min, sec;
1316c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (parseCustomID(id, sign, hour, min, sec)) {
1317c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        formatCustomID(hour, min, sec, (sign < 0), normalized);
1318fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    } else {
1319fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        status = U_ILLEGAL_ARGUMENT_ERROR;
1320c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1321c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return normalized;
1322c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1323c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1324c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruUBool
1325c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruTimeZone::parseCustomID(const UnicodeString& id, int32_t& sign,
1326c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                        int32_t& hour, int32_t& min, int32_t& sec) {
1327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    static const int32_t         kParseFailed = -99999;
1328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    NumberFormat* numberFormat = 0;
1330b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString idUppercase = id;
1331103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    idUppercase.toUpper("");
1332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1333b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (id.length() > GMT_ID_LENGTH &&
1334103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        idUppercase.startsWith(GMT_ID, GMT_ID_LENGTH))
1335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ParsePosition pos(GMT_ID_LENGTH);
1337c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        sign = 1;
1338c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        hour = 0;
1339c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        min = 0;
1340c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        sec = 0;
1341c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1342c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (id[pos.getIndex()] == MINUS /*'-'*/) {
1343c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            sign = -1;
1344c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        } else if (id[pos.getIndex()] != PLUS /*'+'*/) {
1345c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return FALSE;
1346c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1347b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pos.setIndex(pos.getIndex() + 1);
1348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1349b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UErrorCode success = U_ZERO_ERROR;
1350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        numberFormat = NumberFormat::createInstance(success);
1351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(U_FAILURE(success)){
1352c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return FALSE;
1353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        numberFormat->setParseIntegerOnly(TRUE);
1355b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        //numberFormat->setLenient(TRUE); // TODO: May need to set this, depends on latest timezone parsing
1356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Look for either hh:mm, hhmm, or hh
1358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t start = pos.getIndex();
1359b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Formattable n(kParseFailed);
1360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        numberFormat->parse(id, n, pos);
1361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (pos.getIndex() == start) {
1362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            delete numberFormat;
1363c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return FALSE;
1364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1365b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        hour = n.getLong();
1366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (pos.getIndex() < id.length()) {
1368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (pos.getIndex() - start > 2
1369b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                || id[pos.getIndex()] != COLON) {
1370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                delete numberFormat;
1371c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                return FALSE;
1372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // hh:mm
1374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            pos.setIndex(pos.getIndex() + 1);
1375b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t oldPos = pos.getIndex();
1376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            n.setLong(kParseFailed);
1377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            numberFormat->parse(id, n, pos);
1378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if ((pos.getIndex() - oldPos) != 2) {
1379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // must be 2 digits
1380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                delete numberFormat;
1381c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                return FALSE;
1382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            min = n.getLong();
1384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (pos.getIndex() < id.length()) {
1385b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                if (id[pos.getIndex()] != COLON) {
1386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    delete numberFormat;
1387c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                    return FALSE;
1388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // [:ss]
1390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pos.setIndex(pos.getIndex() + 1);
1391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                oldPos = pos.getIndex();
1392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                n.setLong(kParseFailed);
1393b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                numberFormat->parse(id, n, pos);
1394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (pos.getIndex() != id.length()
1395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        || (pos.getIndex() - oldPos) != 2) {
1396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    delete numberFormat;
1397c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                    return FALSE;
1398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                sec = n.getLong();
1400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
1402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Supported formats are below -
1403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            //
1404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // HHmmss
1405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Hmmss
1406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // HHmm
1407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Hmm
1408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // HH
1409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // H
1410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t length = pos.getIndex() - start;
1412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (length <= 0 || 6 < length) {
1413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // invalid length
1414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                delete numberFormat;
1415c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                return FALSE;
1416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1417b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            switch (length) {
1418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                case 1:
1419b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                case 2:
1420b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // already set to hour
1421b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    break;
1422b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                case 3:
1423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                case 4:
1424b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    min = hour % 100;
1425b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    hour /= 100;
1426b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    break;
1427b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                case 5:
1428b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                case 6:
1429b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    sec = hour % 100;
1430b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    min = (hour/100) % 100;
1431b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    hour /= 10000;
1432b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    break;
1433b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1434b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1436b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete numberFormat;
1437b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1438b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (hour > kMAX_CUSTOM_HOUR || min > kMAX_CUSTOM_MIN || sec > kMAX_CUSTOM_SEC) {
1439c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return FALSE;
1440b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1441c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return TRUE;
1442c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1443c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return FALSE;
1444c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1446c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruUnicodeString&
1447c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruTimeZone::formatCustomID(int32_t hour, int32_t min, int32_t sec,
1448c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                         UBool negative, UnicodeString& id) {
1449c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // Create time zone ID - GMT[+|-]hhmm[ss]
1450103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    id.setTo(GMT_ID, GMT_ID_LENGTH);
1451c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (hour | min | sec) {
1452c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (negative) {
1453c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            id += (UChar)MINUS;
1454c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        } else {
1455c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            id += (UChar)PLUS;
1456c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1457b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1458c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (hour < 10) {
1459c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            id += (UChar)ZERO_DIGIT;
1460c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        } else {
1461c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            id += (UChar)(ZERO_DIGIT + hour/10);
1462c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1463c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        id += (UChar)(ZERO_DIGIT + hour%10);
1464b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        id += (UChar)COLON;
1465c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (min < 10) {
1466c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            id += (UChar)ZERO_DIGIT;
1467c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        } else {
1468c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            id += (UChar)(ZERO_DIGIT + min/10);
1469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1470c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        id += (UChar)(ZERO_DIGIT + min%10);
1471b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1472c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (sec) {
1473b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            id += (UChar)COLON;
1474c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            if (sec < 10) {
1475c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                id += (UChar)ZERO_DIGIT;
1476c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            } else {
1477c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                id += (UChar)(ZERO_DIGIT + sec/10);
1478c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
1479c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            id += (UChar)(ZERO_DIGIT + sec%10);
1480b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1482c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return id;
1483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1484b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1485b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1486b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUBool
1487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::hasSameRules(const TimeZone& other) const
1488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1489b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return (getRawOffset() == other.getRawOffset() &&
1490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            useDaylightTime() == other.useDaylightTime());
1491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
149359d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic void U_CALLCONV initTZDataVersion(UErrorCode &status) {
149459d709d503bab6e2b61931737e662dd293b40578ccornelius    ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
149559d709d503bab6e2b61931737e662dd293b40578ccornelius    int32_t len = 0;
149659d709d503bab6e2b61931737e662dd293b40578ccornelius    UResourceBundle *bundle = ures_openDirect(NULL, kZONEINFO, &status);
149759d709d503bab6e2b61931737e662dd293b40578ccornelius    const UChar *tzver = ures_getStringByKey(bundle, kTZVERSION, &len, &status);
1498b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
149959d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_SUCCESS(status)) {
150059d709d503bab6e2b61931737e662dd293b40578ccornelius        if (len >= (int32_t)sizeof(TZDATA_VERSION)) {
150159d709d503bab6e2b61931737e662dd293b40578ccornelius            // Ensure that there is always space for a trailing nul in TZDATA_VERSION
150259d709d503bab6e2b61931737e662dd293b40578ccornelius            len = sizeof(TZDATA_VERSION) - 1;
1503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
150459d709d503bab6e2b61931737e662dd293b40578ccornelius        u_UCharsToChars(tzver, TZDATA_VERSION, len);
1505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
150659d709d503bab6e2b61931737e662dd293b40578ccornelius    ures_close(bundle);
150759d709d503bab6e2b61931737e662dd293b40578ccornelius
150859d709d503bab6e2b61931737e662dd293b40578ccornelius}
150959d709d503bab6e2b61931737e662dd293b40578ccornelius
151059d709d503bab6e2b61931737e662dd293b40578ccorneliusconst char*
151159d709d503bab6e2b61931737e662dd293b40578ccorneliusTimeZone::getTZDataVersion(UErrorCode& status)
151259d709d503bab6e2b61931737e662dd293b40578ccornelius{
151359d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_initOnce(gTZDataVersionInitOnce, &initTZDataVersion, status);
1514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (const char*)TZDATA_VERSION;
1515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1517c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruUnicodeString&
1518c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruTimeZone::getCanonicalID(const UnicodeString& id, UnicodeString& canonicalID, UErrorCode& status)
1519c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru{
1520c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UBool isSystemID = FALSE;
1521c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return getCanonicalID(id, canonicalID, isSystemID, status);
1522c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1523c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1524c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruUnicodeString&
1525c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruTimeZone::getCanonicalID(const UnicodeString& id, UnicodeString& canonicalID, UBool& isSystemID,
1526c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                         UErrorCode& status)
1527c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru{
1528c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    canonicalID.remove();
1529c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    isSystemID = FALSE;
1530c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (U_FAILURE(status)) {
1531c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return canonicalID;
1532c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1533b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (id.compare(UNKNOWN_ZONE_ID, UNKNOWN_ZONE_ID_LENGTH) == 0) {
1534b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // special case - Etc/Unknown is a canonical ID, but not system ID
1535b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        canonicalID.fastCopyFrom(id);
1536b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        isSystemID = FALSE;
1537c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else {
1538b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ZoneMeta::getCanonicalCLDRID(id, canonicalID, status);
1539b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_SUCCESS(status)) {
1540b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            isSystemID = TRUE;
1541b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else {
1542b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Not a system ID
1543b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            status = U_ZERO_ERROR;
1544b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            getCustomID(id, canonicalID, status);
1545b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1546c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1547c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return canonicalID;
1548c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1549c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
155059d709d503bab6e2b61931737e662dd293b40578ccorneliusUnicodeString&
155159d709d503bab6e2b61931737e662dd293b40578ccorneliusTimeZone::getWindowsID(const UnicodeString& id, UnicodeString& winid, UErrorCode& status) {
155259d709d503bab6e2b61931737e662dd293b40578ccornelius    winid.remove();
155359d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_FAILURE(status)) {
155459d709d503bab6e2b61931737e662dd293b40578ccornelius        return winid;
155559d709d503bab6e2b61931737e662dd293b40578ccornelius    }
155659d709d503bab6e2b61931737e662dd293b40578ccornelius
155759d709d503bab6e2b61931737e662dd293b40578ccornelius    // canonicalize the input ID
155859d709d503bab6e2b61931737e662dd293b40578ccornelius    UnicodeString canonicalID;
155959d709d503bab6e2b61931737e662dd293b40578ccornelius    UBool isSystemID = FALSE;
156059d709d503bab6e2b61931737e662dd293b40578ccornelius
156159d709d503bab6e2b61931737e662dd293b40578ccornelius    getCanonicalID(id, canonicalID, isSystemID, status);
156259d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_FAILURE(status) || !isSystemID) {
156359d709d503bab6e2b61931737e662dd293b40578ccornelius        // mapping data is only applicable to tz database IDs
1564fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if (status == U_ILLEGAL_ARGUMENT_ERROR) {
1565fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // getWindowsID() sets an empty string where
1566fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // getCanonicalID() sets a U_ILLEGAL_ARGUMENT_ERROR.
1567fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            status = U_ZERO_ERROR;
1568fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
156959d709d503bab6e2b61931737e662dd293b40578ccornelius        return winid;
157059d709d503bab6e2b61931737e662dd293b40578ccornelius    }
157159d709d503bab6e2b61931737e662dd293b40578ccornelius
157259d709d503bab6e2b61931737e662dd293b40578ccornelius    UResourceBundle *mapTimezones = ures_openDirect(NULL, "windowsZones", &status);
157359d709d503bab6e2b61931737e662dd293b40578ccornelius    ures_getByKey(mapTimezones, "mapTimezones", mapTimezones, &status);
157459d709d503bab6e2b61931737e662dd293b40578ccornelius
157559d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_FAILURE(status)) {
157659d709d503bab6e2b61931737e662dd293b40578ccornelius        return winid;
157759d709d503bab6e2b61931737e662dd293b40578ccornelius    }
157859d709d503bab6e2b61931737e662dd293b40578ccornelius
157959d709d503bab6e2b61931737e662dd293b40578ccornelius    UResourceBundle *winzone = NULL;
158059d709d503bab6e2b61931737e662dd293b40578ccornelius    UBool found = FALSE;
158159d709d503bab6e2b61931737e662dd293b40578ccornelius    while (ures_hasNext(mapTimezones) && !found) {
158259d709d503bab6e2b61931737e662dd293b40578ccornelius        winzone = ures_getNextResource(mapTimezones, winzone, &status);
158359d709d503bab6e2b61931737e662dd293b40578ccornelius        if (U_FAILURE(status)) {
158459d709d503bab6e2b61931737e662dd293b40578ccornelius            break;
158559d709d503bab6e2b61931737e662dd293b40578ccornelius        }
158659d709d503bab6e2b61931737e662dd293b40578ccornelius        if (ures_getType(winzone) != URES_TABLE) {
158759d709d503bab6e2b61931737e662dd293b40578ccornelius            continue;
158859d709d503bab6e2b61931737e662dd293b40578ccornelius        }
158959d709d503bab6e2b61931737e662dd293b40578ccornelius        UResourceBundle *regionalData = NULL;
159059d709d503bab6e2b61931737e662dd293b40578ccornelius        while (ures_hasNext(winzone) && !found) {
159159d709d503bab6e2b61931737e662dd293b40578ccornelius            regionalData = ures_getNextResource(winzone, regionalData, &status);
159259d709d503bab6e2b61931737e662dd293b40578ccornelius            if (U_FAILURE(status)) {
159359d709d503bab6e2b61931737e662dd293b40578ccornelius                break;
159459d709d503bab6e2b61931737e662dd293b40578ccornelius            }
159559d709d503bab6e2b61931737e662dd293b40578ccornelius            if (ures_getType(regionalData) != URES_STRING) {
159659d709d503bab6e2b61931737e662dd293b40578ccornelius                continue;
159759d709d503bab6e2b61931737e662dd293b40578ccornelius            }
159859d709d503bab6e2b61931737e662dd293b40578ccornelius            int32_t len;
159959d709d503bab6e2b61931737e662dd293b40578ccornelius            const UChar *tzids = ures_getString(regionalData, &len, &status);
160059d709d503bab6e2b61931737e662dd293b40578ccornelius            if (U_FAILURE(status)) {
160159d709d503bab6e2b61931737e662dd293b40578ccornelius                break;
160259d709d503bab6e2b61931737e662dd293b40578ccornelius            }
160359d709d503bab6e2b61931737e662dd293b40578ccornelius
160459d709d503bab6e2b61931737e662dd293b40578ccornelius            const UChar *start = tzids;
160559d709d503bab6e2b61931737e662dd293b40578ccornelius            UBool hasNext = TRUE;
160659d709d503bab6e2b61931737e662dd293b40578ccornelius            while (hasNext) {
160759d709d503bab6e2b61931737e662dd293b40578ccornelius                const UChar *end = u_strchr(start, (UChar)0x20);
160859d709d503bab6e2b61931737e662dd293b40578ccornelius                if (end == NULL) {
160959d709d503bab6e2b61931737e662dd293b40578ccornelius                    end = tzids + len;
161059d709d503bab6e2b61931737e662dd293b40578ccornelius                    hasNext = FALSE;
161159d709d503bab6e2b61931737e662dd293b40578ccornelius                }
161259d709d503bab6e2b61931737e662dd293b40578ccornelius                if (canonicalID.compare(start, end - start) == 0) {
161359d709d503bab6e2b61931737e662dd293b40578ccornelius                    winid = UnicodeString(ures_getKey(winzone), -1 , US_INV);
161459d709d503bab6e2b61931737e662dd293b40578ccornelius                    found = TRUE;
161559d709d503bab6e2b61931737e662dd293b40578ccornelius                    break;
161659d709d503bab6e2b61931737e662dd293b40578ccornelius                }
161759d709d503bab6e2b61931737e662dd293b40578ccornelius                start = end + 1;
161859d709d503bab6e2b61931737e662dd293b40578ccornelius            }
161959d709d503bab6e2b61931737e662dd293b40578ccornelius        }
162059d709d503bab6e2b61931737e662dd293b40578ccornelius        ures_close(regionalData);
162159d709d503bab6e2b61931737e662dd293b40578ccornelius    }
162259d709d503bab6e2b61931737e662dd293b40578ccornelius    ures_close(winzone);
162359d709d503bab6e2b61931737e662dd293b40578ccornelius    ures_close(mapTimezones);
162459d709d503bab6e2b61931737e662dd293b40578ccornelius
162559d709d503bab6e2b61931737e662dd293b40578ccornelius    return winid;
162659d709d503bab6e2b61931737e662dd293b40578ccornelius}
162759d709d503bab6e2b61931737e662dd293b40578ccornelius
162859d709d503bab6e2b61931737e662dd293b40578ccornelius#define MAX_WINDOWS_ID_SIZE 128
162959d709d503bab6e2b61931737e662dd293b40578ccornelius
163059d709d503bab6e2b61931737e662dd293b40578ccorneliusUnicodeString&
163159d709d503bab6e2b61931737e662dd293b40578ccorneliusTimeZone::getIDForWindowsID(const UnicodeString& winid, const char* region, UnicodeString& id, UErrorCode& status) {
163259d709d503bab6e2b61931737e662dd293b40578ccornelius    id.remove();
163359d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_FAILURE(status)) {
163459d709d503bab6e2b61931737e662dd293b40578ccornelius        return id;
163559d709d503bab6e2b61931737e662dd293b40578ccornelius    }
163659d709d503bab6e2b61931737e662dd293b40578ccornelius
163759d709d503bab6e2b61931737e662dd293b40578ccornelius    UResourceBundle *zones = ures_openDirect(NULL, "windowsZones", &status);
163859d709d503bab6e2b61931737e662dd293b40578ccornelius    ures_getByKey(zones, "mapTimezones", zones, &status);
163959d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_FAILURE(status)) {
164059d709d503bab6e2b61931737e662dd293b40578ccornelius        ures_close(zones);
164159d709d503bab6e2b61931737e662dd293b40578ccornelius        return id;
164259d709d503bab6e2b61931737e662dd293b40578ccornelius    }
164359d709d503bab6e2b61931737e662dd293b40578ccornelius
164459d709d503bab6e2b61931737e662dd293b40578ccornelius    UErrorCode tmperr = U_ZERO_ERROR;
164559d709d503bab6e2b61931737e662dd293b40578ccornelius    char winidKey[MAX_WINDOWS_ID_SIZE];
164659d709d503bab6e2b61931737e662dd293b40578ccornelius    int32_t winKeyLen = winid.extract(0, winid.length(), winidKey, sizeof(winidKey) - 1, US_INV);
164759d709d503bab6e2b61931737e662dd293b40578ccornelius
164859d709d503bab6e2b61931737e662dd293b40578ccornelius    if (winKeyLen == 0 || winKeyLen >= (int32_t)sizeof(winidKey)) {
164959d709d503bab6e2b61931737e662dd293b40578ccornelius        ures_close(zones);
165059d709d503bab6e2b61931737e662dd293b40578ccornelius        return id;
165159d709d503bab6e2b61931737e662dd293b40578ccornelius    }
165259d709d503bab6e2b61931737e662dd293b40578ccornelius    winidKey[winKeyLen] = 0;
165359d709d503bab6e2b61931737e662dd293b40578ccornelius
165459d709d503bab6e2b61931737e662dd293b40578ccornelius    ures_getByKey(zones, winidKey, zones, &tmperr); // use tmperr, because windows mapping might not
165559d709d503bab6e2b61931737e662dd293b40578ccornelius                                                    // be avaiable by design
165659d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_FAILURE(tmperr)) {
165759d709d503bab6e2b61931737e662dd293b40578ccornelius        ures_close(zones);
165859d709d503bab6e2b61931737e662dd293b40578ccornelius        return id;
165959d709d503bab6e2b61931737e662dd293b40578ccornelius    }
166059d709d503bab6e2b61931737e662dd293b40578ccornelius
166159d709d503bab6e2b61931737e662dd293b40578ccornelius    const UChar *tzid = NULL;
166259d709d503bab6e2b61931737e662dd293b40578ccornelius    int32_t len = 0;
166359d709d503bab6e2b61931737e662dd293b40578ccornelius    UBool gotID = FALSE;
166459d709d503bab6e2b61931737e662dd293b40578ccornelius    if (region) {
166559d709d503bab6e2b61931737e662dd293b40578ccornelius        const UChar *tzids = ures_getStringByKey(zones, region, &len, &tmperr); // use tmperr, because
166659d709d503bab6e2b61931737e662dd293b40578ccornelius                                                                                // regional mapping is optional
166759d709d503bab6e2b61931737e662dd293b40578ccornelius        if (U_SUCCESS(tmperr)) {
166859d709d503bab6e2b61931737e662dd293b40578ccornelius            // first ID delimited by space is the defasult one
166959d709d503bab6e2b61931737e662dd293b40578ccornelius            const UChar *end = u_strchr(tzids, (UChar)0x20);
167059d709d503bab6e2b61931737e662dd293b40578ccornelius            if (end == NULL) {
167159d709d503bab6e2b61931737e662dd293b40578ccornelius                id.setTo(tzids, -1);
167259d709d503bab6e2b61931737e662dd293b40578ccornelius            } else {
167359d709d503bab6e2b61931737e662dd293b40578ccornelius                id.setTo(tzids, end - tzids);
167459d709d503bab6e2b61931737e662dd293b40578ccornelius            }
167559d709d503bab6e2b61931737e662dd293b40578ccornelius            gotID = TRUE;
167659d709d503bab6e2b61931737e662dd293b40578ccornelius        }
167759d709d503bab6e2b61931737e662dd293b40578ccornelius    }
167859d709d503bab6e2b61931737e662dd293b40578ccornelius
167959d709d503bab6e2b61931737e662dd293b40578ccornelius    if (!gotID) {
168059d709d503bab6e2b61931737e662dd293b40578ccornelius        tzid = ures_getStringByKey(zones, "001", &len, &status);    // using status, because "001" must be
168159d709d503bab6e2b61931737e662dd293b40578ccornelius                                                                // available at this point
168259d709d503bab6e2b61931737e662dd293b40578ccornelius        if (U_SUCCESS(status)) {
168359d709d503bab6e2b61931737e662dd293b40578ccornelius            id.setTo(tzid, len);
168459d709d503bab6e2b61931737e662dd293b40578ccornelius        }
168559d709d503bab6e2b61931737e662dd293b40578ccornelius    }
168659d709d503bab6e2b61931737e662dd293b40578ccornelius
168759d709d503bab6e2b61931737e662dd293b40578ccornelius    ures_close(zones);
168859d709d503bab6e2b61931737e662dd293b40578ccornelius    return id;
168959d709d503bab6e2b61931737e662dd293b40578ccornelius}
169059d709d503bab6e2b61931737e662dd293b40578ccornelius
169159d709d503bab6e2b61931737e662dd293b40578ccornelius
1692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_END
1693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_FORMATTING */
1695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//eof
1697