Source Code Cross Referenced for ZoneMeta.java in  » Internationalization-Localization » icu4j » com » ibm » icu » impl » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Internationalization Localization » icu4j » com.ibm.icu.impl 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         **********************************************************************
003:         * Copyright (c) 2003-2006, International Business Machines
004:         * Corporation and others.  All Rights Reserved.
005:         **********************************************************************
006:         * Author: Alan Liu
007:         * Created: September 4 2003
008:         * Since: ICU 2.8
009:         **********************************************************************
010:         */
011:        package com.ibm.icu.impl;
012:
013:        import java.text.ParsePosition;
014:        import java.util.Arrays;
015:        import java.util.ArrayList;
016:        import java.util.Collections;
017:        import java.util.HashMap;
018:        import java.util.Map;
019:        import java.util.MissingResourceException;
020:        import java.util.Set;
021:        import java.util.TreeMap;
022:        import java.util.TreeSet;
023:        import java.util.Vector;
024:
025:        import com.ibm.icu.text.MessageFormat;
026:        import com.ibm.icu.text.NumberFormat;
027:        import com.ibm.icu.text.SimpleDateFormat;
028:        import com.ibm.icu.util.SimpleTimeZone;
029:        import com.ibm.icu.util.TimeZone;
030:        import com.ibm.icu.util.ULocale;
031:        import com.ibm.icu.util.UResourceBundle;
032:
033:        /**
034:         * This class, not to be instantiated, implements the meta-data
035:         * missing from the underlying core JDK implementation of time zones.
036:         * There are two missing features: Obtaining a list of available zones
037:         * for a given country (as defined by the Olson database), and
038:         * obtaining a list of equivalent zones for a given zone (as defined
039:         * by Olson links).
040:         *
041:         * This class uses a data class, ZoneMetaData, which is created by the
042:         * tool tz2icu.
043:         *
044:         * @author Alan Liu
045:         * @since ICU 2.8
046:         */
047:        public final class ZoneMeta {
048:            private static final boolean ASSERT = false;
049:
050:            /**
051:             * Returns a String array containing all system TimeZone IDs
052:             * associated with the given country.  These IDs may be passed to
053:             * <code>TimeZone.getTimeZone()</code> to construct the
054:             * corresponding TimeZone object.
055:             * @param country a two-letter ISO 3166 country code, or <code>null</code>
056:             * to return zones not associated with any country
057:             * @return an array of IDs for system TimeZones in the given
058:             * country.  If there are none, return a zero-length array.
059:             */
060:            public static synchronized String[] getAvailableIDs(String country) {
061:                if (!getOlsonMeta()) {
062:                    return EMPTY;
063:                }
064:                try {
065:                    ICUResourceBundle top = (ICUResourceBundle) ICUResourceBundle
066:                            .getBundleInstance(ICUResourceBundle.ICU_BASE_NAME,
067:                                    "zoneinfo",
068:                                    ICUResourceBundle.ICU_DATA_CLASS_LOADER);
069:                    ICUResourceBundle regions = top.get(kREGIONS);
070:                    ICUResourceBundle names = top.get(kNAMES); // dereference Zones section
071:                    ICUResourceBundle temp = regions.get(country);
072:                    int[] vector = temp.getIntVector();
073:                    if (ASSERT)
074:                        Assert.assrt("vector.length>0", vector.length > 0);
075:                    String[] ret = new String[vector.length];
076:                    for (int i = 0; i < vector.length; ++i) {
077:                        if (ASSERT)
078:                            Assert
079:                                    .assrt(
080:                                            "vector[i] >= 0 && vector[i] < OLSON_ZONE_COUNT",
081:                                            vector[i] >= 0
082:                                                    && vector[i] < OLSON_ZONE_COUNT);
083:                        ret[i] = names.getString(vector[i]);
084:                    }
085:                    return ret;
086:                } catch (MissingResourceException ex) {
087:                    //throw away the exception
088:                }
089:                return EMPTY;
090:            }
091:
092:            public static synchronized String[] getAvailableIDs() {
093:                if (!getOlsonMeta()) {
094:                    return EMPTY;
095:                }
096:                try {
097:                    ICUResourceBundle top = (ICUResourceBundle) ICUResourceBundle
098:                            .getBundleInstance(ICUResourceBundle.ICU_BASE_NAME,
099:                                    "zoneinfo",
100:                                    ICUResourceBundle.ICU_DATA_CLASS_LOADER);
101:                    ICUResourceBundle names = top.get(kNAMES); // dereference Zones section
102:                    return names.getStringArray();
103:                } catch (MissingResourceException ex) {
104:                    //throw away the exception
105:                }
106:                return EMPTY;
107:            }
108:
109:            public static synchronized String[] getAvailableIDs(int offset) {
110:                Vector vector = new Vector();
111:                for (int i = 0; i < OLSON_ZONE_COUNT; ++i) {
112:                    String unistr;
113:                    if ((unistr = getID(i)) != null) {
114:                        // This is VERY inefficient.
115:                        TimeZone z = TimeZone.getTimeZone(unistr);
116:                        // Make sure we get back the ID we wanted (if the ID is
117:                        // invalid we get back GMT).
118:                        if (z != null && z.getID().equals(unistr)
119:                                && z.getRawOffset() == offset) {
120:                            vector.add(unistr);
121:                        }
122:                    }
123:                }
124:                if (!vector.isEmpty()) {
125:                    String[] strings = new String[vector.size()];
126:                    return (String[]) vector.toArray(strings);
127:                }
128:                return EMPTY;
129:            }
130:
131:            private static String getID(int i) {
132:                try {
133:                    ICUResourceBundle top = (ICUResourceBundle) ICUResourceBundle
134:                            .getBundleInstance(ICUResourceBundle.ICU_BASE_NAME,
135:                                    "zoneinfo",
136:                                    ICUResourceBundle.ICU_DATA_CLASS_LOADER);
137:                    ICUResourceBundle names = top.get(kNAMES); // dereference Zones section
138:                    return names.getString(i);
139:                } catch (MissingResourceException ex) {
140:                    //throw away the exception
141:                }
142:                return null;
143:            }
144:
145:            /**
146:             * Returns the number of IDs in the equivalency group that
147:             * includes the given ID.  An equivalency group contains zones
148:             * that behave identically to the given zone.
149:             *
150:             * <p>If there are no equivalent zones, then this method returns
151:             * 0.  This means either the given ID is not a valid zone, or it
152:             * is and there are no other equivalent zones.
153:             * @param id a system time zone ID
154:             * @return the number of zones in the equivalency group containing
155:             * 'id', or zero if there are no equivalent zones.
156:             * @see #getEquivalentID
157:             */
158:            public static synchronized int countEquivalentIDs(String id) {
159:
160:                ICUResourceBundle res = openOlsonResource(id);
161:                int size = res.getSize();
162:                if (size == 4 || size == 6) {
163:                    ICUResourceBundle r = res.get(size - 1);
164:                    //result = ures_getSize(&r); // doesn't work
165:                    int[] v = r.getIntVector();
166:                    return v.length;
167:                }
168:                return 0;
169:            }
170:
171:            /**
172:             * Returns an ID in the equivalency group that includes the given
173:             * ID.  An equivalency group contains zones that behave
174:             * identically to the given zone.
175:             *
176:             * <p>The given index must be in the range 0..n-1, where n is the
177:             * value returned by <code>countEquivalentIDs(id)</code>.  For
178:             * some value of 'index', the returned value will be equal to the
179:             * given id.  If the given id is not a valid system time zone, or
180:             * if 'index' is out of range, then returns an empty string.
181:             * @param id a system time zone ID
182:             * @param index a value from 0 to n-1, where n is the value
183:             * returned by <code>countEquivalentIDs(id)</code>
184:             * @return the ID of the index-th zone in the equivalency group
185:             * containing 'id', or an empty string if 'id' is not a valid
186:             * system ID or 'index' is out of range
187:             * @see #countEquivalentIDs
188:             */
189:            public static synchronized String getEquivalentID(String id,
190:                    int index) {
191:                String result = "";
192:                ICUResourceBundle res = openOlsonResource(id);
193:                int zone = -1;
194:                int size = res.getSize();
195:                if (size == 4 || size == 6) {
196:                    ICUResourceBundle r = res.get(size - 1);
197:                    int[] v = r.getIntVector();
198:                    if (index >= 0 && index < size && getOlsonMeta()) {
199:                        zone = v[index];
200:                    }
201:                }
202:                if (zone >= 0) {
203:                    ICUResourceBundle top = (ICUResourceBundle) ICUResourceBundle
204:                            .getBundleInstance(ICUResourceBundle.ICU_BASE_NAME,
205:                                    "zoneinfo",
206:                                    ICUResourceBundle.ICU_DATA_CLASS_LOADER);
207:                    ICUResourceBundle ares = top.get(kNAMES); // dereference Zones section
208:                    result = ares.getString(zone);
209:
210:                }
211:                return result;
212:            }
213:
214:            /**
215:             * Create the equivalency map.
216:             *
217:            private static void createEquivMap() {
218:                EQUIV_MAP = new TreeMap();
219:
220:                // try leaving all ids as valid
221:            //         Set valid = getValidIDs();
222:
223:                ArrayList list = new ArrayList(); // reuse this below
224:
225:                for (int i=0; i<ZoneMetaData.EQUIV.length; ++i) {
226:                    String[] z = ZoneMetaData.EQUIV[i];
227:                    list.clear();
228:                    for (int j=0; j<z.length; ++j) {
229:            //                  if (valid.contains(z[j])) {
230:                            list.add(z[j]);
231:            //                  }
232:                    }
233:                    if (list.size() > 1) {
234:                        String[] a = (String[]) list.toArray(EMPTY);
235:                        for (int j=0; j<a.length; ++j) {
236:                            EQUIV_MAP.put(a[j], a);
237:                        }
238:                    }
239:                }
240:            }
241:             */
242:            private static String[] getCanonicalInfo(String id) {
243:                if (canonicalMap == null) {
244:                    Map m = new HashMap();
245:                    for (int i = 0; i < ZoneInfoExt.CLDR_INFO.length; ++i) {
246:                        String[] clist = ZoneInfoExt.CLDR_INFO[i];
247:                        String c = clist[0];
248:                        m.put(c, clist);
249:                        for (int j = 3; j < clist.length; ++j) {
250:                            m.put(clist[j], clist);
251:                        }
252:                    }
253:                    synchronized (ZoneMeta.class) {
254:                        canonicalMap = m;
255:                    }
256:                }
257:
258:                return (String[]) canonicalMap.get(id);
259:            }
260:
261:            private static Map canonicalMap = null;
262:
263:            /**
264:             * Return the canonical id for this tzid, which might be the id itself.
265:             * If there is no canonical id for it, return the passed-in id.
266:             */
267:            public static String getCanonicalID(String tzid) {
268:                String[] info = getCanonicalInfo(tzid);
269:                if (info != null) {
270:                    return info[0];
271:                }
272:                return tzid;
273:            }
274:
275:            /**
276:             * Return the canonical country code for this tzid.  If we have none, or if the time zone
277:             * is not associated with a country, return null.
278:             */
279:            public static String getCanonicalCountry(String tzid) {
280:                String[] info = getCanonicalInfo(tzid);
281:                if (info != null) {
282:                    return info[1];
283:                }
284:                return null;
285:            }
286:
287:            /**
288:             * Return the country code if this is a 'single' time zone that can fallback to just
289:             * the country, otherwise return null.  (Note, one must also check the locale data
290:             * to see that there is a localization for the country in order to implement
291:             * tr#35 appendix J step 5.)
292:             */
293:            public static String getSingleCountry(String tzid) {
294:                String[] info = getCanonicalInfo(tzid);
295:                if (info != null && info[2] != null) {
296:                    return info[1];
297:                }
298:                return null;
299:            }
300:
301:            /**
302:             * Handle fallbacks for generic time (rules E.. G)
303:             */
304:            public static String displayFallback(String tzid, String city,
305:                    ULocale locale) {
306:                String[] info = getCanonicalInfo(tzid);
307:                if (info == null) {
308:                    return null; // error
309:                }
310:
311:                String country_code = info[1];
312:                if (country_code == null) {
313:                    return null; // error!   
314:                }
315:
316:                String country = null;
317:                if (country_code != null) {
318:                    ICUResourceBundle rb = (ICUResourceBundle) UResourceBundle
319:                            .getBundleInstance(ICUResourceBundle.ICU_BASE_NAME,
320:                                    locale);
321:                    if (rb.getLoadingStatus() != rb.FROM_ROOT
322:                            && rb.getLoadingStatus() != rb.FROM_DEFAULT) {
323:                        country = ULocale.getDisplayCountry("xx_"
324:                                + country_code, locale);
325:                    }
326:                    if (country == null || country.length() == 0)
327:                        country = country_code;
328:                }
329:
330:                // This is not behavior specified in tr35, but behavior added by Mark.  
331:                // TR35 says to display the country _only_ if there is a localization.
332:                if (info[2] != null) { // single country
333:                    return displayRegion(country, locale);
334:                }
335:
336:                if (city == null) {
337:                    city = tzid.substring(tzid.lastIndexOf('/') + 1).replace(
338:                            '_', ' ');
339:                }
340:
341:                String flbPat = getTZLocalizationInfo(locale, FALLBACK_FORMAT);
342:                MessageFormat mf = new MessageFormat(flbPat);
343:
344:                return mf.format(new Object[] { city, country });
345:            }
346:
347:            public static String displayRegion(String cityOrCountry,
348:                    ULocale locale) {
349:                String regPat = getTZLocalizationInfo(locale, REGION_FORMAT);
350:                MessageFormat mf = new MessageFormat(regPat);
351:                return mf.format(new Object[] { cityOrCountry });
352:            }
353:
354:            public static String displayGMT(long value, ULocale locale) {
355:                String msgpat = getTZLocalizationInfo(locale, GMT);
356:                String dtepat = getTZLocalizationInfo(locale, HOUR);
357:
358:                int n = dtepat.indexOf(';');
359:                if (n != -1) {
360:                    if (value < 0) {
361:                        value = -value;
362:                        dtepat = dtepat.substring(n + 1);
363:                    } else {
364:                        dtepat = dtepat.substring(0, n);
365:                    }
366:                }
367:
368:                final long mph = 3600000;
369:                final long mpm = 60000;
370:
371:                SimpleDateFormat sdf = new SimpleDateFormat(dtepat, locale);
372:                sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
373:                String res = sdf.format(new Long(value));
374:                MessageFormat mf = new MessageFormat(msgpat);
375:                res = mf.format(new Object[] { res });
376:                return res;
377:            }
378:
379:            public static final String HOUR = "hourFormat", GMT = "gmtFormat",
380:                    REGION_FORMAT = "regionFormat",
381:                    FALLBACK_FORMAT = "fallbackFormat",
382:                    ZONE_STRINGS = "zoneStrings", FORWARD_SLASH = "/";
383:
384:            /**
385:             * Get the index'd tz datum for this locale.  Index must be one of the 
386:             * values PREFIX, HOUR, GMT, REGION_FORMAT, FALLBACK_FORMAT
387:             */
388:            public static String getTZLocalizationInfo(ULocale locale,
389:                    String format) {
390:                ICUResourceBundle bundle = (ICUResourceBundle) ICUResourceBundle
391:                        .getBundleInstance(locale);
392:                return bundle.getStringWithFallback(ZONE_STRINGS
393:                        + FORWARD_SLASH + format);
394:            }
395:
396:            private static Set getValidIDs() {
397:                // Construct list of time zones that are valid, according
398:                // to the current underlying core JDK.  We have to do this
399:                // at runtime since we don't know what we're running on.
400:                Set valid = new TreeSet();
401:                valid.addAll(Arrays
402:                        .asList(java.util.TimeZone.getAvailableIDs()));
403:                return valid;
404:            }
405:
406:            /**
407:             * Empty string array.
408:             */
409:            private static final String[] EMPTY = new String[0];
410:
411:            /**
412:             * Given an ID, open the appropriate resource for the given time zone.
413:             * Dereference aliases if necessary.
414:             * @param id zone id
415:             * @param res resource, which must be ready for use (initialized but not open)
416:             * @return top-level resource bundle
417:             */
418:            public static ICUResourceBundle openOlsonResource(String id) {
419:                if (!getOlsonMeta()) {
420:                    return null;
421:                }
422:                ICUResourceBundle top = (ICUResourceBundle) ICUResourceBundle
423:                        .getBundleInstance(ICUResourceBundle.ICU_BASE_NAME,
424:                                "zoneinfo",
425:                                ICUResourceBundle.ICU_DATA_CLASS_LOADER);
426:                ICUResourceBundle res = getZoneByName(top, id);
427:                // Dereference if this is an alias.  Docs say result should be 1
428:                // but it is 0 in 2.8 (?).
429:                if (res.getSize() <= 1 && getOlsonMeta(top)) {
430:                    int deref = res.getInt() + 0;
431:                    ICUResourceBundle ares = top.get(kZONES); // dereference Zones section
432:                    res = ares.get(deref);
433:                }
434:                return res;
435:            }
436:
437:            /**
438:             * Fetch a specific zone by name.  Replaces the getByKey call. 
439:             * @param top Top timezone resource
440:             * @param id Time zone ID
441:             * @return the zone's bundle if found, or undefined if error.  Reuses oldbundle.
442:             */
443:            private static ICUResourceBundle getZoneByName(
444:                    ICUResourceBundle top, String id) {
445:                // load the Rules object
446:                ICUResourceBundle tmp = top.get(kNAMES);
447:
448:                // search for the string
449:                int idx = findInStringArray(tmp, id);
450:
451:                if ((idx == -1)) {
452:                    // not found 
453:                    throw new MissingResourceException(kNAMES, tmp.resPath, id);
454:                    //ures_close(oldbundle);
455:                    //oldbundle = NULL;
456:                } else {
457:                    tmp = top.get(kZONES); // get Zones object from top
458:                    tmp = tmp.get(idx); // get nth Zone object
459:                }
460:                return tmp;
461:            }
462:
463:            private static int findInStringArray(ICUResourceBundle array,
464:                    String id) {
465:                int start = 0;
466:                int limit = array.getSize();
467:                int mid;
468:                String u = null;
469:                int lastMid = Integer.MAX_VALUE;
470:                if ((limit < 1)) {
471:                    return -1;
472:                }
473:                for (;;) {
474:                    mid = (int) ((start + limit) / 2);
475:                    if (lastMid == mid) { /* Have we moved? */
476:                        break; /* We haven't moved, and it wasn't found. */
477:                    }
478:                    lastMid = mid;
479:                    u = array.getString(mid);
480:                    if (u == null) {
481:                        break;
482:                    }
483:                    int r = id.compareTo(u);
484:                    if (r == 0) {
485:                        return mid;
486:                    } else if (r < 0) {
487:                        limit = mid;
488:                    } else {
489:                        start = mid;
490:                    }
491:                }
492:                return -1;
493:            }
494:
495:            private static final String kZONEINFO = "zoneinfo";
496:            private static final String kREGIONS = "Regions";
497:            private static final String kZONES = "Zones";
498:            private static final String kRULES = "Rules";
499:            private static final String kNAMES = "Names";
500:            private static final String kDEFAULT = "Default";
501:            private static final String kGMT_ID = "GMT";
502:            private static final String kCUSTOM_ID = "Custom";
503:            //private static ICUResourceBundle zoneBundle = null;
504:            private static java.util.Enumeration idEnum = null;
505:            private static SoftCache zoneCache = new SoftCache();
506:            /**
507:             * The Olson data is stored the "zoneinfo" resource bundle.
508:             * Sub-resources are organized into three ranges of data: Zones, final
509:             * rules, and country tables.  There is also a meta-data resource
510:             * which has 3 integers: The number of zones, rules, and countries,
511:             * respectively.  The country count includes the non-country 'Default'.
512:             */
513:            static int OLSON_ZONE_START = -1; // starting index of zones
514:            static int OLSON_ZONE_COUNT = 0; // count of zones
515:
516:            /**
517:             * Given a pointer to an open "zoneinfo" resource, load up the Olson
518:             * meta-data. Return true if successful.
519:             */
520:            private static boolean getOlsonMeta(ICUResourceBundle top) {
521:                if (OLSON_ZONE_START < 0) {
522:                    ICUResourceBundle res = top.get(kZONES);
523:                    OLSON_ZONE_COUNT = res.getSize();
524:                    OLSON_ZONE_START = 0;
525:                }
526:                return (OLSON_ZONE_START >= 0);
527:            }
528:
529:            /**
530:             * Load up the Olson meta-data. Return true if successful.
531:             */
532:            private static boolean getOlsonMeta() {
533:                ICUResourceBundle top = (ICUResourceBundle) ICUResourceBundle
534:                        .getBundleInstance(ICUResourceBundle.ICU_BASE_NAME,
535:                                "zoneinfo",
536:                                ICUResourceBundle.ICU_DATA_CLASS_LOADER);
537:                if (OLSON_ZONE_START < 0) {
538:                    getOlsonMeta(top);
539:                }
540:                return (OLSON_ZONE_START >= 0);
541:            }
542:
543:            /**
544:             * Lookup the given name in our system zone table.  If found,
545:             * instantiate a new zone of that name and return it.  If not
546:             * found, return 0.
547:             */
548:            public static TimeZone getSystemTimeZone(String id) {
549:                TimeZone z = (TimeZone) zoneCache.get(id);
550:                if (z == null) {
551:                    try {
552:                        ICUResourceBundle top = (ICUResourceBundle) ICUResourceBundle
553:                                .getBundleInstance(
554:                                        ICUResourceBundle.ICU_BASE_NAME,
555:                                        "zoneinfo",
556:                                        ICUResourceBundle.ICU_DATA_CLASS_LOADER);
557:                        ICUResourceBundle res = openOlsonResource(id);
558:                        z = new OlsonTimeZone(top, res);
559:                        z.setID(id);
560:                        zoneCache.put(id, z);
561:                    } catch (Exception ex) {
562:                        return null;
563:                    }
564:                }
565:                return (TimeZone) z.clone();
566:            }
567:
568:            public static TimeZone getGMT() {
569:                TimeZone z = new SimpleTimeZone(0, kGMT_ID);
570:                z.setID(kGMT_ID);
571:                return z;
572:            }
573:
574:            /**
575:             * Parse a custom time zone identifier and return a corresponding zone.
576:             * @param id a string of the form GMT[+-]hh:mm, GMT[+-]hhmm, or
577:             * GMT[+-]hh.
578:             * @return a newly created SimpleTimeZone with the given offset and
579:             * no Daylight Savings Time, or null if the id cannot be parsed.
580:             */
581:            public static TimeZone getCustomTimeZone(String id) {
582:
583:                NumberFormat numberFormat = null;
584:
585:                String idUppercase = id.toUpperCase();
586:
587:                if (id.length() > kGMT_ID.length()
588:                        && idUppercase.startsWith(kGMT_ID)) {
589:                    ParsePosition pos = new ParsePosition(kGMT_ID.length());
590:                    boolean negative = false;
591:                    long offset;
592:
593:                    if (id.charAt(pos.getIndex()) == 0x002D /*'-'*/)
594:                        negative = true;
595:                    else if (id.charAt(pos.getIndex()) != 0x002B /*'+'*/)
596:                        return null;
597:                    pos.setIndex(pos.getIndex() + 1);
598:
599:                    numberFormat = NumberFormat.getInstance();
600:
601:                    numberFormat.setParseIntegerOnly(true);
602:
603:                    // Look for either hh:mm, hhmm, or hh
604:                    int start = pos.getIndex();
605:
606:                    Number n = numberFormat.parse(id, pos);
607:                    if (pos.getIndex() == start) {
608:                        return null;
609:                    }
610:                    offset = n.longValue();
611:
612:                    if (pos.getIndex() < id.length()
613:                            && id.charAt(pos.getIndex()) == 0x003A /*':'*/) {
614:                        // hh:mm
615:                        offset *= 60;
616:                        pos.setIndex(pos.getIndex() + 1);
617:                        int oldPos = pos.getIndex();
618:                        n = numberFormat.parse(id, pos);
619:                        if (pos.getIndex() == oldPos) {
620:                            return null;
621:                        }
622:                        offset += n.longValue();
623:                    } else {
624:                        // hhmm or hh
625:
626:                        // Be strict about interpreting something as hh; it must be
627:                        // an offset < 30, and it must be one or two digits. Thus
628:                        // 0010 is interpreted as 00:10, but 10 is interpreted as
629:                        // 10:00.
630:                        if (offset < 30 && (pos.getIndex() - start) <= 2)
631:                            offset *= 60; // hh, from 00 to 29; 30 is 00:30
632:                        else
633:                            offset = offset % 100 + offset / 100 * 60; // hhmm
634:                    }
635:
636:                    if (negative)
637:                        offset = -offset;
638:
639:                    TimeZone z = new SimpleTimeZone((int) (offset * 60000),
640:                            kCUSTOM_ID);
641:                    z.setID(kCUSTOM_ID);
642:                    return z;
643:                }
644:                return null;
645:            }
646:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.