1b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/*
2b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*******************************************************************************
3fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* Copyright (C) 1997-2014, 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
43059d709d503bab6e2b61931737e662dd293b40578ccornelius    if (result == 0) {
43159d709d503bab6e2b61931737e662dd293b40578ccornelius        U_DEBUG_TZ_MSG(("failed to load system time zone with id - falling to custom"));
43259d709d503bab6e2b61931737e662dd293b40578ccornelius        result = createCustomTimeZone(ID);
43359d709d503bab6e2b61931737e662dd293b40578ccornelius    }
43459d709d503bab6e2b61931737e662dd293b40578ccornelius    if (result == 0) {
43559d709d503bab6e2b61931737e662dd293b40578ccornelius        U_DEBUG_TZ_MSG(("failed to load time zone with id - falling to Etc/Unknown(GMT)"));
43659d709d503bab6e2b61931737e662dd293b40578ccornelius        result = getUnknown().clone();
43759d709d503bab6e2b61931737e662dd293b40578ccornelius    }
43859d709d503bab6e2b61931737e662dd293b40578ccornelius    return result;
43959d709d503bab6e2b61931737e662dd293b40578ccornelius}
44059d709d503bab6e2b61931737e662dd293b40578ccornelius
441b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
442b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
443b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
44459d709d503bab6e2b61931737e662dd293b40578ccornelius * Initialize DEFAULT_ZONE from the system default time zone.
445b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Upon return, DEFAULT_ZONE will not be NULL, unless operator new()
446b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * returns NULL.
447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
44859d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic void U_CALLCONV initDefault()
449b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho{
45059d709d503bab6e2b61931737e662dd293b40578ccornelius    ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
45159d709d503bab6e2b61931737e662dd293b40578ccornelius
45259d709d503bab6e2b61931737e662dd293b40578ccornelius    // If setDefault() has already been called we can skip getting the
45359d709d503bab6e2b61931737e662dd293b40578ccornelius    // default zone information from the system.
45459d709d503bab6e2b61931737e662dd293b40578ccornelius    if (DEFAULT_ZONE != NULL) {
45559d709d503bab6e2b61931737e662dd293b40578ccornelius        return;
45659d709d503bab6e2b61931737e662dd293b40578ccornelius    }
45759d709d503bab6e2b61931737e662dd293b40578ccornelius
458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // We access system timezone data through TPlatformUtilities,
459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // including tzset(), timezone, and tzname[].
460b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t rawOffset = 0;
461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    const char *hostID;
462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // First, try to create a system timezone, based
464b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // on the string ID in tzname[0].
465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
46659d709d503bab6e2b61931737e662dd293b40578ccornelius    // NOTE:  this code is safely single threaded, being only
46759d709d503bab6e2b61931737e662dd293b40578ccornelius    // run via umtx_initOnce().
46859d709d503bab6e2b61931737e662dd293b40578ccornelius    //
46959d709d503bab6e2b61931737e662dd293b40578ccornelius    // Some of the locale/timezone OS functions may not be thread safe,
47059d709d503bab6e2b61931737e662dd293b40578ccornelius    //
47159d709d503bab6e2b61931737e662dd293b40578ccornelius    // The operating system might actually use ICU to implement timezones.
47259d709d503bab6e2b61931737e662dd293b40578ccornelius    // So we may have ICU calling ICU here, like on AIX.
47359d709d503bab6e2b61931737e662dd293b40578ccornelius    // There shouldn't be a problem with this; initOnce does not hold a mutex
47459d709d503bab6e2b61931737e662dd293b40578ccornelius    // while the init function is being run.
475b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
47659d709d503bab6e2b61931737e662dd293b40578ccornelius    uprv_tzset(); // Initialize tz... system data
477b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
47859d709d503bab6e2b61931737e662dd293b40578ccornelius    // Get the timezone ID from the host.  This function should do
47959d709d503bab6e2b61931737e662dd293b40578ccornelius    // any required host-specific remapping; e.g., on Windows this
48059d709d503bab6e2b61931737e662dd293b40578ccornelius    // function maps the Date and Time control panel setting to an
48159d709d503bab6e2b61931737e662dd293b40578ccornelius    // ICU timezone ID.
48259d709d503bab6e2b61931737e662dd293b40578ccornelius    hostID = uprv_tzname(0);
483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
48459d709d503bab6e2b61931737e662dd293b40578ccornelius    // Invert sign because UNIX semantics are backwards
48559d709d503bab6e2b61931737e662dd293b40578ccornelius    rawOffset = uprv_timezone() * -U_MILLIS_PER_SECOND;
486b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
487b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    TimeZone* default_zone = NULL;
488b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
489b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    /* Make sure that the string is NULL terminated to prevent BoundsChecker/Purify warnings. */
490b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString hostStrID(hostID, -1, US_INV);
491b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    hostStrID.append((UChar)0);
492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    hostStrID.truncate(hostStrID.length()-1);
493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    default_zone = createSystemTimeZone(hostStrID);
494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
495103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius#if U_PLATFORM_USES_ONLY_WIN32_API
49650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    // hostID points to a heap-allocated location on Windows.
49750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    uprv_free(const_cast<char *>(hostID));
49850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#endif
49950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
500b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t hostIDLen = hostStrID.length();
501b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (default_zone != NULL && rawOffset != default_zone->getRawOffset()
502b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        && (3 <= hostIDLen && hostIDLen <= 4))
503b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
504b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Uh oh. This probably wasn't a good id.
505b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // It was probably an ambiguous abbreviation
506b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete default_zone;
507b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        default_zone = NULL;
508b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
509b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
510b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Construct a fixed standard zone with the host's ID
511b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // and raw offset.
512b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (default_zone == NULL) {
513b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        default_zone = new SimpleTimeZone(rawOffset, hostStrID);
514b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
515b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
516b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // If we _still_ don't have a time zone, use GMT.
517b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (default_zone == NULL) {
51859d709d503bab6e2b61931737e662dd293b40578ccornelius        const TimeZone* temptz = TimeZone::getGMT();
519c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        // If we can't use GMT, get out.
520c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (temptz == NULL) {
521c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return;
522c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
523c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        default_zone = temptz->clone();
524b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
525b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
52659d709d503bab6e2b61931737e662dd293b40578ccornelius    // The only way for DEFAULT_ZONE to be non-null at this point is if the user
52759d709d503bab6e2b61931737e662dd293b40578ccornelius    // made a thread-unsafe call to setDefault() or adoptDefault() in another
52859d709d503bab6e2b61931737e662dd293b40578ccornelius    // thread while this thread was doing something that required getting the default.
52959d709d503bab6e2b61931737e662dd293b40578ccornelius    U_ASSERT(DEFAULT_ZONE == NULL);
530b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
53159d709d503bab6e2b61931737e662dd293b40578ccornelius    DEFAULT_ZONE = default_zone;
532b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
533b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
534b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
535b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
536b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone* U_EXPORT2
537b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::createDefault()
538b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
53959d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_initOnce(gDefaultZoneInitOnce, initDefault);
540b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (DEFAULT_ZONE != NULL) ? DEFAULT_ZONE->clone() : NULL;
541b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
542b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
543b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
544b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
545b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid U_EXPORT2
546b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::adoptDefault(TimeZone* zone)
547b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
548b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (zone != NULL)
549b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
55059d709d503bab6e2b61931737e662dd293b40578ccornelius        TimeZone *old = DEFAULT_ZONE;
551b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        DEFAULT_ZONE = zone;
552b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete old;
553b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
554b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
555b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
556b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
557b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
558b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid U_EXPORT2
559b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::setDefault(const TimeZone& zone)
560b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
561b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    adoptDefault(zone.clone());
562b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
563b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
564b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//----------------------------------------------------------------------
565b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
56659d709d503bab6e2b61931737e662dd293b40578ccornelius
56759d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic void U_CALLCONV initMap(USystemTimeZoneType type, UErrorCode& ec) {
56859d709d503bab6e2b61931737e662dd293b40578ccornelius    ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
56959d709d503bab6e2b61931737e662dd293b40578ccornelius
57059d709d503bab6e2b61931737e662dd293b40578ccornelius    UResourceBundle *res = ures_openDirect(0, kZONEINFO, &ec);
57159d709d503bab6e2b61931737e662dd293b40578ccornelius    res = ures_getByKey(res, kNAMES, res, &ec); // dereference Zones section
57259d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_SUCCESS(ec)) {
57359d709d503bab6e2b61931737e662dd293b40578ccornelius        int32_t size = ures_getSize(res);
57459d709d503bab6e2b61931737e662dd293b40578ccornelius        int32_t *m = (int32_t *)uprv_malloc(size * sizeof(int32_t));
57559d709d503bab6e2b61931737e662dd293b40578ccornelius        if (m == NULL) {
57659d709d503bab6e2b61931737e662dd293b40578ccornelius            ec = U_MEMORY_ALLOCATION_ERROR;
57759d709d503bab6e2b61931737e662dd293b40578ccornelius        } else {
57859d709d503bab6e2b61931737e662dd293b40578ccornelius            int32_t numEntries = 0;
57959d709d503bab6e2b61931737e662dd293b40578ccornelius            for (int32_t i = 0; i < size; i++) {
58059d709d503bab6e2b61931737e662dd293b40578ccornelius                UnicodeString id = ures_getUnicodeStringByIndex(res, i, &ec);
58159d709d503bab6e2b61931737e662dd293b40578ccornelius                if (U_FAILURE(ec)) {
58259d709d503bab6e2b61931737e662dd293b40578ccornelius                    break;
58359d709d503bab6e2b61931737e662dd293b40578ccornelius                }
58459d709d503bab6e2b61931737e662dd293b40578ccornelius                if (0 == id.compare(UNKNOWN_ZONE_ID, UNKNOWN_ZONE_ID_LENGTH)) {
58559d709d503bab6e2b61931737e662dd293b40578ccornelius                    // exclude Etc/Unknown
58659d709d503bab6e2b61931737e662dd293b40578ccornelius                    continue;
58759d709d503bab6e2b61931737e662dd293b40578ccornelius                }
58859d709d503bab6e2b61931737e662dd293b40578ccornelius                if (type == UCAL_ZONE_TYPE_CANONICAL || type == UCAL_ZONE_TYPE_CANONICAL_LOCATION) {
58959d709d503bab6e2b61931737e662dd293b40578ccornelius                    UnicodeString canonicalID;
59059d709d503bab6e2b61931737e662dd293b40578ccornelius                    ZoneMeta::getCanonicalCLDRID(id, canonicalID, ec);
59159d709d503bab6e2b61931737e662dd293b40578ccornelius                    if (U_FAILURE(ec)) {
59259d709d503bab6e2b61931737e662dd293b40578ccornelius                        break;
59359d709d503bab6e2b61931737e662dd293b40578ccornelius                    }
59459d709d503bab6e2b61931737e662dd293b40578ccornelius                    if (canonicalID != id) {
59559d709d503bab6e2b61931737e662dd293b40578ccornelius                        // exclude aliases
59659d709d503bab6e2b61931737e662dd293b40578ccornelius                        continue;
59759d709d503bab6e2b61931737e662dd293b40578ccornelius                    }
59859d709d503bab6e2b61931737e662dd293b40578ccornelius                }
59959d709d503bab6e2b61931737e662dd293b40578ccornelius                if (type == UCAL_ZONE_TYPE_CANONICAL_LOCATION) {
60059d709d503bab6e2b61931737e662dd293b40578ccornelius                    const UChar *region = TimeZone::getRegion(id, ec);
60159d709d503bab6e2b61931737e662dd293b40578ccornelius                    if (U_FAILURE(ec)) {
60259d709d503bab6e2b61931737e662dd293b40578ccornelius                        break;
60359d709d503bab6e2b61931737e662dd293b40578ccornelius                    }
60459d709d503bab6e2b61931737e662dd293b40578ccornelius                    if (u_strcmp(region, WORLD) == 0) {
60559d709d503bab6e2b61931737e662dd293b40578ccornelius                       // exclude non-location ("001")
60659d709d503bab6e2b61931737e662dd293b40578ccornelius                        continue;
60759d709d503bab6e2b61931737e662dd293b40578ccornelius                    }
60859d709d503bab6e2b61931737e662dd293b40578ccornelius                }
60959d709d503bab6e2b61931737e662dd293b40578ccornelius                m[numEntries++] = i;
61059d709d503bab6e2b61931737e662dd293b40578ccornelius            }
61159d709d503bab6e2b61931737e662dd293b40578ccornelius            if (U_SUCCESS(ec)) {
61259d709d503bab6e2b61931737e662dd293b40578ccornelius                int32_t *tmp = m;
61359d709d503bab6e2b61931737e662dd293b40578ccornelius                m = (int32_t *)uprv_realloc(tmp, numEntries * sizeof(int32_t));
61459d709d503bab6e2b61931737e662dd293b40578ccornelius                if (m == NULL) {
61559d709d503bab6e2b61931737e662dd293b40578ccornelius                    // realloc failed.. use the original one even it has unused
61659d709d503bab6e2b61931737e662dd293b40578ccornelius                    // area at the end
61759d709d503bab6e2b61931737e662dd293b40578ccornelius                    m = tmp;
61859d709d503bab6e2b61931737e662dd293b40578ccornelius                }
61959d709d503bab6e2b61931737e662dd293b40578ccornelius
62059d709d503bab6e2b61931737e662dd293b40578ccornelius                switch(type) {
62159d709d503bab6e2b61931737e662dd293b40578ccornelius                case UCAL_ZONE_TYPE_ANY:
62259d709d503bab6e2b61931737e662dd293b40578ccornelius                    U_ASSERT(MAP_SYSTEM_ZONES == NULL);
62359d709d503bab6e2b61931737e662dd293b40578ccornelius                    MAP_SYSTEM_ZONES = m;
62459d709d503bab6e2b61931737e662dd293b40578ccornelius                    LEN_SYSTEM_ZONES = numEntries;
62559d709d503bab6e2b61931737e662dd293b40578ccornelius                    break;
62659d709d503bab6e2b61931737e662dd293b40578ccornelius                case UCAL_ZONE_TYPE_CANONICAL:
62759d709d503bab6e2b61931737e662dd293b40578ccornelius                    U_ASSERT(MAP_CANONICAL_SYSTEM_ZONES == NULL);
62859d709d503bab6e2b61931737e662dd293b40578ccornelius                    MAP_CANONICAL_SYSTEM_ZONES = m;
62959d709d503bab6e2b61931737e662dd293b40578ccornelius                    LEN_CANONICAL_SYSTEM_ZONES = numEntries;
63059d709d503bab6e2b61931737e662dd293b40578ccornelius                    break;
63159d709d503bab6e2b61931737e662dd293b40578ccornelius                case UCAL_ZONE_TYPE_CANONICAL_LOCATION:
63259d709d503bab6e2b61931737e662dd293b40578ccornelius                    U_ASSERT(MAP_CANONICAL_SYSTEM_LOCATION_ZONES == NULL);
63359d709d503bab6e2b61931737e662dd293b40578ccornelius                    MAP_CANONICAL_SYSTEM_LOCATION_ZONES = m;
63459d709d503bab6e2b61931737e662dd293b40578ccornelius                    LEN_CANONICAL_SYSTEM_LOCATION_ZONES = numEntries;
63559d709d503bab6e2b61931737e662dd293b40578ccornelius                    break;
63659d709d503bab6e2b61931737e662dd293b40578ccornelius                }
63759d709d503bab6e2b61931737e662dd293b40578ccornelius            }
63859d709d503bab6e2b61931737e662dd293b40578ccornelius        }
63959d709d503bab6e2b61931737e662dd293b40578ccornelius    }
64059d709d503bab6e2b61931737e662dd293b40578ccornelius    ures_close(res);
64159d709d503bab6e2b61931737e662dd293b40578ccornelius}
64259d709d503bab6e2b61931737e662dd293b40578ccornelius
64359d709d503bab6e2b61931737e662dd293b40578ccornelius
644b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
645b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * This is the default implementation for subclasses that do not
646b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * override this method.  This implementation calls through to the
647b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * 8-argument getOffset() method after suitable computations, and
648b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * correctly adjusts GMT millis to local millis when necessary.
649b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru */
650b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruvoid TimeZone::getOffset(UDate date, UBool local, int32_t& rawOffset,
651b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                         int32_t& dstOffset, UErrorCode& ec) const {
652b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_FAILURE(ec)) {
653b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return;
654b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
655b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
656b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    rawOffset = getRawOffset();
657b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (!local) {
658b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        date += rawOffset; // now in local standard millis
659b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
660b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
661b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // When local == TRUE, date might not be in local standard
662b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // millis.  getOffset taking 7 parameters used here assume
663b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // the given time in day is local standard time.
664b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // At STD->DST transition, there is a range of time which
665b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // does not exist.  When 'date' is in this time range
666b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // (and local == TRUE), this method interprets the specified
667b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // local time as DST.  At DST->STD transition, there is a
668b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // range of time which occurs twice.  In this case, this
669b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // method interprets the specified local time as STD.
670b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // To support the behavior above, we need to call getOffset
671b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // (with 7 args) twice when local == true and DST is
672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // detected in the initial call.
673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    for (int32_t pass=0; ; ++pass) {
674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t year, month, dom, dow;
675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        double day = uprv_floor(date / U_MILLIS_PER_DAY);
676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t millis = (int32_t) (date - day * U_MILLIS_PER_DAY);
677b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
678b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Grego::dayToFields(day, year, month, dom, dow);
679b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
680b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        dstOffset = getOffset(GregorianCalendar::AD, year, month, dom,
681b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                              (uint8_t) dow, millis,
682b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                              Grego::monthLength(year, month),
683b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                              ec) - rawOffset;
684b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
685b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Recompute if local==TRUE, dstOffset!=0.
686b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (pass!=0 || !local || dstOffset == 0) {
687b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            break;
688b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
689b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // adjust to local standard millis
690b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        date -= dstOffset;
691b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
692b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
693b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
694b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// -------------------------------------
695b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
696b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// New available IDs API as of ICU 2.4.  Uses StringEnumeration API.
697b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
698b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruclass TZEnumeration : public StringEnumeration {
699b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruprivate:
700b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
701b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // Map into to zones.  Our results are zone[map[i]] for
702b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // i=0..len-1, where zone[i] is the i-th Olson zone.  If map==NULL
703b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    // then our results are zone[i] for i=0..len-1.  Len will be zero
704b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // if the zone data could not be loaded.
705b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t* map;
706b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t* localMap;
707b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t  len;
708b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t  pos;
709b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
710b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TZEnumeration(int32_t* mapData, int32_t mapLen, UBool adoptMapData) : pos(0) {
711b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        map = mapData;
712b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        localMap = adoptMapData ? mapData : NULL;
713b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        len = mapLen;
714b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
715b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
716b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UBool getID(int32_t i) {
717b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UErrorCode ec = U_ZERO_ERROR;
718b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t idLen = 0;
719b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        const UChar* id = NULL;
720b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UResourceBundle *top = ures_openDirect(0, kZONEINFO, &ec);
721b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        top = ures_getByKey(top, kNAMES, top, &ec); // dereference Zones section
722b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        id = ures_getStringByIndex(top, i, &idLen, &ec);
723b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(U_FAILURE(ec)) {
724b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            unistr.truncate(0);
725b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
726b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        else {
727b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            unistr.fastCopyFrom(UnicodeString(TRUE, id, idLen));
728b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
729b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ures_close(top);
730b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return U_SUCCESS(ec);
731b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
732b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
733b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    static int32_t* getMap(USystemTimeZoneType type, int32_t& len, UErrorCode& ec) {
734b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        len = 0;
735b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_FAILURE(ec)) {
736b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return NULL;
737b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
738b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t* m = NULL;
739b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        switch (type) {
740b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        case UCAL_ZONE_TYPE_ANY:
74159d709d503bab6e2b61931737e662dd293b40578ccornelius            umtx_initOnce(gSystemZonesInitOnce, &initMap, type, ec);
742b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            m = MAP_SYSTEM_ZONES;
743b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            len = LEN_SYSTEM_ZONES;
744b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
745b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        case UCAL_ZONE_TYPE_CANONICAL:
74659d709d503bab6e2b61931737e662dd293b40578ccornelius            umtx_initOnce(gCanonicalZonesInitOnce, &initMap, type, ec);
747b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            m = MAP_CANONICAL_SYSTEM_ZONES;
748b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            len = LEN_CANONICAL_SYSTEM_ZONES;
749b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
750b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        case UCAL_ZONE_TYPE_CANONICAL_LOCATION:
75159d709d503bab6e2b61931737e662dd293b40578ccornelius            umtx_initOnce(gCanonicalLocationZonesInitOnce, &initMap, type, ec);
752b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            m = MAP_CANONICAL_SYSTEM_LOCATION_ZONES;
753b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            len = LEN_CANONICAL_SYSTEM_LOCATION_ZONES;
754b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            break;
75559d709d503bab6e2b61931737e662dd293b40578ccornelius        default:
75659d709d503bab6e2b61931737e662dd293b40578ccornelius            ec = U_ILLEGAL_ARGUMENT_ERROR;
75759d709d503bab6e2b61931737e662dd293b40578ccornelius            m = NULL;
75859d709d503bab6e2b61931737e662dd293b40578ccornelius            len = 0;
75959d709d503bab6e2b61931737e662dd293b40578ccornelius            break;
760b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
761b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return m;
762b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
763b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
764b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehopublic:
765b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
766b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#define DEFAULT_FILTERED_MAP_SIZE 8
767b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#define MAP_INCREMENT_SIZE 8
768b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
769b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    static TZEnumeration* create(USystemTimeZoneType type, const char* region, const int32_t* rawOffset, UErrorCode& ec) {
770b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_FAILURE(ec)) {
771b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return NULL;
772b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
773b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
774b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t baseLen;
775b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t *baseMap = getMap(type, baseLen, ec);
776b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
777b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_FAILURE(ec)) {
778b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            return NULL;
779b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
780b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
781b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // If any additional conditions are available,
782b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // create instance local map filtered by the conditions.
783b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
784b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t *filteredMap = NULL;
785b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        int32_t numEntries = 0;
786b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
787b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (region != NULL || rawOffset != NULL) {
788b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            int32_t filteredMapSize = DEFAULT_FILTERED_MAP_SIZE;
789b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            filteredMap = (int32_t *)uprv_malloc(filteredMapSize * sizeof(int32_t));
790b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (filteredMap == NULL) {
791b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                ec = U_MEMORY_ALLOCATION_ERROR;
792b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                return NULL;
79350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            }
79450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
795b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Walk through the base map
796b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            UResourceBundle *res = ures_openDirect(0, kZONEINFO, &ec);
797b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            res = ures_getByKey(res, kNAMES, res, &ec); // dereference Zones section
798b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            for (int32_t i = 0; i < baseLen; i++) {
799b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                int32_t zidx = baseMap[i];
800103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                UnicodeString id = ures_getUnicodeStringByIndex(res, zidx, &ec);
80150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                if (U_FAILURE(ec)) {
80250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    break;
80350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                }
804b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (region != NULL) {
805b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    // Filter by region
806b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    char tzregion[4]; // max 3 letters + null term
807b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    TimeZone::getRegion(id, tzregion, sizeof(tzregion), ec);
808b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (U_FAILURE(ec)) {
809b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        break;
810b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    }
811b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (uprv_stricmp(tzregion, region) != 0) {
812b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        // region does not match
813b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        continue;
814b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    }
81550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                }
816b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (rawOffset != NULL) {
817b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    // Filter by raw offset
818b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    // Note: This is VERY inefficient
81959d709d503bab6e2b61931737e662dd293b40578ccornelius                    TimeZone *z = createSystemTimeZone(id, ec);
820b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (U_FAILURE(ec)) {
821b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        break;
822b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    }
823b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    int32_t tzoffset = z->getRawOffset();
824b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    delete z;
82550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
826b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (tzoffset != *rawOffset) {
827b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        continue;
82850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    }
829b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                }
830b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
831b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                if (filteredMapSize <= numEntries) {
832b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    filteredMapSize += MAP_INCREMENT_SIZE;
833b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    int32_t *tmp = (int32_t *)uprv_realloc(filteredMap, filteredMapSize * sizeof(int32_t));
834b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                    if (tmp == NULL) {
835b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        ec = U_MEMORY_ALLOCATION_ERROR;
836b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        break;
83750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                    } else {
838b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                        filteredMap = tmp;
839b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    }
840b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
841b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
842b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                filteredMap[numEntries++] = zidx;
843b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
844b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
845b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (U_FAILURE(ec)) {
846b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                uprv_free(filteredMap);
847b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                filteredMap = NULL;
848b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
849b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
850b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            ures_close(res);
851b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
852b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
853b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        TZEnumeration *result = NULL;
854b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_SUCCESS(ec)) {
855b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Finally, create a new enumeration instance
856b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (filteredMap == NULL) {
857b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                result = new TZEnumeration(baseMap, baseLen, FALSE);
858b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            } else {
859b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                result = new TZEnumeration(filteredMap, numEntries, TRUE);
860b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                filteredMap = NULL;
861b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
862b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (result == NULL) {
863b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                ec = U_MEMORY_ALLOCATION_ERROR;
864b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            }
865b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
866b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
867b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (filteredMap != NULL) {
868b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            uprv_free(filteredMap);
869b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
870b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
871b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return result;
872b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
873b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
874b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    TZEnumeration(const TZEnumeration &other) : StringEnumeration(), map(NULL), localMap(NULL), len(0), pos(0) {
875b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (other.localMap != NULL) {
876b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            localMap = (int32_t *)uprv_malloc(other.len * sizeof(int32_t));
877b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (localMap != NULL) {
878b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                len = other.len;
879b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                uprv_memcpy(localMap, other.localMap, len * sizeof(int32_t));
880b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pos = other.pos;
881b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                map = localMap;
882b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            } else {
883b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                len = 0;
884b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                pos = 0;
885b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho                map = NULL;
886b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
887b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else {
888b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            map = other.map;
889b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            localMap = NULL;
890b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            len = other.len;
891b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            pos = other.pos;
892b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
893b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
894b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
895103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    virtual ~TZEnumeration();
896b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
897b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    virtual StringEnumeration *clone() const {
898b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return new TZEnumeration(*this);
899b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
900b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
901b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    virtual int32_t count(UErrorCode& status) const {
902b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return U_FAILURE(status) ? 0 : len;
903b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
904b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
905b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    virtual const UnicodeString* snext(UErrorCode& status) {
906b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_SUCCESS(status) && map != NULL && pos < len) {
907b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            getID(map[pos]);
908b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            ++pos;
909b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            return &unistr;
910b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
911b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 0;
912b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
913b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
914b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    virtual void reset(UErrorCode& /*status*/) {
915b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pos = 0;
916b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
917b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
918b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Querupublic:
919b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    static UClassID U_EXPORT2 getStaticClassID(void);
920b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    virtual UClassID getDynamicClassID(void) const;
921b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru};
922b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
923103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusTZEnumeration::~TZEnumeration() {
924103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (localMap != NULL) {
925103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        uprv_free(localMap);
926103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    }
927103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
928103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
929b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUOBJECT_DEFINE_RTTI_IMPLEMENTATION(TZEnumeration)
930b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
931b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruStringEnumeration* U_EXPORT2
932b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZone::createTimeZoneIDEnumeration(
933b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            USystemTimeZoneType zoneType,
934b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            const char* region,
935b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            const int32_t* rawOffset,
936b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            UErrorCode& ec) {
937b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return TZEnumeration::create(zoneType, region, rawOffset, ec);
938b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
939b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
940b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoStringEnumeration* U_EXPORT2
941b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::createEnumeration() {
942b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode ec = U_ZERO_ERROR;
943b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return TZEnumeration::create(UCAL_ZONE_TYPE_ANY, NULL, NULL, ec);
944b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
945b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
946b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruStringEnumeration* U_EXPORT2
947b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::createEnumeration(int32_t rawOffset) {
948b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode ec = U_ZERO_ERROR;
949b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return TZEnumeration::create(UCAL_ZONE_TYPE_ANY, NULL, &rawOffset, ec);
950b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
951b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
952b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruStringEnumeration* U_EXPORT2
953b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::createEnumeration(const char* country) {
954b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode ec = U_ZERO_ERROR;
955b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return TZEnumeration::create(UCAL_ZONE_TYPE_ANY, country, NULL, ec);
956b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
957b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
958b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ---------------------------------------
959b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
960b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruint32_t U_EXPORT2
961b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::countEquivalentIDs(const UnicodeString& id) {
962b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t result = 0;
963b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode ec = U_ZERO_ERROR;
964b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UResourceBundle res;
965b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_initStackObject(&res);
966b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_DEBUG_TZ_MSG(("countEquivalentIDs..\n"));
967b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UResourceBundle *top = openOlsonResource(id, res, ec);
968b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_SUCCESS(ec)) {
96950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        UResourceBundle r;
97050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        ures_initStackObject(&r);
97150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        ures_getByKey(&res, kLINKS, &r, &ec);
97250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        ures_getIntVector(&r, &result, &ec);
97350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        ures_close(&r);
974b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
975b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_close(&res);
976b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_close(top);
977b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
978b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
979b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
980b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ---------------------------------------
981b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
982b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queruconst UnicodeString U_EXPORT2
983b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::getEquivalentID(const UnicodeString& id, int32_t index) {
984b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    U_DEBUG_TZ_MSG(("gEI(%d)\n", index));
985b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString result;
986b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode ec = U_ZERO_ERROR;
987b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UResourceBundle res;
988b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_initStackObject(&res);
989b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UResourceBundle *top = openOlsonResource(id, res, ec);
990b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    int32_t zone = -1;
991b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_SUCCESS(ec)) {
99250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        UResourceBundle r;
99350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        ures_initStackObject(&r);
99450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        int32_t size;
99550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        ures_getByKey(&res, kLINKS, &r, &ec);
99650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        const int32_t* v = ures_getIntVector(&r, &size, &ec);
99750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if (U_SUCCESS(ec)) {
998b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            if (index >= 0 && index < size) {
999b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                zone = v[index];
1000b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1001b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
100250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        ures_close(&r);
1003b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1004b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_close(&res);
1005b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (zone >= 0) {
1006b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UResourceBundle *ares = ures_getByKey(top, kNAMES, NULL, &ec); // dereference Zones section
1007b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (U_SUCCESS(ec)) {
1008b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t idLen = 0;
1009b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            const UChar* id = ures_getStringByIndex(ares, zone, &idLen, &ec);
1010b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            result.fastCopyFrom(UnicodeString(TRUE, id, idLen));
1011b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            U_DEBUG_TZ_MSG(("gei(%d) -> %d, len%d, %s\n", index, zone, result.length(), u_errorName(ec)));
1012b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1013b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ures_close(ares);
1014b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1015b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_close(top);
1016b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#if defined(U_DEBUG_TZ)
1017b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if(result.length() ==0) {
1018b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru      U_DEBUG_TZ_MSG(("equiv [__, #%d] -> 0 (%s)\n", index, u_errorName(ec)));
1019b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1020b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif
1021b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return result;
1022b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1023b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1024b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ---------------------------------------
1025b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1026b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// These methods are used by ZoneMeta class only.
1027b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1028b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UChar*
1029b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZone::findID(const UnicodeString& id) {
1030b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar *result = NULL;
1031b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode ec = U_ZERO_ERROR;
1032b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UResourceBundle *rb = ures_openDirect(NULL, kZONEINFO, &ec);
1033b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1034b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // resolve zone index by name
1035b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UResourceBundle *names = ures_getByKey(rb, kNAMES, NULL, &ec);
1036b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t idx = findInStringArray(names, id, ec);
1037b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    result = ures_getStringByIndex(names, idx, NULL, &ec);
1038b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(ec)) {
1039b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        result = NULL;
1040b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1041b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ures_close(names);
1042b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ures_close(rb);
1043b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return result;
1044b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1045b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
104650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
104750294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoconst UChar*
104850294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoTimeZone::dereferOlsonLink(const UnicodeString& id) {
104950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    const UChar *result = NULL;
1050b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode ec = U_ZERO_ERROR;
105150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    UResourceBundle *rb = ures_openDirect(NULL, kZONEINFO, &ec);
105250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
105350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    // resolve zone index by name
105450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    UResourceBundle *names = ures_getByKey(rb, kNAMES, NULL, &ec);
105550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    int32_t idx = findInStringArray(names, id, ec);
105650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    result = ures_getStringByIndex(names, idx, NULL, &ec);
105750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
105850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    // open the zone bundle by index
105950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    ures_getByKey(rb, kZONES, rb, &ec);
106050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    ures_getByIndex(rb, idx, rb, &ec);
106150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
1062b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (U_SUCCESS(ec)) {
106350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        if (ures_getType(rb) == URES_INT) {
106450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            // this is a link - dereference the link
106550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            int32_t deref = ures_getInt(rb, &ec);
106650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho            const UChar* tmp = ures_getStringByIndex(names, deref, NULL, &ec);
1067b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (U_SUCCESS(ec)) {
106850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho                result = tmp;
1069b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1070b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1071b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
107250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
107350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    ures_close(names);
107450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    ures_close(rb);
107550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
107650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    return result;
107750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho}
107850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
107950294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoconst UChar*
108050294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoTimeZone::getRegion(const UnicodeString& id) {
1081b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UErrorCode status = U_ZERO_ERROR;
1082b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return getRegion(id, status);
1083b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1084b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1085b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoconst UChar*
1086b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZone::getRegion(const UnicodeString& id, UErrorCode& status) {
1087b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
1088b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return NULL;
1089b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1090b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar *result = NULL;
1091b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UResourceBundle *rb = ures_openDirect(NULL, kZONEINFO, &status);
109250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
109350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    // resolve zone index by name
1094b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    UResourceBundle *res = ures_getByKey(rb, kNAMES, NULL, &status);
1095b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t idx = findInStringArray(res, id, status);
109650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
109750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    // get region mapping
1098b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    ures_getByKey(rb, kREGIONS, res, &status);
1099b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar *tmp = ures_getStringByIndex(res, idx, NULL, &status);
1100b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_SUCCESS(status)) {
110150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho        result = tmp;
110250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    }
110350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
1104b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    ures_close(res);
110550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    ures_close(rb);
110650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho
110750294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho    return result;
1108b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1109b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1110b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1111b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho// ---------------------------------------
1112b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoint32_t
1113b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoTimeZone::getRegion(const UnicodeString& id, char *region, int32_t capacity, UErrorCode& status)
1114b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho{
1115b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    int32_t resultLen = 0;
1116b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    *region = 0;
1117b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (U_FAILURE(status)) {
1118b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return 0;
1119b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1120b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1121b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    const UChar *uregion = NULL;
1122b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // "Etc/Unknown" is not a system zone ID,
1123b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // but in the zone data
1124b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (id.compare(UNKNOWN_ZONE_ID, UNKNOWN_ZONE_ID_LENGTH) != 0) {
1125b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        uregion = getRegion(id);
1126b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1127b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (uregion == NULL) {
1128b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        status = U_ILLEGAL_ARGUMENT_ERROR;
1129b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return 0;
1130b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1131b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    resultLen = u_strlen(uregion);
1132b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // A region code is represented by invariant characters
1133b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    u_UCharsToChars(uregion, region, uprv_min(resultLen, capacity));
1134b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1135b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (capacity < resultLen) {
1136b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        status = U_BUFFER_OVERFLOW_ERROR;
1137b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        return resultLen;
1138b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1139b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1140b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return u_terminateChars(region, capacity, resultLen, &status);
1141b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho}
1142b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1143b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru// ---------------------------------------
1144b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1145b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1146b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString&
1147b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::getDisplayName(UnicodeString& result) const
1148b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1149b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return getDisplayName(FALSE,LONG,Locale::getDefault(), result);
1150b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1151b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1152b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString&
1153b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::getDisplayName(const Locale& locale, UnicodeString& result) const
1154b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1155b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return getDisplayName(FALSE, LONG, locale, result);
1156b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1157b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1158b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString&
1159b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::getDisplayName(UBool daylight, EDisplayType style, UnicodeString& result)  const
1160b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1161b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return getDisplayName(daylight,style, Locale::getDefault(), result);
1162b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1163b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//--------------------------------------
1164b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoint32_t
1165b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::getDSTSavings()const {
1166b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (useDaylightTime()) {
1167b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        return 3600000;
1168b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1169b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return 0;
1170b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1171b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//---------------------------------------
1172b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruUnicodeString&
1173b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::getDisplayName(UBool daylight, EDisplayType style, const Locale& locale, UnicodeString& result) const
1174b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1175b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
1176103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    UDate date = Calendar::getNow();
1177103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    UTimeZoneFormatTimeType timeType;
1178103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    int32_t offset;
1179b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho
1180103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (style == GENERIC_LOCATION || style == LONG_GENERIC || style == SHORT_GENERIC) {
1181103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        LocalPointer<TimeZoneFormat> tzfmt(TimeZoneFormat::createInstance(locale, status));
1182c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (U_FAILURE(status)) {
1183103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            result.remove();
1184103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            return result;
1185c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1186103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        // Generic format
1187103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        switch (style) {
1188103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        case GENERIC_LOCATION:
1189103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            tzfmt->format(UTZFMT_STYLE_GENERIC_LOCATION, *this, date, result, &timeType);
1190103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            break;
1191103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        case LONG_GENERIC:
1192103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            tzfmt->format(UTZFMT_STYLE_GENERIC_LONG, *this, date, result, &timeType);
1193103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            break;
1194103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        case SHORT_GENERIC:
1195103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            tzfmt->format(UTZFMT_STYLE_GENERIC_SHORT, *this, date, result, &timeType);
1196103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            break;
1197103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        default:
1198103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            U_ASSERT(FALSE);
1199103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        }
1200103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        // Generic format many use Localized GMT as the final fallback.
1201103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        // When Localized GMT format is used, the result might not be
1202103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        // appropriate for the requested daylight value.
1203103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        if ((daylight && timeType == UTZFMT_TIME_TYPE_STANDARD) || (!daylight && timeType == UTZFMT_TIME_TYPE_DAYLIGHT)) {
1204103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            offset = daylight ? getRawOffset() + getDSTSavings() : getRawOffset();
12058393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            if (style == SHORT_GENERIC) {
12068393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                tzfmt->formatOffsetShortLocalizedGMT(offset, result, status);
12078393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            } else {
12088393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                tzfmt->formatOffsetLocalizedGMT(offset, result, status);
12098393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            }
1210c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1211103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    } else if (style == LONG_GMT || style == SHORT_GMT) {
1212103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        LocalPointer<TimeZoneFormat> tzfmt(TimeZoneFormat::createInstance(locale, status));
1213103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        if (U_FAILURE(status)) {
1214103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            result.remove();
1215103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            return result;
1216103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        }
1217103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        offset = daylight && useDaylightTime() ? getRawOffset() + getDSTSavings() : getRawOffset();
1218103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        switch (style) {
1219103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        case LONG_GMT:
1220103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            tzfmt->formatOffsetLocalizedGMT(offset, result, status);
1221103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            break;
1222103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        case SHORT_GMT:
12238393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            tzfmt->formatOffsetISO8601Basic(offset, FALSE, FALSE, FALSE, result, status);
1224103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            break;
1225103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        default:
1226103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            U_ASSERT(FALSE);
1227103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        }
1228103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
1229c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else {
1230103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        U_ASSERT(style == LONG || style == SHORT || style == SHORT_COMMONLY_USED);
1231103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        UTimeZoneNameType nameType = UTZNM_UNKNOWN;
1232103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        switch (style) {
1233103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        case LONG:
1234103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            nameType = daylight ? UTZNM_LONG_DAYLIGHT : UTZNM_LONG_STANDARD;
1235103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            break;
1236103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        case SHORT:
1237103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        case SHORT_COMMONLY_USED:
1238103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            nameType = daylight ? UTZNM_SHORT_DAYLIGHT : UTZNM_SHORT_STANDARD;
1239103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            break;
1240103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        default:
1241103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            U_ASSERT(FALSE);
1242103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        }
1243103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        LocalPointer<TimeZoneNames> tznames(TimeZoneNames::createInstance(locale, status));
1244103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        if (U_FAILURE(status)) {
1245103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            result.remove();
1246103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            return result;
1247103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        }
1248103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        UnicodeString canonicalID(ZoneMeta::getCanonicalCLDRID(*this));
1249103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        tznames->getDisplayName(canonicalID, nameType, date, result);
1250103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        if (result.isEmpty()) {
1251103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            // Fallback to localized GMT
1252103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            LocalPointer<TimeZoneFormat> tzfmt(TimeZoneFormat::createInstance(locale, status));
1253103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            offset = daylight && useDaylightTime() ? getRawOffset() + getDSTSavings() : getRawOffset();
12548393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            if (style == LONG) {
12558393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                tzfmt->formatOffsetLocalizedGMT(offset, result, status);
12568393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            } else {
12578393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius                tzfmt->formatOffsetShortLocalizedGMT(offset, result, status);
12588393335b955da7340c9f19b1b4b2d6c0c2c04be7Craig Cornelius            }
1259c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1260c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1261103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (U_FAILURE(status)) {
1262103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        result.remove();
1263103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    }
1264c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return  result;
1265b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1266b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1267b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru/**
1268b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * Parse a custom time zone identifier and return a corresponding zone.
1269b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @param id a string of the form GMT[+-]hh:mm, GMT[+-]hhmm, or
1270b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * GMT[+-]hh.
1271b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * @return a newly created SimpleTimeZone with the given offset and
1272b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru * no Daylight Savings Time, or null if the id cannot be parsed.
1273b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru*/
1274b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone*
1275b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::createCustomTimeZone(const UnicodeString& id)
1276b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1277c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t sign, hour, min, sec;
1278c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (parseCustomID(id, sign, hour, min, sec)) {
1279c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        UnicodeString customID;
1280c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        formatCustomID(hour, min, sec, (sign < 0), customID);
1281c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        int32_t offset = sign * ((hour * 60 + min) * 60 + sec) * 1000;
1282c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return new SimpleTimeZone(offset, customID);
1283c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1284c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return NULL;
1285c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1286c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1287c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruUnicodeString&
1288c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruTimeZone::getCustomID(const UnicodeString& id, UnicodeString& normalized, UErrorCode& status) {
1289c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    normalized.remove();
1290c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (U_FAILURE(status)) {
1291c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return normalized;
1292c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1293c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    int32_t sign, hour, min, sec;
1294c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (parseCustomID(id, sign, hour, min, sec)) {
1295c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        formatCustomID(hour, min, sec, (sign < 0), normalized);
1296fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    } else {
1297fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        status = U_ILLEGAL_ARGUMENT_ERROR;
1298c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1299c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return normalized;
1300c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1301c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1302c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruUBool
1303c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruTimeZone::parseCustomID(const UnicodeString& id, int32_t& sign,
1304c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                        int32_t& hour, int32_t& min, int32_t& sec) {
1305b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    static const int32_t         kParseFailed = -99999;
1306b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1307b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    NumberFormat* numberFormat = 0;
1308b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    UnicodeString idUppercase = id;
1309103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    idUppercase.toUpper("");
1310b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1311b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    if (id.length() > GMT_ID_LENGTH &&
1312103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        idUppercase.startsWith(GMT_ID, GMT_ID_LENGTH))
1313b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    {
1314b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        ParsePosition pos(GMT_ID_LENGTH);
1315c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        sign = 1;
1316c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        hour = 0;
1317c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        min = 0;
1318c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        sec = 0;
1319c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1320c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (id[pos.getIndex()] == MINUS /*'-'*/) {
1321c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            sign = -1;
1322c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        } else if (id[pos.getIndex()] != PLUS /*'+'*/) {
1323c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return FALSE;
1324c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1325b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        pos.setIndex(pos.getIndex() + 1);
1326b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1327b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        UErrorCode success = U_ZERO_ERROR;
1328b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        numberFormat = NumberFormat::createInstance(success);
1329b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if(U_FAILURE(success)){
1330c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return FALSE;
1331b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1332b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        numberFormat->setParseIntegerOnly(TRUE);
1333b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        //numberFormat->setLenient(TRUE); // TODO: May need to set this, depends on latest timezone parsing
1334b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1335b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        // Look for either hh:mm, hhmm, or hh
1336b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        int32_t start = pos.getIndex();
1337b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        Formattable n(kParseFailed);
1338b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        numberFormat->parse(id, n, pos);
1339b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (pos.getIndex() == start) {
1340b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            delete numberFormat;
1341c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return FALSE;
1342b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1343b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        hour = n.getLong();
1344b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1345b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (pos.getIndex() < id.length()) {
1346b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (pos.getIndex() - start > 2
1347b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                || id[pos.getIndex()] != COLON) {
1348b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                delete numberFormat;
1349c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                return FALSE;
1350b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1351b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // hh:mm
1352b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            pos.setIndex(pos.getIndex() + 1);
1353b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t oldPos = pos.getIndex();
1354b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            n.setLong(kParseFailed);
1355b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            numberFormat->parse(id, n, pos);
1356b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if ((pos.getIndex() - oldPos) != 2) {
1357b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // must be 2 digits
1358b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                delete numberFormat;
1359c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                return FALSE;
1360b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1361b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            min = n.getLong();
1362b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (pos.getIndex() < id.length()) {
1363b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru                if (id[pos.getIndex()] != COLON) {
1364b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    delete numberFormat;
1365c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                    return FALSE;
1366b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1367b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // [:ss]
1368b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                pos.setIndex(pos.getIndex() + 1);
1369b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                oldPos = pos.getIndex();
1370b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                n.setLong(kParseFailed);
1371b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                numberFormat->parse(id, n, pos);
1372b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                if (pos.getIndex() != id.length()
1373b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                        || (pos.getIndex() - oldPos) != 2) {
1374b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    delete numberFormat;
1375c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                    return FALSE;
1376b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                }
1377b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                sec = n.getLong();
1378b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1379b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        } else {
1380b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Supported formats are below -
1381b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            //
1382b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // HHmmss
1383b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Hmmss
1384b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // HHmm
1385b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // Hmm
1386b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // HH
1387b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            // H
1388b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1389b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            int32_t length = pos.getIndex() - start;
1390b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            if (length <= 0 || 6 < length) {
1391b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                // invalid length
1392b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                delete numberFormat;
1393c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                return FALSE;
1394b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1395b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            switch (length) {
1396b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                case 1:
1397b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                case 2:
1398b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    // already set to hour
1399b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    break;
1400b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                case 3:
1401b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                case 4:
1402b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    min = hour % 100;
1403b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    hour /= 100;
1404b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    break;
1405b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                case 5:
1406b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                case 6:
1407b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    sec = hour % 100;
1408b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    min = (hour/100) % 100;
1409b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    hour /= 10000;
1410b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru                    break;
1411b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            }
1412b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1413b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1414b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        delete numberFormat;
1415b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1416b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        if (hour > kMAX_CUSTOM_HOUR || min > kMAX_CUSTOM_MIN || sec > kMAX_CUSTOM_SEC) {
1417c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            return FALSE;
1418b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1419c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return TRUE;
1420c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1421c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return FALSE;
1422c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1423b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1424c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruUnicodeString&
1425c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruTimeZone::formatCustomID(int32_t hour, int32_t min, int32_t sec,
1426c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                         UBool negative, UnicodeString& id) {
1427c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    // Create time zone ID - GMT[+|-]hhmm[ss]
1428103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    id.setTo(GMT_ID, GMT_ID_LENGTH);
1429c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (hour | min | sec) {
1430c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (negative) {
1431c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            id += (UChar)MINUS;
1432c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        } else {
1433c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            id += (UChar)PLUS;
1434c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1435b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1436c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (hour < 10) {
1437c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            id += (UChar)ZERO_DIGIT;
1438c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        } else {
1439c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            id += (UChar)(ZERO_DIGIT + hour/10);
1440c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        }
1441c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        id += (UChar)(ZERO_DIGIT + hour%10);
1442b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru        id += (UChar)COLON;
1443c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (min < 10) {
1444c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            id += (UChar)ZERO_DIGIT;
1445c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        } else {
1446c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            id += (UChar)(ZERO_DIGIT + min/10);
1447b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1448c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        id += (UChar)(ZERO_DIGIT + min%10);
1449b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1450c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        if (sec) {
1451b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru            id += (UChar)COLON;
1452c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            if (sec < 10) {
1453c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                id += (UChar)ZERO_DIGIT;
1454c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            } else {
1455c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                id += (UChar)(ZERO_DIGIT + sec/10);
1456c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            }
1457c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru            id += (UChar)(ZERO_DIGIT + sec%10);
1458b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
1459b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
1460c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return id;
1461b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1462b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1463b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1464b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2clairehoUBool
1465b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruTimeZone::hasSameRules(const TimeZone& other) const
1466b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru{
1467b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    return (getRawOffset() == other.getRawOffset() &&
1468b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru            useDaylightTime() == other.useDaylightTime());
1469b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1470b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
147159d709d503bab6e2b61931737e662dd293b40578ccorneliusstatic void U_CALLCONV initTZDataVersion(UErrorCode &status) {
147259d709d503bab6e2b61931737e662dd293b40578ccornelius    ucln_i18n_registerCleanup(UCLN_I18N_TIMEZONE, timeZone_cleanup);
147359d709d503bab6e2b61931737e662dd293b40578ccornelius    int32_t len = 0;
147459d709d503bab6e2b61931737e662dd293b40578ccornelius    UResourceBundle *bundle = ures_openDirect(NULL, kZONEINFO, &status);
147559d709d503bab6e2b61931737e662dd293b40578ccornelius    const UChar *tzver = ures_getStringByKey(bundle, kTZVERSION, &len, &status);
1476b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
147759d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_SUCCESS(status)) {
147859d709d503bab6e2b61931737e662dd293b40578ccornelius        if (len >= (int32_t)sizeof(TZDATA_VERSION)) {
147959d709d503bab6e2b61931737e662dd293b40578ccornelius            // Ensure that there is always space for a trailing nul in TZDATA_VERSION
148059d709d503bab6e2b61931737e662dd293b40578ccornelius            len = sizeof(TZDATA_VERSION) - 1;
1481b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru        }
148259d709d503bab6e2b61931737e662dd293b40578ccornelius        u_UCharsToChars(tzver, TZDATA_VERSION, len);
1483b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    }
148459d709d503bab6e2b61931737e662dd293b40578ccornelius    ures_close(bundle);
148559d709d503bab6e2b61931737e662dd293b40578ccornelius
148659d709d503bab6e2b61931737e662dd293b40578ccornelius}
148759d709d503bab6e2b61931737e662dd293b40578ccornelius
148859d709d503bab6e2b61931737e662dd293b40578ccorneliusconst char*
148959d709d503bab6e2b61931737e662dd293b40578ccorneliusTimeZone::getTZDataVersion(UErrorCode& status)
149059d709d503bab6e2b61931737e662dd293b40578ccornelius{
149159d709d503bab6e2b61931737e662dd293b40578ccornelius    umtx_initOnce(gTZDataVersionInitOnce, &initTZDataVersion, status);
1492b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru    return (const char*)TZDATA_VERSION;
1493b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru}
1494b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1495c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruUnicodeString&
1496c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruTimeZone::getCanonicalID(const UnicodeString& id, UnicodeString& canonicalID, UErrorCode& status)
1497c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru{
1498c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    UBool isSystemID = FALSE;
1499c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return getCanonicalID(id, canonicalID, isSystemID, status);
1500c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1501c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
1502c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruUnicodeString&
1503c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste QueruTimeZone::getCanonicalID(const UnicodeString& id, UnicodeString& canonicalID, UBool& isSystemID,
1504c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru                         UErrorCode& status)
1505c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru{
1506c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    canonicalID.remove();
1507c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    isSystemID = FALSE;
1508c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    if (U_FAILURE(status)) {
1509c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru        return canonicalID;
1510c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1511b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (id.compare(UNKNOWN_ZONE_ID, UNKNOWN_ZONE_ID_LENGTH) == 0) {
1512b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        // special case - Etc/Unknown is a canonical ID, but not system ID
1513b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        canonicalID.fastCopyFrom(id);
1514b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        isSystemID = FALSE;
1515c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    } else {
1516b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        ZoneMeta::getCanonicalCLDRID(id, canonicalID, status);
1517b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (U_SUCCESS(status)) {
1518b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            isSystemID = TRUE;
1519b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        } else {
1520b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            // Not a system ID
1521b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            status = U_ZERO_ERROR;
1522b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            getCustomID(id, canonicalID, status);
1523b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1524c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    }
1525c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru    return canonicalID;
1526c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru}
1527c69afcec261fc345fda8daf46f0ea6b4351dc777Jean-Baptiste Queru
152859d709d503bab6e2b61931737e662dd293b40578ccornelius#ifndef U_HIDE_DRAFT_API
152959d709d503bab6e2b61931737e662dd293b40578ccorneliusUnicodeString&
153059d709d503bab6e2b61931737e662dd293b40578ccorneliusTimeZone::getWindowsID(const UnicodeString& id, UnicodeString& winid, UErrorCode& status) {
153159d709d503bab6e2b61931737e662dd293b40578ccornelius    winid.remove();
153259d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_FAILURE(status)) {
153359d709d503bab6e2b61931737e662dd293b40578ccornelius        return winid;
153459d709d503bab6e2b61931737e662dd293b40578ccornelius    }
153559d709d503bab6e2b61931737e662dd293b40578ccornelius
153659d709d503bab6e2b61931737e662dd293b40578ccornelius    // canonicalize the input ID
153759d709d503bab6e2b61931737e662dd293b40578ccornelius    UnicodeString canonicalID;
153859d709d503bab6e2b61931737e662dd293b40578ccornelius    UBool isSystemID = FALSE;
153959d709d503bab6e2b61931737e662dd293b40578ccornelius
154059d709d503bab6e2b61931737e662dd293b40578ccornelius    getCanonicalID(id, canonicalID, isSystemID, status);
154159d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_FAILURE(status) || !isSystemID) {
154259d709d503bab6e2b61931737e662dd293b40578ccornelius        // mapping data is only applicable to tz database IDs
1543fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if (status == U_ILLEGAL_ARGUMENT_ERROR) {
1544fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // getWindowsID() sets an empty string where
1545fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // getCanonicalID() sets a U_ILLEGAL_ARGUMENT_ERROR.
1546fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            status = U_ZERO_ERROR;
1547fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
154859d709d503bab6e2b61931737e662dd293b40578ccornelius        return winid;
154959d709d503bab6e2b61931737e662dd293b40578ccornelius    }
155059d709d503bab6e2b61931737e662dd293b40578ccornelius
155159d709d503bab6e2b61931737e662dd293b40578ccornelius    UResourceBundle *mapTimezones = ures_openDirect(NULL, "windowsZones", &status);
155259d709d503bab6e2b61931737e662dd293b40578ccornelius    ures_getByKey(mapTimezones, "mapTimezones", mapTimezones, &status);
155359d709d503bab6e2b61931737e662dd293b40578ccornelius
155459d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_FAILURE(status)) {
155559d709d503bab6e2b61931737e662dd293b40578ccornelius        return winid;
155659d709d503bab6e2b61931737e662dd293b40578ccornelius    }
155759d709d503bab6e2b61931737e662dd293b40578ccornelius
155859d709d503bab6e2b61931737e662dd293b40578ccornelius    UResourceBundle *winzone = NULL;
155959d709d503bab6e2b61931737e662dd293b40578ccornelius    UBool found = FALSE;
156059d709d503bab6e2b61931737e662dd293b40578ccornelius    while (ures_hasNext(mapTimezones) && !found) {
156159d709d503bab6e2b61931737e662dd293b40578ccornelius        winzone = ures_getNextResource(mapTimezones, winzone, &status);
156259d709d503bab6e2b61931737e662dd293b40578ccornelius        if (U_FAILURE(status)) {
156359d709d503bab6e2b61931737e662dd293b40578ccornelius            break;
156459d709d503bab6e2b61931737e662dd293b40578ccornelius        }
156559d709d503bab6e2b61931737e662dd293b40578ccornelius        if (ures_getType(winzone) != URES_TABLE) {
156659d709d503bab6e2b61931737e662dd293b40578ccornelius            continue;
156759d709d503bab6e2b61931737e662dd293b40578ccornelius        }
156859d709d503bab6e2b61931737e662dd293b40578ccornelius        UResourceBundle *regionalData = NULL;
156959d709d503bab6e2b61931737e662dd293b40578ccornelius        while (ures_hasNext(winzone) && !found) {
157059d709d503bab6e2b61931737e662dd293b40578ccornelius            regionalData = ures_getNextResource(winzone, regionalData, &status);
157159d709d503bab6e2b61931737e662dd293b40578ccornelius            if (U_FAILURE(status)) {
157259d709d503bab6e2b61931737e662dd293b40578ccornelius                break;
157359d709d503bab6e2b61931737e662dd293b40578ccornelius            }
157459d709d503bab6e2b61931737e662dd293b40578ccornelius            if (ures_getType(regionalData) != URES_STRING) {
157559d709d503bab6e2b61931737e662dd293b40578ccornelius                continue;
157659d709d503bab6e2b61931737e662dd293b40578ccornelius            }
157759d709d503bab6e2b61931737e662dd293b40578ccornelius            int32_t len;
157859d709d503bab6e2b61931737e662dd293b40578ccornelius            const UChar *tzids = ures_getString(regionalData, &len, &status);
157959d709d503bab6e2b61931737e662dd293b40578ccornelius            if (U_FAILURE(status)) {
158059d709d503bab6e2b61931737e662dd293b40578ccornelius                break;
158159d709d503bab6e2b61931737e662dd293b40578ccornelius            }
158259d709d503bab6e2b61931737e662dd293b40578ccornelius
158359d709d503bab6e2b61931737e662dd293b40578ccornelius            const UChar *start = tzids;
158459d709d503bab6e2b61931737e662dd293b40578ccornelius            UBool hasNext = TRUE;
158559d709d503bab6e2b61931737e662dd293b40578ccornelius            while (hasNext) {
158659d709d503bab6e2b61931737e662dd293b40578ccornelius                const UChar *end = u_strchr(start, (UChar)0x20);
158759d709d503bab6e2b61931737e662dd293b40578ccornelius                if (end == NULL) {
158859d709d503bab6e2b61931737e662dd293b40578ccornelius                    end = tzids + len;
158959d709d503bab6e2b61931737e662dd293b40578ccornelius                    hasNext = FALSE;
159059d709d503bab6e2b61931737e662dd293b40578ccornelius                }
159159d709d503bab6e2b61931737e662dd293b40578ccornelius                if (canonicalID.compare(start, end - start) == 0) {
159259d709d503bab6e2b61931737e662dd293b40578ccornelius                    winid = UnicodeString(ures_getKey(winzone), -1 , US_INV);
159359d709d503bab6e2b61931737e662dd293b40578ccornelius                    found = TRUE;
159459d709d503bab6e2b61931737e662dd293b40578ccornelius                    break;
159559d709d503bab6e2b61931737e662dd293b40578ccornelius                }
159659d709d503bab6e2b61931737e662dd293b40578ccornelius                start = end + 1;
159759d709d503bab6e2b61931737e662dd293b40578ccornelius            }
159859d709d503bab6e2b61931737e662dd293b40578ccornelius        }
159959d709d503bab6e2b61931737e662dd293b40578ccornelius        ures_close(regionalData);
160059d709d503bab6e2b61931737e662dd293b40578ccornelius    }
160159d709d503bab6e2b61931737e662dd293b40578ccornelius    ures_close(winzone);
160259d709d503bab6e2b61931737e662dd293b40578ccornelius    ures_close(mapTimezones);
160359d709d503bab6e2b61931737e662dd293b40578ccornelius
160459d709d503bab6e2b61931737e662dd293b40578ccornelius    return winid;
160559d709d503bab6e2b61931737e662dd293b40578ccornelius}
160659d709d503bab6e2b61931737e662dd293b40578ccornelius
160759d709d503bab6e2b61931737e662dd293b40578ccornelius#define MAX_WINDOWS_ID_SIZE 128
160859d709d503bab6e2b61931737e662dd293b40578ccornelius
160959d709d503bab6e2b61931737e662dd293b40578ccorneliusUnicodeString&
161059d709d503bab6e2b61931737e662dd293b40578ccorneliusTimeZone::getIDForWindowsID(const UnicodeString& winid, const char* region, UnicodeString& id, UErrorCode& status) {
161159d709d503bab6e2b61931737e662dd293b40578ccornelius    id.remove();
161259d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_FAILURE(status)) {
161359d709d503bab6e2b61931737e662dd293b40578ccornelius        return id;
161459d709d503bab6e2b61931737e662dd293b40578ccornelius    }
161559d709d503bab6e2b61931737e662dd293b40578ccornelius
161659d709d503bab6e2b61931737e662dd293b40578ccornelius    UResourceBundle *zones = ures_openDirect(NULL, "windowsZones", &status);
161759d709d503bab6e2b61931737e662dd293b40578ccornelius    ures_getByKey(zones, "mapTimezones", zones, &status);
161859d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_FAILURE(status)) {
161959d709d503bab6e2b61931737e662dd293b40578ccornelius        ures_close(zones);
162059d709d503bab6e2b61931737e662dd293b40578ccornelius        return id;
162159d709d503bab6e2b61931737e662dd293b40578ccornelius    }
162259d709d503bab6e2b61931737e662dd293b40578ccornelius
162359d709d503bab6e2b61931737e662dd293b40578ccornelius    UErrorCode tmperr = U_ZERO_ERROR;
162459d709d503bab6e2b61931737e662dd293b40578ccornelius    char winidKey[MAX_WINDOWS_ID_SIZE];
162559d709d503bab6e2b61931737e662dd293b40578ccornelius    int32_t winKeyLen = winid.extract(0, winid.length(), winidKey, sizeof(winidKey) - 1, US_INV);
162659d709d503bab6e2b61931737e662dd293b40578ccornelius
162759d709d503bab6e2b61931737e662dd293b40578ccornelius    if (winKeyLen == 0 || winKeyLen >= (int32_t)sizeof(winidKey)) {
162859d709d503bab6e2b61931737e662dd293b40578ccornelius        ures_close(zones);
162959d709d503bab6e2b61931737e662dd293b40578ccornelius        return id;
163059d709d503bab6e2b61931737e662dd293b40578ccornelius    }
163159d709d503bab6e2b61931737e662dd293b40578ccornelius    winidKey[winKeyLen] = 0;
163259d709d503bab6e2b61931737e662dd293b40578ccornelius
163359d709d503bab6e2b61931737e662dd293b40578ccornelius    ures_getByKey(zones, winidKey, zones, &tmperr); // use tmperr, because windows mapping might not
163459d709d503bab6e2b61931737e662dd293b40578ccornelius                                                    // be avaiable by design
163559d709d503bab6e2b61931737e662dd293b40578ccornelius    if (U_FAILURE(tmperr)) {
163659d709d503bab6e2b61931737e662dd293b40578ccornelius        ures_close(zones);
163759d709d503bab6e2b61931737e662dd293b40578ccornelius        return id;
163859d709d503bab6e2b61931737e662dd293b40578ccornelius    }
163959d709d503bab6e2b61931737e662dd293b40578ccornelius
164059d709d503bab6e2b61931737e662dd293b40578ccornelius    const UChar *tzid = NULL;
164159d709d503bab6e2b61931737e662dd293b40578ccornelius    int32_t len = 0;
164259d709d503bab6e2b61931737e662dd293b40578ccornelius    UBool gotID = FALSE;
164359d709d503bab6e2b61931737e662dd293b40578ccornelius    if (region) {
164459d709d503bab6e2b61931737e662dd293b40578ccornelius        const UChar *tzids = ures_getStringByKey(zones, region, &len, &tmperr); // use tmperr, because
164559d709d503bab6e2b61931737e662dd293b40578ccornelius                                                                                // regional mapping is optional
164659d709d503bab6e2b61931737e662dd293b40578ccornelius        if (U_SUCCESS(tmperr)) {
164759d709d503bab6e2b61931737e662dd293b40578ccornelius            // first ID delimited by space is the defasult one
164859d709d503bab6e2b61931737e662dd293b40578ccornelius            const UChar *end = u_strchr(tzids, (UChar)0x20);
164959d709d503bab6e2b61931737e662dd293b40578ccornelius            if (end == NULL) {
165059d709d503bab6e2b61931737e662dd293b40578ccornelius                id.setTo(tzids, -1);
165159d709d503bab6e2b61931737e662dd293b40578ccornelius            } else {
165259d709d503bab6e2b61931737e662dd293b40578ccornelius                id.setTo(tzids, end - tzids);
165359d709d503bab6e2b61931737e662dd293b40578ccornelius            }
165459d709d503bab6e2b61931737e662dd293b40578ccornelius            gotID = TRUE;
165559d709d503bab6e2b61931737e662dd293b40578ccornelius        }
165659d709d503bab6e2b61931737e662dd293b40578ccornelius    }
165759d709d503bab6e2b61931737e662dd293b40578ccornelius
165859d709d503bab6e2b61931737e662dd293b40578ccornelius    if (!gotID) {
165959d709d503bab6e2b61931737e662dd293b40578ccornelius        tzid = ures_getStringByKey(zones, "001", &len, &status);    // using status, because "001" must be
166059d709d503bab6e2b61931737e662dd293b40578ccornelius                                                                // available at this point
166159d709d503bab6e2b61931737e662dd293b40578ccornelius        if (U_SUCCESS(status)) {
166259d709d503bab6e2b61931737e662dd293b40578ccornelius            id.setTo(tzid, len);
166359d709d503bab6e2b61931737e662dd293b40578ccornelius        }
166459d709d503bab6e2b61931737e662dd293b40578ccornelius    }
166559d709d503bab6e2b61931737e662dd293b40578ccornelius
166659d709d503bab6e2b61931737e662dd293b40578ccornelius    ures_close(zones);
166759d709d503bab6e2b61931737e662dd293b40578ccornelius    return id;
166859d709d503bab6e2b61931737e662dd293b40578ccornelius}
166959d709d503bab6e2b61931737e662dd293b40578ccornelius#endif /* U_HIDE_DRAFT_API */
167059d709d503bab6e2b61931737e662dd293b40578ccornelius
167159d709d503bab6e2b61931737e662dd293b40578ccornelius
1672b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste QueruU_NAMESPACE_END
1673b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1674b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_FORMATTING */
1675b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru
1676b13da9df870a61b11249bf741347908dbea0edd8Jean-Baptiste Queru//eof
1677