]> granicus.if.org Git - icu/commitdiff
ICU-10934 The tz database abbreviation support in ICU4C
authorYoshito Umaoka <y.umaoka@gmail.com>
Wed, 23 Jul 2014 21:51:09 +0000 (21:51 +0000)
committerYoshito Umaoka <y.umaoka@gmail.com>
Wed, 23 Jul 2014 21:51:09 +0000 (21:51 +0000)
X-SVN-Rev: 36080

13 files changed:
.gitattributes
icu4c/source/data/Makefile.in
icu4c/source/data/zone/resfiles.mk
icu4c/source/data/zone/tzdbNames.txt [new file with mode: 0644]
icu4c/source/i18n/tzfmt.cpp
icu4c/source/i18n/tznames.cpp
icu4c/source/i18n/tznames_impl.cpp
icu4c/source/i18n/tznames_impl.h
icu4c/source/i18n/ucln_in.h
icu4c/source/i18n/unicode/tzfmt.h
icu4c/source/i18n/unicode/tznames.h
icu4c/source/test/intltest/tzfmttst.cpp
icu4c/source/test/intltest/tzfmttst.h

index e41fb11e9ce4651318fdb9e62f1c3c72587a81f6..a0ecae30e436205dbb814cbc50527dd90f0769d2 100644 (file)
@@ -70,6 +70,7 @@ icu4c/source/data/makedata.vcxproj -text
 icu4c/source/data/makedata.vcxproj.filters -text
 icu4c/source/data/region/pool.res -text
 icu4c/source/data/zone/pool.res -text
+icu4c/source/data/zone/tzdbNames.txt -text
 icu4c/source/extra/uconv/uconv.vcxproj -text
 icu4c/source/extra/uconv/uconv.vcxproj.filters -text
 icu4c/source/i18n/i18n.vcxproj -text
index df97376c20f9423e1ceb04d7bcb2ef5a24a3f434..97b1a48093c541553cda2a533569e94ef16877c5 100644 (file)
@@ -322,7 +322,7 @@ REGION_SRC_FILES = $(REGION_SRC:%=$(REGIONSRCDIR)/%)
 INSTALLED_REGION_FILES = $(REGION_SOURCE:%.txt=%)  $(REGION_SOURCE_LOCAL:%.txt=%)
 endif
 ifdef ZONE_SOURCE
-ZONE_SRC= root.txt $(ZONE_SOURCE) $(ZONE_ALIAS_SOURCE) $(ZONE_SOURCE_LOCAL)
+ZONE_SRC= root.txt $(ZONE_SOURCE) $(ZONE_ALIAS_SOURCE) $(ZONE_SOURCE_LOCAL) tzdbNames.txt
 ZONE_SRC_FILES = $(ZONE_SRC:%=$(ZONESRCDIR)/%)
 INSTALLED_ZONE_FILES = $(ZONE_SOURCE:%.txt=%)  $(ZONE_SOURCE_LOCAL:%.txt=%)
 endif
index 2dd77f50372ab058ab513501aebf53c943879aeb..6b0835ca08e1cb40fd60c6a116e3945f7a47d952 100644 (file)
@@ -116,5 +116,6 @@ ZONE_SOURCE = af.txt agq.txt ak.txt am.txt\
  vai.txt vai_Latn.txt vai_Vaii.txt vi.txt vun.txt\
  xog.txt yav.txt yo.txt zgh.txt zh.txt\
  zh_Hans.txt zh_Hans_HK.txt zh_Hans_MO.txt zh_Hans_SG.txt zh_Hant.txt\
- zh_Hant_HK.txt zh_Hant_MO.txt zu.txt
+ zh_Hant_HK.txt zh_Hant_MO.txt zu.txt\
+ tzdbNames.txt
 
diff --git a/icu4c/source/data/zone/tzdbNames.txt b/icu4c/source/data/zone/tzdbNames.txt
new file mode 100644 (file)
index 0000000..e603fa5
--- /dev/null
@@ -0,0 +1,709 @@
+// ***************************************************************************\r
+// *\r
+// * Copyright (C) 2014 International Business Machines\r
+// * Corporation and others. All Rights Reserved.\r
+// *\r
+// * This file is manually edited for supporting the tz database name\r
+// * compatibility.\r
+// *\r
+// ***************************************************************************#\r
+tzdbNames{\r
+    zoneStrings{\r
+        "meta:Acre"{\r
+            sd{"ACST"}\r
+            ss{"ACT"}\r
+        }\r
+        "meta:Afghanistan"{\r
+            ss{"AFT"}\r
+        }\r
+        "meta:Africa_Central"{\r
+            sd{"CAST"}\r
+            ss{"CAT"}\r
+        }\r
+        "meta:Africa_Eastern"{\r
+            sd{"EAST"}\r
+            ss{"EAT"}\r
+        }\r
+        "meta:Africa_FarWestern"{\r
+            ss{"WAT"}\r
+            parseRegions{""} // this metazone is never used for parsing\r
+        }\r
+        "meta:Africa_Southern"{\r
+            ss{"SAST"}\r
+        }\r
+        "meta:Africa_Western"{\r
+            sd{"WAST"}\r
+            ss{"WAT"}\r
+        }\r
+        "meta:Aktyubinsk"{\r
+            sd{"AKTST"}\r
+            ss{"AKTT"}\r
+        }\r
+        "meta:Alaska"{\r
+            sd{"AKDT"}\r
+            ss{"AKST"}\r
+        }\r
+        "meta:Alaska_Hawaii"{\r
+            sd{"AHDT"}\r
+            ss{"AHST"}\r
+        }\r
+        "meta:Almaty"{\r
+            sd{"ALMST"}\r
+            ss{"ALMT"}\r
+            parseRegions{""} // this metazone is never used for parsing\r
+        }\r
+        "meta:Amazon"{\r
+            sd{"AMST"}\r
+            ss{"AMT"}\r
+        }\r
+        "meta:America_Central"{\r
+            sd{"CDT"}\r
+            ss{"CST"}\r
+        }\r
+        "meta:America_Eastern"{\r
+            sd{"EDT"}\r
+            ss{"EST"}\r
+        }\r
+        "meta:America_Mountain"{\r
+            sd{"MDT"}\r
+            ss{"MST"}\r
+        }\r
+        "meta:America_Pacific"{\r
+            sd{"PDT"}\r
+            ss{"PST"}\r
+        }\r
+        "meta:Anadyr"{\r
+            sd{"ANAST"}\r
+            ss{"ANAT"}\r
+        }\r
+        "meta:Aqtau"{\r
+            sd{"AQTST"}\r
+            ss{"AQTT"}\r
+            parseRegions{""} // this metazone is never used for parsing\r
+        }\r
+        "meta:Aqtobe"{\r
+            sd{"AQTST"}\r
+            ss{"AQTT"}\r
+            parseRegions{""} // this metazone is never used for parsing\r
+        }\r
+        "meta:Arabian"{\r
+            sd{"ADT"}\r
+            ss{"AST"}\r
+            parseRegions{"BH", "IQ", "KW", "QA", "SA", "YE"}\r
+        }\r
+        "meta:Argentina"{\r
+            sd{"ARST"}\r
+            ss{"ART"}\r
+        }\r
+        "meta:Argentina_Western"{\r
+            sd{"WARST"}\r
+            ss{"WART"}\r
+        }\r
+        "meta:Armenia"{\r
+            sd{"AMST"}\r
+            ss{"AMT"}\r
+            parseRegions{"AM"}\r
+        }\r
+        "meta:Ashkhabad"{\r
+            sd{"ASHST"}\r
+            ss{"ASHT"}\r
+        }\r
+        "meta:Atlantic"{\r
+            sd{"ADT"}\r
+            ss{"AST"}\r
+        }\r
+        "meta:Australia_Central"{\r
+            sd{"CST"}\r
+            ss{"CST"}\r
+            parseRegions{"AU"}\r
+        }\r
+        "meta:Australia_CentralWestern"{\r
+            sd{"CWST"}\r
+            ss{"CWST"}\r
+        }\r
+        "meta:Australia_Eastern"{\r
+            sd{"EST"}\r
+            ss{"EST"}\r
+            parseRegions{"AU"}\r
+        }\r
+        "meta:Australia_Western"{\r
+            sd{"WST"}\r
+            ss{"WST"}\r
+        }\r
+        "meta:Azerbaijan"{\r
+            sd{"AZT"}\r
+            ss{"AZST"}\r
+        }\r
+        "meta:Azores"{\r
+            sd{"AZOST"}\r
+            ss{"AZOT"}\r
+        }\r
+        "meta:Baku"{\r
+            sd{"BAKST"}\r
+            ss{"BAKT"}\r
+        }\r
+        "meta:Bangladesh"{\r
+            sd{"BDST"}\r
+            ss{"BDT"}\r
+        }\r
+        "meta:Bering"{\r
+            sd{"BDT"}\r
+            ss{"BST"}\r
+            parseRegions{""} // this metazone is never used for parsing\r
+        }\r
+        "meta:Bhutan"{\r
+            ss{"BTT"}\r
+        }\r
+        "meta:Bolivia"{\r
+            ss{"BOT"}\r
+        }\r
+        "meta:Borneo"{\r
+            ss{"BORT"}\r
+        }\r
+        "meta:Brasilia"{\r
+            sd{"BRST"}\r
+            ss{"BRT"}\r
+        }\r
+        "meta:British"{\r
+            sd{"BST"}\r
+            parseRegions{""} // this metazone is never used for parsing\r
+        }\r
+        "meta:Brunei"{\r
+            ss{"BNT"}\r
+        }\r
+        "meta:Cape_Verde"{\r
+            sd{"CVST"}\r
+            ss{"CVT"}\r
+        }\r
+        "meta:Casey"{\r
+            ss{"CAST"}\r
+            parseRegions{"AQ"}\r
+        }\r
+        "meta:Chamorro"{\r
+            ss{"ChST"}\r
+        }\r
+        "meta:Changbai"{\r
+            ss{"CHAT"}\r
+        }\r
+        "meta:Chatham"{\r
+            sd{"CHAST"}\r
+            ss{"CHADT"}\r
+        }\r
+        "meta:Chile"{\r
+            sd{"CLST"}\r
+            ss{"CLT"}\r
+        }\r
+        "meta:China"{\r
+            sd{"CDT"}\r
+            ss{"CST"}\r
+            parseRegions{"CN", "MO", "TW"}\r
+        }\r
+        "meta:Choibalsan"{\r
+            sd{"CHOST"}\r
+            ss{"CHOT"}\r
+        }\r
+        "meta:Christmas"{\r
+            ss{"CXT"}\r
+        }\r
+        "meta:Cocos"{\r
+            ss{"CCT"}\r
+        }\r
+        "meta:Colombia"{\r
+            sd{"COST"}\r
+            ss{"COT"}\r
+        }\r
+        "meta:Cook"{\r
+            sd{"CKHST"}\r
+            ss{"CKT"}\r
+        }\r
+        "meta:Cuba"{\r
+            sd{"CDT"}\r
+            ss{"CST"}\r
+            parseRegions{"CU"}\r
+        }\r
+        "meta:Dacca"{\r
+            ss{"DACT"}\r
+        }\r
+        "meta:Davis"{\r
+            ss{"DAVT"}\r
+        }\r
+        "meta:Dominican"{\r
+            sd{"EHDT"}\r
+            ss{"EST"}\r
+        }\r
+        "meta:DumontDUrville"{\r
+            ss{"DDUT"}\r
+        }\r
+        "meta:Dushanbe"{\r
+            sd{"DUSST"}\r
+            ss{"DUST"}\r
+        }\r
+        "meta:Dutch_Guiana"{\r
+            ss{"NEGT"}\r
+        }\r
+        "meta:East_Timor"{\r
+            ss{"TLT"}\r
+        }\r
+        "meta:Easter"{\r
+            sd{"EASST"}\r
+            ss{"EAST"}\r
+            parseRegions{"CL"}\r
+        }\r
+        "meta:Ecuador"{\r
+            ss{"ECT"}\r
+        }\r
+        "meta:Europe_Central"{\r
+            sd{"CEST"}\r
+            ss{"CET"}\r
+        }\r
+        "meta:Europe_Eastern"{\r
+            sd{"EEST"}\r
+            ss{"EET"}\r
+        }\r
+        "meta:Europe_Western"{\r
+            sd{"WEST"}\r
+            ss{"WET"}\r
+        }\r
+        "meta:Falkland"{\r
+            ss{"FKST"}\r
+        }\r
+        "meta:Fiji"{\r
+            sd{"FJST"}\r
+            ss{"FJT"}\r
+        }\r
+        "meta:French_Guiana"{\r
+            ss{"GFT"}\r
+        }\r
+        "meta:French_Southern"{\r
+            ss{"TFT"}\r
+        }\r
+        "meta:Frunze"{\r
+            sd{"FRUST"}\r
+            ss{"FRUT"}\r
+        }\r
+        "meta:GMT"{\r
+            ss{"GMT"}\r
+        }\r
+        "meta:Galapagos"{\r
+            ss{"GALT"}\r
+        }\r
+        "meta:Gambier"{\r
+            ss{"GAMT"}\r
+        }\r
+        "meta:Georgia"{\r
+            sd{"GEST"}\r
+            ss{"GET"}\r
+        }\r
+        "meta:Gilbert_Islands"{\r
+            ss{"GILT"}\r
+        }\r
+        "meta:Goose_Bay"{\r
+            sd{"ADT"}\r
+            ss{"AST"}\r
+            parseRegions{"CA"}\r
+        }\r
+        "meta:Greenland_Central"{\r
+            sd{"CGST"}\r
+            ss{"CGT"}\r
+        }\r
+        "meta:Greenland_Eastern"{\r
+            sd{"EGST"}\r
+            ss{"EGT"}\r
+        }\r
+        "meta:Greenland_Western"{\r
+            sd{"WGST"}\r
+            ss{"WGT"}\r
+        }\r
+        "meta:Guam"{\r
+            ss{"GST"}\r
+            parseRegions{""} // this metazone is never used for parsing\r
+        }\r
+        "meta:Gulf"{\r
+            ss{"GST"}\r
+        }\r
+        "meta:Guyana"{\r
+            ss{"GYT"}\r
+        }\r
+        "meta:Hawaii_Aleutian"{\r
+            sd{"HDT"}\r
+            ss{"HST"}\r
+        }\r
+        "meta:Hong_Kong"{\r
+            sd{"HKST"}\r
+            ss{"HKT"}\r
+        }\r
+        "meta:Hovd"{\r
+            sd{"HOVST"}\r
+            ss{"HOVT"}\r
+        }\r
+        "meta:India"{\r
+            ss{"IST"}\r
+        }\r
+        "meta:Indian_Ocean"{\r
+            ss{"IOT"}\r
+        }\r
+        "meta:Indochina"{\r
+            ss{"ICT"}\r
+        }\r
+        "meta:Indonesia_Central"{\r
+            ss{"WITA"}\r
+        }\r
+        "meta:Indonesia_Eastern"{\r
+            ss{"WIT"}\r
+        }\r
+        "meta:Indonesia_Western"{\r
+            ss{"WIB"}\r
+        }\r
+        "meta:Iran"{\r
+            sd{"IRDT"}\r
+            ss{"IRST"}\r
+        }\r
+        "meta:Irkutsk"{\r
+            sd{"IRKST"}\r
+            ss{"IRKT"}\r
+        }\r
+        "meta:Israel"{\r
+            sd{"IDT"}\r
+            ss{"IST"}\r
+            parseRegions{"IL", "PS"}\r
+        }\r
+        "meta:Japan"{\r
+            sd{"JDT"}\r
+            ss{"JST"}\r
+        }\r
+        "meta:Kamchatka"{\r
+            sd{"PETST"}\r
+            ss{"PETT"}\r
+        }\r
+        "meta:Karachi"{\r
+            ss{"KART"}\r
+        }\r
+        "meta:Kashgar"{\r
+            ss{"KAST"}\r
+        }\r
+        "meta:Kazakhstan_Eastern"{\r
+            sd{"ALMST"}\r
+            ss{"ALMT"}\r
+        }\r
+        "meta:Kazakhstan_Western"{\r
+            sd{"AQTST"}\r
+            ss{"AQTT"}\r
+        }\r
+        "meta:Kizilorda"{\r
+            sd{"KIZST"}\r
+            ss{"KIZT"}\r
+        }\r
+        "meta:Korea"{\r
+            sd{"KDT"}\r
+            ss{"KST"}\r
+        }\r
+        "meta:Kosrae"{\r
+            ss{"KOST"}\r
+        }\r
+        "meta:Krasnoyarsk"{\r
+            sd{"KRAST"}\r
+            ss{"KRAT"}\r
+        }\r
+        "meta:Kuybyshev"{\r
+            sd{"KUYST"}\r
+            ss{"KUYT"}\r
+        }\r
+        "meta:Kwajalein"{\r
+            ss{"KWAT"}\r
+        }\r
+        "meta:Kyrgystan"{\r
+            sd{"KGST"}\r
+            ss{"KGT"}\r
+        }\r
+        "meta:Lanka"{\r
+            ss{"LKT"}\r
+        }\r
+        "meta:Liberia"{\r
+            ss{"LRT"}\r
+        }\r
+        "meta:Line_Islands"{\r
+            ss{"LINT"}\r
+        }\r
+        "meta:Long_Shu"{\r
+            ss{"LONT"}\r
+        }\r
+        "meta:Lord_Howe"{\r
+            ss{"LHST"}\r
+        }\r
+        "meta:Macau"{\r
+            sd{"MOST"}\r
+            ss{"MOT"}\r
+        }\r
+        "meta:Macquarie"{\r
+            ss{"MIST"}\r
+        }\r
+        "meta:Magadan"{\r
+            sd{"MAGST"}\r
+            ss{"MAGT"}\r
+        }\r
+        "meta:Malaya"{\r
+            ss{"MALT"}\r
+        }\r
+        "meta:Malaysia"{\r
+            ss{"MYT"}\r
+        }\r
+        "meta:Maldives"{\r
+            ss{"MVT"}\r
+        }\r
+        "meta:Marquesas"{\r
+            ss{"MART"}\r
+        }\r
+        "meta:Marshall_Islands"{\r
+            ss{"MHT"}\r
+        }\r
+        "meta:Mauritius"{\r
+            sd{"MUST"}\r
+            ss{"MUT"}\r
+        }\r
+        "meta:Mawson"{\r
+            ss{"MAWT"}\r
+        }\r
+        "meta:Mexico_Northwest"{\r
+            sd{"PDT"}\r
+            ss{"PST"}\r
+        }\r
+        "meta:Mexico_Pacific"{\r
+            sd{"MDT"}\r
+            ss{"MST"}\r
+            parseRegions{"MX"}\r
+        }\r
+        "meta:Mongolia"{\r
+            sd{"ULAST"}\r
+            ss{"ULAT"}\r
+        }\r
+        "meta:Moscow"{\r
+            sd{"MSD"}\r
+            ss{"MSK"}\r
+        }\r
+        "meta:Myanmar"{\r
+            ss{"MMT"}\r
+        }\r
+        "meta:Nauru"{\r
+            ss{"NRT"}\r
+        }\r
+        "meta:Nepal"{\r
+            ss{"NPT"}\r
+        }\r
+        "meta:New_Caledonia"{\r
+            sd{"NCST"}\r
+            ss{"NCT"}\r
+        }\r
+        "meta:New_Zealand"{\r
+            sd{"NZDT"}\r
+            ss{"NZST"}\r
+        }\r
+        "meta:Newfoundland"{\r
+            sd{"NDT"}\r
+            ss{"NST"}\r
+        }\r
+        "meta:Niue"{\r
+            ss{"NUT"}\r
+        }\r
+        "meta:Norfolk"{\r
+            ss{"NFT"}\r
+        }\r
+        "meta:Noronha"{\r
+            sd{"FNST"}\r
+            ss{"FNT"}\r
+        }\r
+        "meta:North_Mariana"{\r
+            ss{"MPT"}\r
+        }\r
+        "meta:Novosibirsk"{\r
+            sd{"NOVST"}\r
+            ss{"NOVT"}\r
+        }\r
+        "meta:Omsk"{\r
+            sd{"OMSST"}\r
+            ss{"OMST"}\r
+        }\r
+        "meta:Oral"{\r
+            sd{"ORAST"}\r
+            ss{"ORAT"}\r
+        }\r
+        "meta:Pakistan"{\r
+            sd{"PKST"}\r
+            ss{"PKT"}\r
+        }\r
+        "meta:Palau"{\r
+            ss{"PWT"}\r
+        }\r
+        "meta:Papua_New_Guinea"{\r
+            ss{"PGT"}\r
+        }\r
+        "meta:Paraguay"{\r
+            sd{"PYST"}\r
+            ss{"PYT"}\r
+        }\r
+        "meta:Peru"{\r
+            sd{"PEST"}\r
+            ss{"PET"}\r
+        }\r
+        "meta:Philippines"{\r
+            sd{"PHST"}\r
+            ss{"PHT"}\r
+        }\r
+        "meta:Phoenix_Islands"{\r
+            ss{"PHOT"}\r
+        }\r
+        "meta:Pierre_Miquelon"{\r
+            sd{"PMDT"}\r
+            ss{"PMST"}\r
+        }\r
+        "meta:Pitcairn"{\r
+            ss{"PST"}\r
+            parseRegions{"PN"}\r
+        }\r
+        "meta:Ponape"{\r
+            ss{"PONT"}\r
+        }\r
+        "meta:Qyzylorda"{\r
+            sd{"QYZST"}\r
+            ss{"QYZT"}\r
+        }\r
+        "meta:Reunion"{\r
+            ss{"RET"}\r
+        }\r
+        "meta:Rothera"{\r
+            ss{"ROTT"}\r
+        }\r
+        "meta:Sakhalin"{\r
+            sd{"SAKST"}\r
+            ss{"SAKT"}\r
+        }\r
+        "meta:Samara"{\r
+            sd{"SAMST"}\r
+            ss{"SAMT"}\r
+        }\r
+        "meta:Samarkand"{\r
+            sd{"SAMST"}\r
+            ss{"SAMT"}\r
+            parseRegions{"UZ"}\r
+        }\r
+        "meta:Samoa"{\r
+            ss{"SST"}\r
+        }\r
+        "meta:Seychelles"{\r
+            ss{"SCT"}\r
+        }\r
+        "meta:Shevchenko"{\r
+            sd{"SHEST"}\r
+            ss{"SHET"}\r
+        }\r
+        "meta:Singapore"{\r
+            ss{"SGT"}\r
+        }\r
+        "meta:Solomon"{\r
+            ss{"SBT"}\r
+        }\r
+        "meta:South_Georgia"{\r
+            ss{"GST"}\r
+            parseRegions{"GS"}\r
+        }\r
+        "meta:Suriname"{\r
+            ss{"SRT"}\r
+        }\r
+        "meta:Syowa"{\r
+            ss{"SYOT"}\r
+        }\r
+        "meta:Tahiti"{\r
+            ss{"TAHT"}\r
+        }\r
+        "meta:Taipei"{\r
+            sd{"CDT"}\r
+            ss{"CST"}\r
+        }\r
+        "meta:Tajikistan"{\r
+            ss{"TJT"}\r
+        }\r
+        "meta:Tashkent"{\r
+            sd{"TASST"}\r
+            ss{"TAST"}\r
+        }\r
+        "meta:Tbilisi"{\r
+            sd{"TBIST"}\r
+            ss{"TBIT"}\r
+        }\r
+        "meta:Tokelau"{\r
+            ss{"TKT"}\r
+        }\r
+        "meta:Tonga"{\r
+            sd{"TOST"}\r
+            ss{"TOT"}\r
+        }\r
+        "meta:Truk"{\r
+            ss{"CHUT"}\r
+        }\r
+        "meta:Turkey"{\r
+            sd{"TRST"}\r
+            ss{"TRT"}\r
+        }\r
+        "meta:Turkmenistan"{\r
+            sd{"TMST"}\r
+            ss{"TMT"}\r
+        }\r
+        "meta:Tuvalu"{\r
+            ss{"TVT"}\r
+        }\r
+        "meta:Uralsk"{\r
+            sd{"URAST"}\r
+            ss{"URAT"}\r
+        }\r
+        "meta:Uruguay"{\r
+            sd{"UYST"}\r
+            ss{"UYT"}\r
+        }\r
+        "meta:Urumqi"{\r
+            ss{"URUT"}\r
+        }\r
+        "meta:Uzbekistan"{\r
+            sd{"UZST"}\r
+            ss{"UZT"}\r
+        }\r
+        "meta:Vanuatu"{\r
+            sd{"VUST"}\r
+            ss{"VUT"}\r
+        }\r
+        "meta:Venezuela"{\r
+            ss{"VET"}\r
+        }\r
+        "meta:Vladivostok"{\r
+            sd{"VLAST"}\r
+            ss{"VLAT"}\r
+        }\r
+        "meta:Volgograd"{\r
+            sd{"VOLST"}\r
+            ss{"VOLT"}\r
+        }\r
+        "meta:Vostok"{\r
+            ss{"VOST"}\r
+        }\r
+        "meta:Wake"{\r
+            ss{"WAKT"}\r
+        }\r
+        "meta:Wallis"{\r
+            ss{"WFT"}\r
+        }\r
+        "meta:Yakutsk"{\r
+            sd{"YAKST"}\r
+            ss{"YAKT"}\r
+        }\r
+        "meta:Yekaterinburg"{\r
+            sd{"YEKST"}\r
+            ss{"YEKT"}\r
+        }\r
+        "meta:Yerevan"{\r
+            sd{"YERST"}\r
+            ss{"YERT"}\r
+        }\r
+        "meta:Yukon"{\r
+            sd{"YDT"}\r
+            ss{"YST"}\r
+        }\r
+    }\r
+}\r
index a2e8a5936a64ee83b8f20f8e60960222d737064a..6900fdf94ed41f3034b64feaac85d494e4543656 100644 (file)
@@ -1,6 +1,6 @@
 /*
 *******************************************************************************
-* Copyright (C) 2011-2013, International Business Machines Corporation and
+* Copyright (C) 2011-2014, International Business Machines Corporation and
 * others. All Rights Reserved.
 *******************************************************************************
 */
@@ -308,7 +308,8 @@ U_CDECL_END
 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(TimeZoneFormat)
 
 TimeZoneFormat::TimeZoneFormat(const Locale& locale, UErrorCode& status) 
-: fLocale(locale), fTimeZoneNames(NULL), fTimeZoneGenericNames(NULL), fDefParseOptionFlags(0) {
+: fLocale(locale), fTimeZoneNames(NULL), fTimeZoneGenericNames(NULL),
+  fDefParseOptionFlags(0), fTZDBTimeZoneNames(NULL) {
 
     for (int32_t i = 0; i < UTZFMT_PAT_COUNT; i++) {
         fGMTOffsetPatternItems[i] = NULL;
@@ -418,6 +419,7 @@ TimeZoneFormat::TimeZoneFormat(const TimeZoneFormat& other)
 TimeZoneFormat::~TimeZoneFormat() {
     delete fTimeZoneNames;
     delete fTimeZoneGenericNames;
+    delete fTZDBTimeZoneNames;
     for (int32_t i = 0; i < UTZFMT_PAT_COUNT; i++) {
         delete fGMTOffsetPatternItems[i];
     }
@@ -846,6 +848,8 @@ TimeZoneFormat::parse(UTimeZoneFormatStyle style, const UnicodeString& text, Par
     UErrorCode status = U_ZERO_ERROR;
     UnicodeString tzID;
 
+    UBool parseTZDBAbbrev = ((parseOptions & UTZFMT_PARSE_OPTION_TZ_DATABASE_ABBREVIATIONS) != 0);
+
     // Try the specified style
     switch (style) {
     case UTZFMT_STYLE_LOCALIZED_GMT:
@@ -956,6 +960,41 @@ TimeZoneFormat::parse(UTimeZoneFormatStyle style, const UnicodeString& text, Par
                     return TimeZone::createTimeZone(tzID);
                 }
             }
+
+            if (parseTZDBAbbrev && style == UTZFMT_STYLE_SPECIFIC_SHORT) {
+                U_ASSERT((nameTypes & UTZNM_SHORT_STANDARD) != 0);
+                U_ASSERT((nameTypes & UTZNM_SHORT_DAYLIGHT) != 0);
+
+                const TZDBTimeZoneNames *tzdbTimeZoneNames = getTZDBTimeZoneNames(status);
+                if (U_SUCCESS(status)) {
+                    LocalPointer<TimeZoneNames::MatchInfoCollection> tzdbNameMatches(
+                        tzdbTimeZoneNames->find(text, startIdx, nameTypes, status));
+                    if (U_FAILURE(status)) {
+                        pos.setErrorIndex(startIdx);
+                        return NULL;
+                    }
+                    if (!tzdbNameMatches.isNull()) {
+                        int32_t matchIdx = -1;
+                        int32_t matchPos = -1;
+                        for (int32_t i = 0; i < tzdbNameMatches->size(); i++) {
+                            matchPos = startIdx + tzdbNameMatches->getMatchLengthAt(i);
+                            if (matchPos > parsedPos) {
+                                matchIdx = i;
+                                parsedPos = matchPos;
+                            }
+                        }
+                        if (matchIdx >= 0) {
+                            if (timeType) {
+                                *timeType = getTimeType(tzdbNameMatches->getNameTypeAt(matchIdx));
+                            }
+                            pos.setIndex(matchPos);
+                            getTimeZoneID(tzdbNameMatches.getAlias(), matchIdx, tzID);
+                            U_ASSERT(!tzID.isEmpty());
+                            return TimeZone::createTimeZone(tzID);
+                        }
+                    }
+                }
+            }
             break;
         }
     case UTZFMT_STYLE_GENERIC_LONG:
@@ -1168,6 +1207,34 @@ TimeZoneFormat::parse(UTimeZoneFormatStyle style, const UnicodeString& text, Par
                 parsedOffset = UNKNOWN_OFFSET;
             }
         }
+        if (parseTZDBAbbrev && parsedPos < maxPos && (evaluated & STYLE_PARSE_FLAGS[UTZFMT_STYLE_SPECIFIC_SHORT]) == 0) {
+            const TZDBTimeZoneNames *tzdbTimeZoneNames = getTZDBTimeZoneNames(status);
+            if (U_SUCCESS(status)) {
+                LocalPointer<TimeZoneNames::MatchInfoCollection> tzdbNameMatches(
+                    tzdbTimeZoneNames->find(text, startIdx, ALL_SIMPLE_NAME_TYPES, status));
+                if (U_FAILURE(status)) {
+                    pos.setErrorIndex(startIdx);
+                    return NULL;
+                }
+                int32_t tzdbNameMatchIdx = -1;
+                int32_t matchPos = -1;
+                if (!tzdbNameMatches.isNull()) {
+                    for (int32_t i = 0; i < tzdbNameMatches->size(); i++) {
+                        if (startIdx + tzdbNameMatches->getMatchLengthAt(i) > matchPos) {
+                            tzdbNameMatchIdx = i;
+                            matchPos = startIdx + tzdbNameMatches->getMatchLengthAt(i);
+                        }
+                    }
+                }
+                if (parsedPos < matchPos) {
+                    U_ASSERT(tzdbNameMatchIdx >= 0);
+                    parsedPos = matchPos;
+                    getTimeZoneID(tzdbNameMatches.getAlias(), tzdbNameMatchIdx, parsedID);
+                    parsedTimeType = getTimeType(tzdbNameMatches->getNameTypeAt(tzdbNameMatchIdx));
+                    parsedOffset = UNKNOWN_OFFSET;
+                }
+            }
+        }
         // Try generic names
         if (parsedPos < maxPos) {
             int32_t genMatchLen = -1;
@@ -1182,7 +1249,7 @@ TimeZoneFormat::parse(UTimeZoneFormatStyle style, const UnicodeString& text, Par
                 return NULL;
             }
 
-            if (parsedPos < startIdx + genMatchLen) {
+            if (genMatchLen > 0 && parsedPos < startIdx + genMatchLen) {
                 parsedPos = startIdx + genMatchLen;
                 parsedID.setTo(tzID);
                 parsedTimeType = tt;
@@ -1313,6 +1380,27 @@ TimeZoneFormat::getTimeZoneGenericNames(UErrorCode& status) const {
     return fTimeZoneGenericNames;
 }
 
+const TZDBTimeZoneNames*
+TimeZoneFormat::getTZDBTimeZoneNames(UErrorCode& status) const {
+    if (U_FAILURE(status)) {
+        return NULL;
+    }
+
+    umtx_lock(&gLock);
+    if (fTZDBTimeZoneNames == NULL) {
+        TZDBTimeZoneNames *tzdbNames = new TZDBTimeZoneNames(fLocale);
+        if (tzdbNames == NULL) {
+            status = U_MEMORY_ALLOCATION_ERROR;
+        } else {
+            TimeZoneFormat *nonConstThis = const_cast<TimeZoneFormat *>(this);
+            nonConstThis->fTZDBTimeZoneNames = tzdbNames;
+        }
+    }
+    umtx_unlock(&gLock);
+
+    return fTZDBTimeZoneNames;
+}
+
 UnicodeString&
 TimeZoneFormat::formatExemplarLocation(const TimeZone& tz, UnicodeString& name) const {
     UnicodeString location;
@@ -2576,9 +2664,8 @@ TimeZoneFormat::getTimeType(UTimeZoneNameType nameType) {
         return UTZFMT_TIME_TYPE_DAYLIGHT;
 
     default:
-        U_ASSERT(FALSE);
+        return UTZFMT_TIME_TYPE_UNKNOWN;
     }
-    return UTZFMT_TIME_TYPE_UNKNOWN;
 }
 
 UnicodeString&
index bb1e863cd8bb849a34a3dc78e1a6bcb5a01c559b..57bda37fc666326953df2925b05a8d559e8a68fa 100644 (file)
@@ -1,6 +1,6 @@
 /*
 *******************************************************************************
-* Copyright (C) 2011-2013, International Business Machines Corporation and    *
+* Copyright (C) 2011-2014, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */
@@ -291,8 +291,29 @@ TimeZoneNames::~TimeZoneNames() {
 
 TimeZoneNames*
 TimeZoneNames::createInstance(const Locale& locale, UErrorCode& status) {
-    return new TimeZoneNamesDelegate(locale, status);
+    TimeZoneNames *instance = NULL;
+    if (U_SUCCESS(status)) {
+        instance = new TimeZoneNamesDelegate(locale, status);
+        if (instance == NULL && U_SUCCESS(status)) {
+            status = U_MEMORY_ALLOCATION_ERROR;
+        }
+    }
+    return instance;
+}
+
+#ifndef U_HIDE_DRAFT_API
+TimeZoneNames*
+TimeZoneNames::createTZDBInstance(const Locale& locale, UErrorCode& status) {
+    TimeZoneNames *instance = NULL;
+    if (U_SUCCESS(status)) {
+        instance = new TZDBTimeZoneNames(locale);
+        if (instance == NULL && U_SUCCESS(status)) {
+            status = U_MEMORY_ALLOCATION_ERROR;
+        }
+    }
+    return instance;
 }
+#endif /* U_HIDE_DRAFT_API */
 
 UnicodeString&
 TimeZoneNames::getExemplarLocationName(const UnicodeString& tzID, UnicodeString& name) const {
index d11d787cfc7758756d11fa20a7b76d207ba43980..1595d89c549472c01f56da3e3aa7bc63226b7a01 100644 (file)
@@ -1,6 +1,6 @@
 /*
 *******************************************************************************
-* Copyright (C) 2011-2013, International Business Machines Corporation and
+* Copyright (C) 2011-2014, International Business Machines Corporation and
 * others. All Rights Reserved.
 *******************************************************************************
 *
@@ -51,6 +51,36 @@ static const UTimeZoneNameType ALL_NAME_TYPES[] = {
     UTZNM_UNKNOWN // unknown as the last one
 };
 
+// stuff for TZDBTimeZoneNames
+static const char* TZDBNAMES_KEYS[]               = {"ss", "sd"};
+static const int32_t TZDBNAMES_KEYS_SIZE = (sizeof TZDBNAMES_KEYS / sizeof TZDBNAMES_KEYS[0]);
+
+static UMutex gTZDBNamesMapLock = U_MUTEX_INITIALIZER;
+
+static UHashtable* gTZDBNamesMap = NULL;
+static icu::UInitOnce gTZDBNamesMapInitOnce = U_INITONCE_INITIALIZER;
+
+static TextTrieMap* gTZDBNamesTrie = NULL;
+static icu::UInitOnce gTZDBNamesTrieInitOnce = U_INITONCE_INITIALIZER;
+
+U_CDECL_BEGIN
+static UBool U_CALLCONV tzdbTimeZoneNames_cleanup(void) {
+    if (gTZDBNamesMap != NULL) {
+        uhash_close(gTZDBNamesMap);
+        gTZDBNamesMap = NULL;
+    }
+    gTZDBNamesMapInitOnce.reset();
+
+    if (gTZDBNamesTrie != NULL) {
+        delete gTZDBNamesTrie;
+        gTZDBNamesTrie = NULL;
+    }
+    gTZDBNamesTrieInitOnce.reset();
+
+    return TRUE;
+}
+U_CDECL_END
+
 #define DEFAULT_CHARACTERNODE_CAPACITY 1
 
 // ---------------------------------------------------
@@ -799,7 +829,7 @@ ZNameSearchHandler::handleMatch(int32_t matchLength, const CharacterNode *node,
         for (int32_t i = 0; i < valuesCount; i++) {
             ZNameInfo *nameinfo = (ZNameInfo *)node->getValue(i);
             if (nameinfo == NULL) {
-                break;
+                continue;
             }
             if ((nameinfo->type & fTypes) != 0) {
                 // matches a requested type
@@ -986,6 +1016,12 @@ TimeZoneNamesImpl::clone() const {
 
 StringEnumeration*
 TimeZoneNamesImpl::getAvailableMetaZoneIDs(UErrorCode& status) const {
+    return TimeZoneNamesImpl::_getAvailableMetaZoneIDs(status);
+}
+
+// static implementation of getAvailableMetaZoneIDs(UErrorCode&)
+StringEnumeration*
+TimeZoneNamesImpl::_getAvailableMetaZoneIDs(UErrorCode& status) {
     if (U_FAILURE(status)) {
         return NULL;
     }
@@ -998,6 +1034,12 @@ TimeZoneNamesImpl::getAvailableMetaZoneIDs(UErrorCode& status) const {
 
 StringEnumeration*
 TimeZoneNamesImpl::getAvailableMetaZoneIDs(const UnicodeString& tzID, UErrorCode& status) const {
+    return TimeZoneNamesImpl::_getAvailableMetaZoneIDs(tzID, status);
+}
+
+// static implementation of getAvailableMetaZoneIDs(const UnicodeString&, UErrorCode&)
+StringEnumeration*
+TimeZoneNamesImpl::_getAvailableMetaZoneIDs(const UnicodeString& tzID, UErrorCode& status) {
     if (U_FAILURE(status)) {
         return NULL;
     }
@@ -1032,16 +1074,29 @@ TimeZoneNamesImpl::getAvailableMetaZoneIDs(const UnicodeString& tzID, UErrorCode
 
 UnicodeString&
 TimeZoneNamesImpl::getMetaZoneID(const UnicodeString& tzID, UDate date, UnicodeString& mzID) const {
+    return TimeZoneNamesImpl::_getMetaZoneID(tzID, date, mzID);
+}
+
+// static implementation of getMetaZoneID
+UnicodeString&
+TimeZoneNamesImpl::_getMetaZoneID(const UnicodeString& tzID, UDate date, UnicodeString& mzID) {
     ZoneMeta::getMetazoneID(tzID, date, mzID);
     return mzID;
 }
 
 UnicodeString&
 TimeZoneNamesImpl::getReferenceZoneID(const UnicodeString& mzID, const char* region, UnicodeString& tzID) const {
+    return TimeZoneNamesImpl::_getReferenceZoneID(mzID, region, tzID);
+}
+
+// static implementaion of getReferenceZoneID
+UnicodeString&
+TimeZoneNamesImpl::_getReferenceZoneID(const UnicodeString& mzID, const char* region, UnicodeString& tzID) {
     ZoneMeta::getZoneIdByMetazone(mzID, UnicodeString(region, -1, US_INV), tzID);
     return tzID;
 }
 
+
 UnicodeString&
 TimeZoneNamesImpl::getMetaZoneDisplayName(const UnicodeString& mzID,
                                           UTimeZoneNameType type,
@@ -1170,6 +1225,7 @@ TimeZoneNamesImpl::loadMetaZoneNames(const UnicodeString& mzID) {
             if (U_FAILURE(status)) {
                 if (znames != NULL) {
                     delete znames;
+                    znames = NULL;
                 }
             } else if (znames != NULL) {
                 // put the name info into the trie
@@ -1247,6 +1303,7 @@ TimeZoneNamesImpl::loadTimeZoneNames(const UnicodeString& tzID) {
             if (U_FAILURE(status)) {
                 if (tznames != NULL) {
                     delete tznames;
+                    tznames = NULL;
                 }
             } else if (tznames != NULL) {
                 // put the name info into the trie
@@ -1371,6 +1428,589 @@ TimeZoneNamesImpl::getDefaultExemplarLocationName(const UnicodeString& tzID, Uni
     return name;
 }
 
+// ---------------------------------------------------
+// TZDBTimeZoneNames and its supporting classes
+//
+// TZDBTimeZoneNames is an implementation class of
+// TimeZoneNames holding the IANA tz database abbreviations.
+// ---------------------------------------------------
+
+class TZDBNames : public UMemory {
+public:
+    virtual ~TZDBNames();
+
+    static TZDBNames* createInstance(UResourceBundle* rb, const char* key);
+    const UChar* getName(UTimeZoneNameType type) const;
+    const char** getParseRegions(int32_t& numRegions) const;
+
+protected:
+    TZDBNames(const UChar** names, char** regions, int32_t numRegions);
+
+private:
+    const UChar** fNames;
+    char** fRegions;
+    int32_t fNumRegions;
+};
+
+TZDBNames::TZDBNames(const UChar** names, char** regions, int32_t numRegions)
+    :   fNames(names),
+        fRegions(regions),
+        fNumRegions(numRegions) {
+}
+
+TZDBNames::~TZDBNames() {
+    if (fNames != NULL) {
+        uprv_free(fNames);
+    }
+    if (fRegions != NULL) {
+        char **p = fRegions;
+        for (int32_t i = 0; i < fNumRegions; p++, i++) {
+            uprv_free(*p);
+        }
+        uprv_free(fRegions);
+    }
+}
+
+TZDBNames*
+TZDBNames::createInstance(UResourceBundle* rb, const char* key) {
+    if (rb == NULL || key == NULL || *key == 0) {
+        return NULL;
+    }
+
+    UErrorCode status = U_ZERO_ERROR;
+
+    const UChar **names = NULL;
+    char** regions = NULL;
+    int32_t numRegions = 0;
+
+    int32_t len = 0;
+
+    UResourceBundle* rbTable = NULL;
+    rbTable = ures_getByKey(rb, key, rbTable, &status);
+    if (U_FAILURE(status)) {
+        return NULL;
+    }
+
+    names = (const UChar **)uprv_malloc(sizeof(const UChar*) * TZDBNAMES_KEYS_SIZE);
+    UBool isEmpty = TRUE;
+    if (names != NULL) {
+        for (int32_t i = 0; i < TZDBNAMES_KEYS_SIZE; i++) {
+            status = U_ZERO_ERROR;
+            const UChar *value = ures_getStringByKey(rbTable, TZDBNAMES_KEYS[i], &len, &status);
+            if (U_FAILURE(status) || len == 0) {
+                names[i] = NULL;
+            } else {
+                names[i] = value;
+                isEmpty = FALSE;
+            }
+        }
+    }
+
+    if (isEmpty) {
+        if (names != NULL) {
+            uprv_free(names);
+        }
+        return NULL;
+    }
+
+    UResourceBundle *regionsRes = ures_getByKey(rbTable, "parseRegions", NULL, &status);
+    UBool regionError = FALSE;
+    if (U_SUCCESS(status)) {
+        numRegions = ures_getSize(regionsRes);
+        if (numRegions > 0) {
+            regions = (char**)uprv_malloc(sizeof(char*) * numRegions);
+            if (regions != NULL) {
+                char **pRegion = regions;
+                for (int32_t i = 0; i < numRegions; i++, pRegion++) {
+                    *pRegion = NULL;
+                }
+                // filling regions
+                pRegion = regions;
+                for (int32_t i = 0; i < numRegions; i++, pRegion++) {
+                    status = U_ZERO_ERROR;
+                    const UChar *uregion = ures_getStringByIndex(regionsRes, i, &len, &status);
+                    if (U_FAILURE(status)) {
+                        regionError = TRUE;
+                        break;
+                    }
+                    *pRegion = (char*)uprv_malloc(sizeof(char) * (len + 1));
+                    if (*pRegion == NULL) {
+                        regionError = TRUE;
+                        break;
+                    }
+                    u_UCharsToChars(uregion, *pRegion, len);
+                    (*pRegion)[len] = 0;
+                }
+            }
+        }
+    }
+    ures_close(regionsRes);
+    ures_close(rbTable);
+
+    if (regionError) {
+        if (names != NULL) {
+            uprv_free(names);
+        }
+        if (regions != NULL) {
+            char **p = regions;
+            for (int32_t i = 0; i < numRegions; p++, i++) {
+                uprv_free(p);
+            }
+            uprv_free(regions);
+        }
+        return NULL;
+    }
+
+    return new TZDBNames(names, regions, numRegions);
+}
+
+const UChar*
+TZDBNames::getName(UTimeZoneNameType type) const {
+    if (fNames == NULL) {
+        return NULL;
+    }
+    const UChar *name = NULL;
+    switch(type) {
+    case UTZNM_SHORT_STANDARD:
+        name = fNames[0];
+        break;
+    case UTZNM_SHORT_DAYLIGHT:
+        name = fNames[1];
+        break;
+    default:
+        name = NULL;
+    }
+    return name;
+}
+
+const char**
+TZDBNames::getParseRegions(int32_t& numRegions) const {
+    if (fRegions == NULL) {
+        numRegions = 0;
+    } else {
+        numRegions = fNumRegions;
+    }
+    return (const char**)fRegions;
+}
+
+U_CDECL_BEGIN
+/**
+ * TZDBNameInfo stores metazone name information for the IANA abbreviations
+ * in the trie
+ */
+typedef struct TZDBNameInfo {
+    const UChar*        mzID;
+    UTimeZoneNameType   type;
+    UBool               ambiguousType;
+    const char**        parseRegions;
+    int32_t             nRegions;
+} TZDBNameInfo;
+U_CDECL_END
+
+
+class TZDBNameSearchHandler : public TextTrieMapSearchResultHandler {
+public:
+    TZDBNameSearchHandler(uint32_t types, const char* region);
+    virtual ~TZDBNameSearchHandler();
+
+    UBool handleMatch(int32_t matchLength, const CharacterNode *node, UErrorCode &status);
+    TimeZoneNames::MatchInfoCollection* getMatches(int32_t& maxMatchLen);
+
+private:
+    uint32_t fTypes;
+    int32_t fMaxMatchLen;
+    TimeZoneNames::MatchInfoCollection* fResults;
+    const char* fRegion;
+};
+
+TZDBNameSearchHandler::TZDBNameSearchHandler(uint32_t types, const char* region) 
+: fTypes(types), fMaxMatchLen(0), fResults(NULL), fRegion(region) {
+}
+
+TZDBNameSearchHandler::~TZDBNameSearchHandler() {
+    if (fResults != NULL) {
+        delete fResults;
+    }
+}
+
+UBool
+TZDBNameSearchHandler::handleMatch(int32_t matchLength, const CharacterNode *node, UErrorCode &status) {
+    if (U_FAILURE(status)) {
+        return FALSE;
+    }
+
+    TZDBNameInfo *match = NULL;
+    TZDBNameInfo *defaultRegionMatch = NULL;
+
+    if (node->hasValues()) {
+        int32_t valuesCount = node->countValues();
+        for (int32_t i = 0; i < valuesCount; i++) {
+            TZDBNameInfo *ninfo = (TZDBNameInfo *)node->getValue(i);
+            if (ninfo == NULL) {
+                continue;
+            }
+            if ((ninfo->type & fTypes) != 0) {
+                // Some tz database abbreviations are ambiguous. For example,
+                // CST means either Central Standard Time or China Standard Time.
+                // Unlike CLDR time zone display names, this implementation
+                // does not use unique names. And TimeZoneFormat does not expect
+                // multiple results returned for the same time zone type.
+                // For this reason, this implementation resolve one among same
+                // zone type with a same name at this level.
+                if (ninfo->parseRegions == NULL) {
+                    // parseRegions == null means this is the default metazone
+                    // mapping for the abbreviation.
+                    if (defaultRegionMatch == NULL) {
+                        match = defaultRegionMatch = ninfo;
+                    }
+                } else {
+                    UBool matchRegion = FALSE;
+                    // non-default metazone mapping for an abbreviation
+                    // comes with applicable regions. For example, the default
+                    // metazone mapping for "CST" is America_Central,
+                    // but if region is one of CN/MO/TW, "CST" is parsed
+                    // as metazone China (China Standard Time).
+                    for (int32_t i = 0; i < ninfo->nRegions; i++) {
+                        const char *region = ninfo->parseRegions[i];
+                        if (uprv_strcmp(fRegion, region) == 0) {
+                            match = ninfo;
+                            matchRegion = TRUE;
+                            break;
+                        }
+                    }
+                    if (matchRegion) {
+                        break;
+                    }
+                    if (match == NULL) {
+                        match = ninfo;
+                    }
+                }
+            }
+        }
+
+        if (match != NULL) {
+            UTimeZoneNameType ntype = match->type;
+            // Note: Workaround for duplicated standard/daylight names
+            // The tz database contains a few zones sharing a
+            // same name for both standard time and daylight saving
+            // time. For example, Australia/Sydney observes DST,
+            // but "EST" is used for both standard and daylight.
+            // When both SHORT_STANDARD and SHORT_DAYLIGHT are included
+            // in the find operation, we cannot tell which one was
+            // actually matched.
+            // TimeZoneFormat#parse returns a matched name type (standard
+            // or daylight) and DateFormat implementation uses the info to
+            // to adjust actual time. To avoid false type information,
+            // this implementation replaces the name type with SHORT_GENERIC.
+            if (match->ambiguousType
+                    && (ntype == UTZNM_SHORT_STANDARD || ntype == UTZNM_SHORT_DAYLIGHT)
+                    && (fTypes & UTZNM_SHORT_STANDARD) != 0
+                    && (fTypes & UTZNM_SHORT_DAYLIGHT) != 0) {
+                ntype = UTZNM_SHORT_GENERIC;
+            }
+
+            if (fResults == NULL) {
+                fResults = new TimeZoneNames::MatchInfoCollection();
+                if (fResults == NULL) {
+                    status = U_MEMORY_ALLOCATION_ERROR;
+                }
+            }
+            if (U_SUCCESS(status)) {
+                U_ASSERT(fResults != NULL);
+                U_ASSERT(match->mzID != NULL);
+                fResults->addMetaZone(ntype, matchLength, UnicodeString(match->mzID, -1), status);
+                if (U_SUCCESS(status) && matchLength > fMaxMatchLen) {
+                    fMaxMatchLen = matchLength;
+                }
+            }
+        }
+    }
+    return TRUE;
+}
+
+TimeZoneNames::MatchInfoCollection*
+TZDBNameSearchHandler::getMatches(int32_t& maxMatchLen) {
+    // give the ownership to the caller
+    TimeZoneNames::MatchInfoCollection* results = fResults;
+    maxMatchLen = fMaxMatchLen;
+
+    // reset
+    fResults = NULL;
+    fMaxMatchLen = 0;
+    return results;
+}
+
+U_CDECL_BEGIN
+/**
+ * Deleter for TZDBNames
+ */
+static void U_CALLCONV
+deleteTZDBNames(void *obj) {
+    if (obj != EMPTY) {
+        delete (TZDBNames *)obj;
+    }
+}
+
+static void U_CALLCONV initTZDBNamesMap(UErrorCode &status) {
+    gTZDBNamesMap = uhash_open(uhash_hashUChars, uhash_compareUChars, NULL, &status);
+    if (U_FAILURE(status)) {
+        gTZDBNamesMap = NULL;
+        return;
+    }
+    // no key deleters for tzdb name maps
+    uhash_setValueDeleter(gTZDBNamesMap, deleteTZDBNames);
+    ucln_i18n_registerCleanup(UCLN_I18N_TZDBTIMEZONENAMES, tzdbTimeZoneNames_cleanup);
+}
+
+/**
+ * Deleter for TZDBNameInfo
+ */
+static void U_CALLCONV
+deleteTZDBNameInfo(void *obj) {
+    if (obj != NULL) {
+        uprv_free(obj);
+    }
+}
+
+static void U_CALLCONV prepareFind(UErrorCode &status) {
+    if (U_FAILURE(status)) {
+        return;
+    }
+    gTZDBNamesTrie = new TextTrieMap(TRUE, deleteTZDBNameInfo);
+    if (gTZDBNamesTrie == NULL) {
+        status = U_MEMORY_ALLOCATION_ERROR;
+        return;
+    }
+
+    const UnicodeString *mzID;
+    StringEnumeration *mzIDs = TimeZoneNamesImpl::_getAvailableMetaZoneIDs(status);
+    if (U_SUCCESS(status)) {
+        while ((mzID = mzIDs->snext(status)) && U_SUCCESS(status)) {
+            const TZDBNames *names = TZDBTimeZoneNames::getMetaZoneNames(*mzID, status);
+            if (names == NULL) {
+                continue;
+            }
+            const UChar *std = names->getName(UTZNM_SHORT_STANDARD);
+            const UChar *dst = names->getName(UTZNM_SHORT_DAYLIGHT);
+            if (std == NULL && dst == NULL) {
+                continue;
+            }
+            int32_t numRegions = 0;
+            const char **parseRegions = names->getParseRegions(numRegions);
+
+            // The tz database contains a few zones sharing a
+            // same name for both standard time and daylight saving
+            // time. For example, Australia/Sydney observes DST,
+            // but "EST" is used for both standard and daylight.
+            // we need to store the information for later processing.
+            UBool ambiguousType = (std != NULL && dst != NULL && u_strcmp(std, dst) == 0);
+
+            const UChar *uMzID = ZoneMeta::findMetaZoneID(*mzID);
+            if (std != NULL) {
+                TZDBNameInfo *stdInf = (TZDBNameInfo *)uprv_malloc(sizeof(TZDBNameInfo));
+                if (stdInf == NULL) {
+                    status = U_MEMORY_ALLOCATION_ERROR;
+                    break;
+                }
+                stdInf->mzID = uMzID;
+                stdInf->type = UTZNM_SHORT_STANDARD;
+                stdInf->ambiguousType = ambiguousType;
+                stdInf->parseRegions = parseRegions;
+                stdInf->nRegions = numRegions;
+                gTZDBNamesTrie->put(std, stdInf, status);
+            }
+            if (U_SUCCESS(status) && dst != NULL) {
+                TZDBNameInfo *dstInf = (TZDBNameInfo *)uprv_malloc(sizeof(TZDBNameInfo));
+                if (dstInf == NULL) {
+                    status = U_MEMORY_ALLOCATION_ERROR;
+                    break;
+                }
+                dstInf->mzID = uMzID;
+                dstInf->type = UTZNM_SHORT_DAYLIGHT;
+                dstInf->ambiguousType = ambiguousType;
+                dstInf->parseRegions = parseRegions;
+                dstInf->nRegions = numRegions;
+                gTZDBNamesTrie->put(dst, dstInf, status);
+            }
+        }
+    }
+    delete mzIDs;
+
+    if (U_FAILURE(status)) {
+        delete gTZDBNamesTrie;
+        gTZDBNamesTrie = NULL;
+        return;
+    }
+
+    ucln_i18n_registerCleanup(UCLN_I18N_TZDBTIMEZONENAMES, tzdbTimeZoneNames_cleanup);
+}
+
+U_CDECL_END
+
+TZDBTimeZoneNames::TZDBTimeZoneNames(const Locale& locale)
+: fLocale(locale) {
+    UBool useWorld = TRUE;
+    const char* region = fLocale.getCountry();
+    int32_t regionLen = uprv_strlen(region);
+    if (regionLen == 0) {
+        UErrorCode status = U_ZERO_ERROR;
+        char loc[ULOC_FULLNAME_CAPACITY];
+        uloc_addLikelySubtags(fLocale.getName(), loc, sizeof(loc), &status);
+        regionLen = uloc_getCountry(loc, fRegion, sizeof(fRegion), &status);
+        if (U_SUCCESS(status) && regionLen < (int32_t)sizeof(fRegion)) {
+            useWorld = FALSE;
+        }
+    } else if (regionLen < (int32_t)sizeof(fRegion)) {
+        uprv_strcpy(fRegion, region);
+        useWorld = FALSE;
+    }
+    if (useWorld) {
+        uprv_strcpy(fRegion, "001");
+    }
+}
+
+TZDBTimeZoneNames::~TZDBTimeZoneNames() {
+}
+
+UBool
+TZDBTimeZoneNames::operator==(const TimeZoneNames& other) const {
+    if (this == &other) {
+        return TRUE;
+    }
+    // No implementation for now
+    return FALSE;
+}
+
+TimeZoneNames*
+TZDBTimeZoneNames::clone() const {
+    return new TZDBTimeZoneNames(fLocale);
+}
+
+StringEnumeration*
+TZDBTimeZoneNames::getAvailableMetaZoneIDs(UErrorCode& status) const {
+    return TimeZoneNamesImpl::_getAvailableMetaZoneIDs(status);
+}
+
+StringEnumeration*
+TZDBTimeZoneNames::getAvailableMetaZoneIDs(const UnicodeString& tzID, UErrorCode& status) const {
+    return TimeZoneNamesImpl::_getAvailableMetaZoneIDs(tzID, status);
+}
+
+UnicodeString&
+TZDBTimeZoneNames::getMetaZoneID(const UnicodeString& tzID, UDate date, UnicodeString& mzID) const {
+    return TimeZoneNamesImpl::_getMetaZoneID(tzID, date, mzID);
+}
+
+UnicodeString&
+TZDBTimeZoneNames::getReferenceZoneID(const UnicodeString& mzID, const char* region, UnicodeString& tzID) const {
+    return TimeZoneNamesImpl::_getReferenceZoneID(mzID, region, tzID);
+}
+
+UnicodeString&
+TZDBTimeZoneNames::getMetaZoneDisplayName(const UnicodeString& mzID,
+                                          UTimeZoneNameType type,
+                                          UnicodeString& name) const {
+    name.setToBogus();
+    if (mzID.isEmpty()) {
+        return name;
+    }
+
+    UErrorCode status = U_ZERO_ERROR;
+    const TZDBNames *tzdbNames = TZDBTimeZoneNames::getMetaZoneNames(mzID, status);
+    if (U_SUCCESS(status)) {
+        const UChar *s = tzdbNames->getName(type);
+        if (s != NULL) {
+            name.setTo(TRUE, s, -1);
+        }
+    }
+
+    return name;
+}
+
+UnicodeString&
+TZDBTimeZoneNames::getTimeZoneDisplayName(const UnicodeString& /* tzID */, UTimeZoneNameType /* type */, UnicodeString& name) const {
+    // No abbreviations associated a zone directly for now.
+    name.setToBogus();
+    return name;
+}
+
+TZDBTimeZoneNames::MatchInfoCollection*
+TZDBTimeZoneNames::find(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const {
+    umtx_initOnce(gTZDBNamesTrieInitOnce, &prepareFind, status);
+    if (U_FAILURE(status)) {
+        return NULL;
+    }
+
+    TZDBNameSearchHandler handler(types, fRegion);
+    gTZDBNamesTrie->search(text, start, (TextTrieMapSearchResultHandler *)&handler, status);
+    if (U_FAILURE(status)) {
+        return NULL;
+    }
+    int32_t maxLen = 0;
+    return handler.getMatches(maxLen);
+}
+
+const TZDBNames*
+TZDBTimeZoneNames::getMetaZoneNames(const UnicodeString& mzID, UErrorCode& status) {
+    umtx_initOnce(gTZDBNamesMapInitOnce, &initTZDBNamesMap, status);
+    if (U_FAILURE(status)) {
+        return NULL;
+    }
+
+    TZDBNames* tzdbNames = NULL;
+
+    UChar mzIDKey[ZID_KEY_MAX + 1];
+    mzID.extract(mzIDKey, ZID_KEY_MAX + 1, status);
+    U_ASSERT(status == U_ZERO_ERROR);   // already checked length above
+    mzIDKey[mzID.length()] = 0;
+
+    umtx_lock(&gTZDBNamesMapLock);
+    {
+        void *cacheVal = uhash_get(gTZDBNamesMap, mzIDKey);
+        if (cacheVal == NULL) {
+            UResourceBundle *zoneStringsRes = ures_openDirect(U_ICUDATA_ZONE, "tzdbNames", &status);
+            zoneStringsRes = ures_getByKey(zoneStringsRes, gZoneStrings, zoneStringsRes, &status);
+            if (U_SUCCESS(status)) {
+                char key[ZID_KEY_MAX + 1];
+                mergeTimeZoneKey(mzID, key);
+                tzdbNames = TZDBNames::createInstance(zoneStringsRes, key);
+
+                if (tzdbNames == NULL) {
+                    cacheVal = (void *)EMPTY;
+                } else {
+                    cacheVal = tzdbNames;
+                }
+                // Use the persistent ID as the resource key, so we can
+                // avoid duplications.
+                const UChar* newKey = ZoneMeta::findMetaZoneID(mzID);
+                if (newKey != NULL) {
+                    uhash_put(gTZDBNamesMap, (void *)newKey, cacheVal, &status);
+                    if (U_FAILURE(status)) {
+                        if (tzdbNames != NULL) {
+                            delete tzdbNames;
+                            tzdbNames = NULL;
+                        }
+                    }
+                } else {
+                    // Should never happen with a valid input
+                    if (tzdbNames != NULL) {
+                        // It's not possible that we get a valid tzdbNames with unknown ID.
+                        // But just in case..
+                        delete tzdbNames;
+                        tzdbNames = NULL;
+                    }
+                }
+            }
+            ures_close(zoneStringsRes);
+        } else if (cacheVal != EMPTY) {
+            tzdbNames = (TZDBNames *)cacheVal;
+        }
+    }
+    umtx_unlock(&gTZDBNamesMapLock);
+
+    return tzdbNames;
+}
+
 U_NAMESPACE_END
 
 
index c677a8b9537a536560818745a70179f4a69584d8..5e5d96829e79caa76f4b52617a87e603ae6ef456 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *******************************************************************************
- * Copyright (C) 2011-2013, International Business Machines Corporation and    *
+ * Copyright (C) 2011-2014, International Business Machines Corporation and    *
  * others. All Rights Reserved.                                                *
  *******************************************************************************
  */
@@ -186,6 +186,11 @@ public:
 
     static UnicodeString& getDefaultExemplarLocationName(const UnicodeString& tzID, UnicodeString& name);
 
+    static StringEnumeration* _getAvailableMetaZoneIDs(UErrorCode& status);
+    static StringEnumeration* _getAvailableMetaZoneIDs(const UnicodeString& tzID, UErrorCode& status);
+    static UnicodeString& _getMetaZoneID(const UnicodeString& tzID, UDate date, UnicodeString& mzID);
+    static UnicodeString& _getReferenceZoneID(const UnicodeString& mzID, const char* region, UnicodeString& tzID);
+
 private:
 
     Locale fLocale;
@@ -207,6 +212,34 @@ private:
     TZNames* loadTimeZoneNames(const UnicodeString& mzId);
 };
 
+class TZDBNames;
+
+class TZDBTimeZoneNames : public TimeZoneNames {
+public:
+    TZDBTimeZoneNames(const Locale& locale);
+    virtual ~TZDBTimeZoneNames();
+
+    virtual UBool operator==(const TimeZoneNames& other) const;
+    virtual TimeZoneNames* clone() const;
+
+    StringEnumeration* getAvailableMetaZoneIDs(UErrorCode& status) const;
+    StringEnumeration* getAvailableMetaZoneIDs(const UnicodeString& tzID, UErrorCode& status) const;
+
+    UnicodeString& getMetaZoneID(const UnicodeString& tzID, UDate date, UnicodeString& mzID) const;
+    UnicodeString& getReferenceZoneID(const UnicodeString& mzID, const char* region, UnicodeString& tzID) const;
+
+    UnicodeString& getMetaZoneDisplayName(const UnicodeString& mzID, UTimeZoneNameType type, UnicodeString& name) const;
+    UnicodeString& getTimeZoneDisplayName(const UnicodeString& tzID, UTimeZoneNameType type, UnicodeString& name) const;
+
+    TimeZoneNames::MatchInfoCollection* find(const UnicodeString& text, int32_t start, uint32_t types, UErrorCode& status) const;
+
+    static const TZDBNames* getMetaZoneNames(const UnicodeString& mzId, UErrorCode& status);
+
+private:
+    Locale fLocale;
+    char fRegion[ULOC_COUNTRY_CAPACITY];
+};
+
 U_NAMESPACE_END
 
 #endif /* #if !UCONFIG_NO_FORMATTING */
index a2d9ffdcc4fc2a8788d69c62e1d88abff9ee81d9..f63137659aacc271969340d8ad8f70d159767777 100644 (file)
@@ -35,6 +35,7 @@ typedef enum ECleanupI18NType {
     UCLN_I18N_DANGI_CALENDAR,
     UCLN_I18N_CALENDAR,
     UCLN_I18N_TIMEZONEFORMAT,
+    UCLN_I18N_TZDBTIMEZONENAMES,
     UCLN_I18N_TIMEZONEGENERICNAMES,
     UCLN_I18N_TIMEZONENAMES,
     UCLN_I18N_ZONEMETA,
index 9551f854380d289e54b3b8b98ee82b367a2e7037..53cb7f64f349a3275edb686a61bc8be9442ccc24 100644 (file)
@@ -233,7 +233,15 @@ typedef enum UTimeZoneFormatParseOption {
      * by other styles.
      * @stable ICU 50
      */
-    UTZFMT_PARSE_OPTION_ALL_STYLES  = 0x01
+    UTZFMT_PARSE_OPTION_ALL_STYLES  = 0x01,
+     /**
+      * When parsing a time zone display name in UTZFMT_STYLE_SPECIFIC_SHORT,
+      * look for the IANA tz database compatible zone abbreviations in addition
+      * to the localized names coming from the {@link TimeZoneNames} currently
+      * used by the {@link TimeZoneFormat}. 
+      * @draft ICU 54
+      */
+    UTZFMT_PARSE_OPTION_TZ_DATABASE_ABBREVIATIONS = 0x02
 } UTimeZoneFormatParseOption;
 
 U_CDECL_END
@@ -241,6 +249,7 @@ U_CDECL_END
 U_NAMESPACE_BEGIN
 
 class TimeZoneGenericNames;
+class TZDBTimeZoneNames;
 class UVector;
 
 /**
@@ -697,6 +706,9 @@ private:
 
     UBool fAbuttingOffsetHoursAndMinutes;
 
+    /* TZDBTimeZoneNames object used for parsing */
+    TZDBTimeZoneNames* fTZDBTimeZoneNames;
+
     /**
      * Returns the time zone's specific format string.
      * @param tz the time zone
@@ -727,6 +739,13 @@ private:
      */
     const TimeZoneGenericNames* getTimeZoneGenericNames(UErrorCode& status) const;
 
+    /**
+     * Lazily create a TZDBTimeZoneNames instance
+     * @param status receives the status
+     * @return the cached TZDBTimeZoneNames.
+     */
+    const TZDBTimeZoneNames* getTZDBTimeZoneNames(UErrorCode& status) const;
+
     /**
      * Private method returning the time zone's exemplar location string.
      * This method will never return empty.
index 084dec1bf8f214fcb582f895e41b8df87f0a2281..5ae16ef4e2e4b08501e965857fb1bf613dbbc24f 100644 (file)
@@ -158,15 +158,28 @@ public:
     virtual TimeZoneNames* clone() const = 0;
 
     /**
-     * Returns an instance of <code>TimeZoneDisplayNames</code> for the specified locale.
+     * Returns an instance of <code>TimeZoneNames</code> for the specified locale.
      *
      * @param locale The locale.
      * @param status Receives the status.
-     * @return An instance of <code>TimeZoneDisplayNames</code>
+     * @return An instance of <code>TimeZoneNames</code>
      * @stable ICU 50
      */
     static TimeZoneNames* U_EXPORT2 createInstance(const Locale& locale, UErrorCode& status);
 
+#ifndef U_HIDE_DRAFT_API
+    /**
+     * Returns an instance of <code>TimeZoneNames</code> containing only short specific
+     * zone names (SHORT_STANDARD and SHORT_DAYLIGHT),
+     * compatible with the IANA tz database's zone abbreviations (not localized).
+     * <br>
+     * Note: The input locale is used for resolving ambiguous names (e.g. "IST" is parsed
+     * as Israel Standard Time for Israel, while it is parsed as India Standard Time for
+     * all other regions). The zone names returned by this instance are not localized.
+     */
+     static TimeZoneNames* U_EXPORT2 createTZDBInstance(const Locale& locale, UErrorCode& status);
+#endif /* U_HIDE_DRAFT_API */
+
     /**
      * Returns an enumeration of all available meta zone IDs.
      * @param status Receives the status.
index ffdaeae279c62e374fe7df698060bb59bb5e6201..3e4ece8c37fff21982332faf5fa153637fd2253a 100644 (file)
@@ -1,6 +1,6 @@
 /*
 *******************************************************************************
-* Copyright (C) 2007-2013, International Business Machines Corporation and    *
+* Copyright (C) 2007-2014, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */
@@ -76,6 +76,7 @@ TimeZoneFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &name
         TESTCASE(2, TestParse);
         TESTCASE(3, TestISOFormat);
         TESTCASE(4, TestFormat);
+        TESTCASE(5, TestFormatTZDBNames);
         default: name = ""; break;
     }
 }
@@ -685,7 +686,7 @@ typedef struct {
     int32_t         inPos;
     const char*     locale;
     UTimeZoneFormatStyle    style;
-    UBool           parseAll;
+    uint32_t        parseOptions;
     const char*     expected;
     int32_t         outPos;
     UTimeZoneFormatTimeType timeType;
@@ -694,26 +695,94 @@ typedef struct {
 void
 TimeZoneFormatTest::TestParse(void) {
     const ParseTestData DATA[] = {
-        //   text               inPos   locale      style                               parseAll    expected            outPos  timeType
-            {"Z",               0,      "en_US",    UTZFMT_STYLE_ISO_EXTENDED_FULL,     false,      "Etc/GMT",          1,      UTZFMT_TIME_TYPE_UNKNOWN},
-            {"Z",               0,      "en_US",    UTZFMT_STYLE_SPECIFIC_LONG,         false,      "Etc/GMT",          1,      UTZFMT_TIME_TYPE_UNKNOWN},
-            {"Zambia time",     0,      "en_US",    UTZFMT_STYLE_ISO_EXTENDED_FULL,     true,       "Etc/GMT",          1,      UTZFMT_TIME_TYPE_UNKNOWN},
-            {"Zambia time",     0,      "en_US",    UTZFMT_STYLE_GENERIC_LOCATION,      false,      "Africa/Lusaka",    11,     UTZFMT_TIME_TYPE_UNKNOWN},
-            {"Zambia time",     0,      "en_US",    UTZFMT_STYLE_ISO_BASIC_LOCAL_FULL,  true,       "Africa/Lusaka",    11,     UTZFMT_TIME_TYPE_UNKNOWN},
-            {"+00:00",          0,      "en_US",    UTZFMT_STYLE_ISO_EXTENDED_FULL,     false,      "Etc/GMT",          6,      UTZFMT_TIME_TYPE_UNKNOWN},
-            {"-01:30:45",       0,      "en_US",    UTZFMT_STYLE_ISO_EXTENDED_FULL,     false,      "GMT-01:30:45",     9,      UTZFMT_TIME_TYPE_UNKNOWN},
-            {"-7",              0,      "en_US",    UTZFMT_STYLE_ISO_BASIC_LOCAL_FULL,  false,      "GMT-07:00",        2,      UTZFMT_TIME_TYPE_UNKNOWN},
-            {"-2222",           0,      "en_US",    UTZFMT_STYLE_ISO_BASIC_LOCAL_FULL,  false,      "GMT-22:22",        5,      UTZFMT_TIME_TYPE_UNKNOWN},
-            {"-3333",           0,      "en_US",    UTZFMT_STYLE_ISO_BASIC_LOCAL_FULL,  false,      "GMT-03:33",        4,      UTZFMT_TIME_TYPE_UNKNOWN},
-            {"XXX+01:30YYY",    3,      "en_US",    UTZFMT_STYLE_LOCALIZED_GMT,         false,      "GMT+01:30",        9,      UTZFMT_TIME_TYPE_UNKNOWN},
-            {"GMT0",            0,      "en_US",    UTZFMT_STYLE_SPECIFIC_SHORT,        false,      "Etc/GMT",          3,      UTZFMT_TIME_TYPE_UNKNOWN},
-            {"EST",             0,      "en_US",    UTZFMT_STYLE_SPECIFIC_SHORT,        false,      "America/New_York", 3,      UTZFMT_TIME_TYPE_STANDARD},
-            {"ESTx",            0,      "en_US",    UTZFMT_STYLE_SPECIFIC_SHORT,        false,      "America/New_York", 3,      UTZFMT_TIME_TYPE_STANDARD},
-            {"EDTx",            0,      "en_US",    UTZFMT_STYLE_SPECIFIC_SHORT,        false,      "America/New_York", 3,      UTZFMT_TIME_TYPE_DAYLIGHT},
-            {"EST",             0,      "en_US",    UTZFMT_STYLE_SPECIFIC_LONG,         false,      NULL,               0,      UTZFMT_TIME_TYPE_UNKNOWN},
-            {"EST",             0,      "en_US",    UTZFMT_STYLE_SPECIFIC_LONG,         true,       "America/New_York", 3,      UTZFMT_TIME_TYPE_STANDARD},
-            {"EST",             0,      "en_CA",    UTZFMT_STYLE_SPECIFIC_SHORT,        false,      "America/Toronto",  3,      UTZFMT_TIME_TYPE_STANDARD},
-            {NULL,              0,      NULL,       UTZFMT_STYLE_GENERIC_LOCATION,      false,      NULL,               0,      UTZFMT_TIME_TYPE_UNKNOWN}
+        //   text               inPos   locale      style
+        //      parseOptions                        expected            outPos  timeType
+            {"Z",               0,      "en_US",    UTZFMT_STYLE_ISO_EXTENDED_FULL,
+                UTZFMT_PARSE_OPTION_NONE,           "Etc/GMT",          1,      UTZFMT_TIME_TYPE_UNKNOWN},
+
+            {"Z",               0,      "en_US",    UTZFMT_STYLE_SPECIFIC_LONG,
+                UTZFMT_PARSE_OPTION_NONE,           "Etc/GMT",          1,      UTZFMT_TIME_TYPE_UNKNOWN},
+
+            {"Zambia time",     0,      "en_US",    UTZFMT_STYLE_ISO_EXTENDED_FULL,
+                UTZFMT_PARSE_OPTION_ALL_STYLES,     "Etc/GMT",          1,      UTZFMT_TIME_TYPE_UNKNOWN},
+
+            {"Zambia time",     0,      "en_US",    UTZFMT_STYLE_GENERIC_LOCATION,
+                UTZFMT_PARSE_OPTION_NONE,           "Africa/Lusaka",    11,     UTZFMT_TIME_TYPE_UNKNOWN},
+
+            {"Zambia time",     0,      "en_US",    UTZFMT_STYLE_ISO_BASIC_LOCAL_FULL,
+                UTZFMT_PARSE_OPTION_ALL_STYLES,     "Africa/Lusaka",    11,     UTZFMT_TIME_TYPE_UNKNOWN},
+
+            {"+00:00",          0,      "en_US",    UTZFMT_STYLE_ISO_EXTENDED_FULL,
+                UTZFMT_PARSE_OPTION_NONE,           "Etc/GMT",          6,      UTZFMT_TIME_TYPE_UNKNOWN},
+
+            {"-01:30:45",       0,      "en_US",    UTZFMT_STYLE_ISO_EXTENDED_FULL,
+                UTZFMT_PARSE_OPTION_NONE,           "GMT-01:30:45",     9,      UTZFMT_TIME_TYPE_UNKNOWN},
+
+            {"-7",              0,      "en_US",    UTZFMT_STYLE_ISO_BASIC_LOCAL_FULL,
+                UTZFMT_PARSE_OPTION_NONE,           "GMT-07:00",        2,      UTZFMT_TIME_TYPE_UNKNOWN},
+
+            {"-2222",           0,      "en_US",    UTZFMT_STYLE_ISO_BASIC_LOCAL_FULL,
+                UTZFMT_PARSE_OPTION_NONE,           "GMT-22:22",        5,      UTZFMT_TIME_TYPE_UNKNOWN},
+
+            {"-3333",           0,      "en_US",    UTZFMT_STYLE_ISO_BASIC_LOCAL_FULL,
+                UTZFMT_PARSE_OPTION_NONE,           "GMT-03:33",        4,      UTZFMT_TIME_TYPE_UNKNOWN},
+
+            {"XXX+01:30YYY",    3,      "en_US",    UTZFMT_STYLE_LOCALIZED_GMT,
+                UTZFMT_PARSE_OPTION_NONE,           "GMT+01:30",        9,      UTZFMT_TIME_TYPE_UNKNOWN},
+
+            {"GMT0",            0,      "en_US",    UTZFMT_STYLE_SPECIFIC_SHORT,
+                UTZFMT_PARSE_OPTION_NONE,           "Etc/GMT",          3,      UTZFMT_TIME_TYPE_UNKNOWN},
+
+            {"EST",             0,      "en_US",    UTZFMT_STYLE_SPECIFIC_SHORT,
+                UTZFMT_PARSE_OPTION_NONE,           "America/New_York", 3,      UTZFMT_TIME_TYPE_STANDARD},
+
+            {"ESTx",            0,      "en_US",    UTZFMT_STYLE_SPECIFIC_SHORT,
+                UTZFMT_PARSE_OPTION_NONE,           "America/New_York", 3,      UTZFMT_TIME_TYPE_STANDARD},
+
+            {"EDTx",            0,      "en_US",    UTZFMT_STYLE_SPECIFIC_SHORT,
+                UTZFMT_PARSE_OPTION_NONE,           "America/New_York", 3,      UTZFMT_TIME_TYPE_DAYLIGHT},
+
+            {"EST",             0,      "en_US",    UTZFMT_STYLE_SPECIFIC_LONG,
+                UTZFMT_PARSE_OPTION_NONE,           NULL,               0,      UTZFMT_TIME_TYPE_UNKNOWN},
+
+            {"EST",             0,      "en_US",    UTZFMT_STYLE_SPECIFIC_LONG,
+                UTZFMT_PARSE_OPTION_ALL_STYLES,     "America/New_York", 3,      UTZFMT_TIME_TYPE_STANDARD},
+
+            {"EST",             0,      "en_CA",    UTZFMT_STYLE_SPECIFIC_SHORT,
+                UTZFMT_PARSE_OPTION_NONE,           "America/Toronto",  3,      UTZFMT_TIME_TYPE_STANDARD},
+
+            {"CST",             0,      "en_US",    UTZFMT_STYLE_SPECIFIC_SHORT,
+                UTZFMT_PARSE_OPTION_NONE,           "America/Chicago",  3,      UTZFMT_TIME_TYPE_STANDARD},
+
+            {"CST",             0,      "en_GB",    UTZFMT_STYLE_SPECIFIC_SHORT,
+                UTZFMT_PARSE_OPTION_NONE,           NULL,               0,      UTZFMT_TIME_TYPE_UNKNOWN},
+
+            {"CST",             0,      "en_GB",    UTZFMT_STYLE_SPECIFIC_SHORT,
+                UTZFMT_PARSE_OPTION_TZ_DATABASE_ABBREVIATIONS,  "America/Chicago",  3,  UTZFMT_TIME_TYPE_STANDARD},
+
+            {"--CST--",           2,    "en_GB",    UTZFMT_STYLE_SPECIFIC_SHORT,
+                UTZFMT_PARSE_OPTION_TZ_DATABASE_ABBREVIATIONS,  "America/Chicago",  5,  UTZFMT_TIME_TYPE_STANDARD},
+
+            {"CST",             0,      "zh_CN",    UTZFMT_STYLE_SPECIFIC_SHORT,
+                UTZFMT_PARSE_OPTION_TZ_DATABASE_ABBREVIATIONS,  "Asia/Shanghai",    3,  UTZFMT_TIME_TYPE_STANDARD},
+
+            {"EST",             0,      "en_AU",    UTZFMT_STYLE_SPECIFIC_SHORT,
+                UTZFMT_PARSE_OPTION_TZ_DATABASE_ABBREVIATIONS,  "Australia/Sydney", 3,  UTZFMT_TIME_TYPE_UNKNOWN},
+
+            {"AST",             0,      "ar_SA",    UTZFMT_STYLE_SPECIFIC_SHORT,
+                UTZFMT_PARSE_OPTION_TZ_DATABASE_ABBREVIATIONS,  "Asia/Riyadh",      3,  UTZFMT_TIME_TYPE_STANDARD},
+
+            {"AQTST",           0,      "en",       UTZFMT_STYLE_SPECIFIC_LONG,
+                UTZFMT_PARSE_OPTION_NONE,           NULL,               0,      UTZFMT_TIME_TYPE_UNKNOWN},
+
+            {"AQTST",           0,      "en",       UTZFMT_STYLE_SPECIFIC_LONG,
+                UTZFMT_PARSE_OPTION_ALL_STYLES,     NULL,               0,      UTZFMT_TIME_TYPE_UNKNOWN},
+
+            {"AQTST",           0,      "en",       UTZFMT_STYLE_SPECIFIC_LONG,
+                UTZFMT_PARSE_OPTION_ALL_STYLES | UTZFMT_PARSE_OPTION_TZ_DATABASE_ABBREVIATIONS, "Asia/Aqtobe",  5,  UTZFMT_TIME_TYPE_DAYLIGHT},
+
+            {NULL,              0,      NULL,       UTZFMT_STYLE_GENERIC_LOCATION,
+                UTZFMT_PARSE_OPTION_NONE,           NULL,               0,      UTZFMT_TIME_TYPE_UNKNOWN}
     };
 
     for (int32_t i = 0; DATA[i].text; i++) {
@@ -725,8 +794,7 @@ TimeZoneFormatTest::TestParse(void) {
         }
         UTimeZoneFormatTimeType ttype = UTZFMT_TIME_TYPE_UNKNOWN;
         ParsePosition pos(DATA[i].inPos);
-        int32_t parseOptions = DATA[i].parseAll ? UTZFMT_PARSE_OPTION_ALL_STYLES : UTZFMT_PARSE_OPTION_NONE;
-        TimeZone* tz = tzfmt->parse(DATA[i].style, DATA[i].text, pos, parseOptions, &ttype);
+        TimeZone* tz = tzfmt->parse(DATA[i].style, DATA[i].text, pos, DATA[i].parseOptions, &ttype);
 
         UnicodeString errMsg;
         if (tz) {
@@ -1025,4 +1093,102 @@ TimeZoneFormatTest::TestFormat(void) {
     }
 }
 
+void
+TimeZoneFormatTest::TestFormatTZDBNames(void) {
+    UDate dateJan = 1358208000000.0;    // 2013-01-15T00:00:00Z
+    UDate dateJul = 1373846400000.0;    // 2013-07-15T00:00:00Z
+
+    const FormatTestData DATA[] = {
+        {
+            "en",
+            "America/Chicago", 
+            dateJan,
+            UTZFMT_STYLE_SPECIFIC_SHORT,
+            "CST",
+            UTZFMT_TIME_TYPE_STANDARD
+        },
+        {
+            "en",
+            "Asia/Shanghai", 
+            dateJan,
+            UTZFMT_STYLE_SPECIFIC_SHORT,
+            "CST",
+            UTZFMT_TIME_TYPE_STANDARD
+        },
+        {
+            "zh_Hans",
+            "Asia/Shanghai", 
+            dateJan,
+            UTZFMT_STYLE_SPECIFIC_SHORT,
+            "CST",
+            UTZFMT_TIME_TYPE_STANDARD
+        },
+        {
+            "en",
+            "America/Los_Angeles",
+            dateJul,
+            UTZFMT_STYLE_SPECIFIC_LONG,
+            "GMT-07:00",    // No long display names
+            UTZFMT_TIME_TYPE_DAYLIGHT
+        },
+        {
+            "ja",
+            "America/Los_Angeles",
+            dateJul,
+            UTZFMT_STYLE_SPECIFIC_SHORT,
+            "PDT",
+            UTZFMT_TIME_TYPE_DAYLIGHT
+        },
+        {
+            "en",
+            "Australia/Sydney",
+            dateJan,
+            UTZFMT_STYLE_SPECIFIC_SHORT,
+            "EST",
+            UTZFMT_TIME_TYPE_DAYLIGHT
+        },
+        {
+            "en",
+            "Australia/Sydney",
+            dateJul,
+            UTZFMT_STYLE_SPECIFIC_SHORT,
+            "EST",
+            UTZFMT_TIME_TYPE_STANDARD
+        },
+
+        {0, 0, 0.0, UTZFMT_STYLE_GENERIC_LOCATION, 0, UTZFMT_TIME_TYPE_UNKNOWN}
+    };
+
+    for (int32_t i = 0; DATA[i].locale; i++) {
+        UErrorCode status = U_ZERO_ERROR;
+        Locale loc(DATA[i].locale);
+        LocalPointer<TimeZoneFormat> tzfmt(TimeZoneFormat::createInstance(loc, status));
+        if (U_FAILURE(status)) {
+            dataerrln("Fail TimeZoneFormat::createInstance: %s", u_errorName(status));
+            continue;
+        }
+        TimeZoneNames *tzdbNames = TimeZoneNames::createTZDBInstance(loc, status);
+        if (U_FAILURE(status)) {
+            dataerrln("Fail TimeZoneNames::createTZDBInstance: %s", u_errorName(status));
+            continue;
+        }
+        tzfmt->adoptTimeZoneNames(tzdbNames);
+
+        LocalPointer<TimeZone> tz(TimeZone::createTimeZone(DATA[i].tzid));
+        UnicodeString out;
+        UTimeZoneFormatTimeType timeType;
+
+        tzfmt->format(DATA[i].style, *(tz.getAlias()), DATA[i].date, out, &timeType);
+        UnicodeString expected(DATA[i].expected, -1, US_INV);
+        expected = expected.unescape();
+
+        assertEquals(UnicodeString("Format result for ") + DATA[i].tzid + " (Test Case " + i + ")", expected, out);
+        if (DATA[i].timeType != timeType) {
+            dataerrln(UnicodeString("Formatted time zone type (Test Case ") + i + "), returned="
+                + timeType + ", expected=" + DATA[i].timeType);
+        }
+    }
+}
+
+
 #endif /* #if !UCONFIG_NO_FORMATTING */
index 3d81a82b6dd7e42d54a8a073d9b8ac7891a8979c..cb763576b40df48794c3d260dbc44ececc7decd3 100644 (file)
@@ -1,6 +1,6 @@
 /*
 *******************************************************************************
-* Copyright (C) 2007-2013, International Business Machines Corporation and    *
+* Copyright (C) 2007-2014, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */
@@ -23,6 +23,7 @@ class TimeZoneFormatTest : public IntlTest {
     void TestParse(void);
     void TestISOFormat(void);
     void TestFormat(void);
+    void TestFormatTZDBNames(void);
 };
 
 #endif /* #if !UCONFIG_NO_FORMATTING */