mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-14 09:21:03 +00:00
ICU-5990 Merging time zone formatting/parsing changes from yoshito's working branch to the trunk.
X-SVN-Rev: 22978
This commit is contained in:
parent
d1599f4771
commit
7e51ed7330
72 changed files with 9602 additions and 2278 deletions
1
.gitattributes
vendored
1
.gitattributes
vendored
|
@ -48,6 +48,7 @@ README text !eol
|
|||
*.spp -text
|
||||
*.tri2 -text
|
||||
|
||||
icu4c/source/data/misc/metazoneInfo.txt -text
|
||||
icu4c/source/data/xml/collation/as.xml -text
|
||||
icu4c/source/data/xml/collation/bn.xml -text
|
||||
icu4c/source/data/xml/collation/cy.xml -text
|
||||
|
|
|
@ -170,7 +170,7 @@ static const char * const LANGUAGES[] = {
|
|||
"ty", "tyv", "udm", "ug", "uga", "uk", "umb", "und", "ur",
|
||||
"uz", "vai", "ve", "vi", "vo", "vot", "wa", "wak",
|
||||
"wal", "war", "was", "wen", "wo", "xal", "xh", "yao", "yap",
|
||||
"yi", "yo", "ypk", "za", "zap", "zen", "zh", "znd",
|
||||
"yi", "yo", "ypk", "za", "zap", "zbl", "zen", "zh", "znd",
|
||||
"zu", "zun", "zxx", "zza",
|
||||
NULL,
|
||||
"in", "iw", "ji", "jw", "sh", /* obsolete language codes */
|
||||
|
@ -310,8 +310,8 @@ static const char * const LANGUAGES_3[] = {
|
|||
"uzb", "vai", "ven", "vie", "vol", "vot", "wln", "wak",
|
||||
/* "wal", "war", "was", "wen", "wo", "xal", "xh", "yao", "yap", */
|
||||
"wal", "war", "was", "wen", "wol", "xal", "xho", "yao", "yap",
|
||||
/* "yi", "yo", "ypk", "za", "zap", "zen", "zh", "znd", */
|
||||
"yid", "yor", "ypk", "zha", "zap", "zen", "zho", "znd",
|
||||
/* "yi", "yo", "ypk", "za", "zap", "zbl", "zen", "zh", "znd", */
|
||||
"yid", "yor", "ypk", "zha", "zap", "zbl", "zen", "zho", "znd",
|
||||
/* "zu", "zun", "zxx", "zza", */
|
||||
"zul", "zun", "zxx", "zza",
|
||||
NULL,
|
||||
|
|
|
@ -70,7 +70,7 @@
|
|||
</taskdef>
|
||||
</target>
|
||||
<!-- target for generating ICU data -->
|
||||
<target name="all" depends="locales, resfiles, collation, colfiles, supplementalData, brkitr, brkfiles" />
|
||||
<target name="all" depends="locales, resfiles, collation, colfiles, supplementalData, metazoneInfo, brkitr, brkfiles" />
|
||||
|
||||
<!-- parallel target -->
|
||||
<target name="pall" depends="init">
|
||||
|
@ -237,6 +237,20 @@
|
|||
</run>
|
||||
</cldr-build>
|
||||
</target>
|
||||
<target name="metazoneInfo" depends="init,setup" description="builds metazoneInfo.txt from metazoneInfo.xml">
|
||||
<cldr-build toolName="org.unicode.cldr.icu.LDML2ICUConverter" destFile="metazoneInfo.txt" noArgs="true">
|
||||
<!-- launch the tool and generate the data after reading the config file -->
|
||||
<run>
|
||||
<args>
|
||||
<arg name="-s" value="${env.CLDR_DIR}/common/supplemental" />
|
||||
<arg name="-d" value="${env.ICU4C_DIR}/source/data/misc"/>
|
||||
<arg name="-z"/>
|
||||
<arg name="-f"/>
|
||||
<arg name="-m" value="${env.CLDR_DIR}/common/supplemental" />
|
||||
</args>
|
||||
</run>
|
||||
</cldr-build>
|
||||
</target>
|
||||
<target name="brkitr" depends="init,setup" description="builds break iterator files in ICU text format">
|
||||
<cldr-build toolName="org.unicode.cldr.icu.LDML2ICUConverter" srcFile=".*xml" destFile=".*txt">
|
||||
<run>
|
||||
|
@ -316,6 +330,9 @@
|
|||
<fileset id="locales" dir="${env.ICU4C_DIR}/source/data/misc">
|
||||
<include name="supplementalData.txt" />
|
||||
</fileset>
|
||||
<fileset id="locales" dir="${env.ICU4C_DIR}/source/data/misc">
|
||||
<include name="metazoneInfo.txt" />
|
||||
</fileset>
|
||||
</delete>
|
||||
</target>
|
||||
</project>
|
||||
|
|
|
@ -1413,7 +1413,7 @@ bg{
|
|||
traditional{"Традиционно"}
|
||||
}
|
||||
}
|
||||
Version{"1.89"}
|
||||
Version{"1.90"}
|
||||
calendar{
|
||||
gregorian{
|
||||
AmPmMarkers{
|
||||
|
@ -2197,12 +2197,6 @@ bg{
|
|||
"meta:GMT"{
|
||||
ls{"Часова зона Гринуич"}
|
||||
}
|
||||
"meta:Hawaii"{
|
||||
ld{"Лятна часова зона Хавай"}
|
||||
ls{"Часова зона Хавай"}
|
||||
sd{"HDT"}
|
||||
ss{"HST"}
|
||||
}
|
||||
"meta:Israel"{
|
||||
ld{"Лятна часова зона Израел"}
|
||||
ls{"Часова зона Израел"}
|
||||
|
|
|
@ -1441,7 +1441,7 @@ cs{
|
|||
japanese{"Japonský kalendář"}
|
||||
}
|
||||
}
|
||||
Version{"1.103"}
|
||||
Version{"1.104"}
|
||||
calendar{
|
||||
gregorian{
|
||||
AmPmMarkers{
|
||||
|
@ -1723,12 +1723,6 @@ cs{
|
|||
ls{"Greenwichský střední čas"}
|
||||
ss{"GMT"}
|
||||
}
|
||||
"meta:Hawaii"{
|
||||
ld{"Havajský letní čas"}
|
||||
ls{"Havajský standardní čas"}
|
||||
sd{"HDT"}
|
||||
ss{"HST"}
|
||||
}
|
||||
"meta:Israel"{
|
||||
ld{"Izraelský letní čas"}
|
||||
ls{"Izraelský standardní čas"}
|
||||
|
|
|
@ -1918,7 +1918,7 @@ da{
|
|||
traditional{"traditionel sorteringsrækkefølge"}
|
||||
}
|
||||
}
|
||||
Version{"1.89"}
|
||||
Version{"1.90"}
|
||||
calendar{
|
||||
gregorian{
|
||||
AmPmMarkers{
|
||||
|
@ -2270,7 +2270,6 @@ da{
|
|||
lg{"mellemeuropæisk tid"}
|
||||
ls{"mellemeuropæisk normaltid"}
|
||||
sd{"CEST"}
|
||||
sg{"CET"}
|
||||
ss{"CET"}
|
||||
}
|
||||
"meta:Europe_Eastern"{
|
||||
|
@ -2279,7 +2278,6 @@ da{
|
|||
lg{"østeuropæisk tid"}
|
||||
ls{"østeuropæisk normaltid"}
|
||||
sd{"EEST"}
|
||||
sg{"EET"}
|
||||
ss{"EET"}
|
||||
}
|
||||
"meta:Europe_Western"{
|
||||
|
@ -2287,23 +2285,14 @@ da{
|
|||
ld{"vesteuropæisk sommertid"}
|
||||
lg{"vesteuropæisk tid"}
|
||||
ls{"vesteuropæisk normaltid"}
|
||||
sg{"WET"}
|
||||
sd{"WEST"}
|
||||
ss{"WET"}
|
||||
}
|
||||
"meta:GMT"{
|
||||
cu:int{1}
|
||||
ld{"GMT-sommertid"}
|
||||
lg{"verdenstid"}
|
||||
ls{"Verdenstid"}
|
||||
sd{"GMT"}
|
||||
sg{"GMT"}
|
||||
ss{"GMT"}
|
||||
}
|
||||
"meta:Hawaii"{
|
||||
ld{"Hawaii-sommertid"}
|
||||
ls{"Hawaii-normaltid"}
|
||||
sd{"HDT"}
|
||||
ss{"HST"}
|
||||
}
|
||||
"meta:Israel"{
|
||||
ld{"Israelsk sommertid"}
|
||||
ls{"Israelsk normaltid"}
|
||||
|
|
|
@ -75,6 +75,7 @@ en{
|
|||
BH{"Bahrain"}
|
||||
BI{"Burundi"}
|
||||
BJ{"Benin"}
|
||||
BL{"Saint Barthélemy"}
|
||||
BM{"Bermuda"}
|
||||
BN{"Brunei"}
|
||||
BO{"Bolivia"}
|
||||
|
@ -188,6 +189,7 @@ en{
|
|||
MC{"Monaco"}
|
||||
MD{"Moldova"}
|
||||
ME{"Montenegro"}
|
||||
MF{"Saint Martin"}
|
||||
MG{"Madagascar"}
|
||||
MH{"Marshall Islands"}
|
||||
MK{"Macedonia"}
|
||||
|
@ -1882,6 +1884,7 @@ en{
|
|||
ypk{"Yupik Language"}
|
||||
za{"Zhuang"}
|
||||
zap{"Zapotec"}
|
||||
zbl{"Blissymbols"}
|
||||
zen{"Zenaga"}
|
||||
zh{"Chinese"}
|
||||
zh_Hans{"Simplified Chinese"}
|
||||
|
@ -1918,6 +1921,7 @@ en{
|
|||
Scripts{
|
||||
Arab{"Arabic"}
|
||||
Armn{"Armenian"}
|
||||
Avst{"Avestan"}
|
||||
Bali{"Balinese"}
|
||||
Batk{"Batak"}
|
||||
Beng{"Bengali"}
|
||||
|
@ -1981,6 +1985,7 @@ en{
|
|||
Lyci{"Lycian"}
|
||||
Lydi{"Lydian"}
|
||||
Mand{"Mandaean"}
|
||||
Mani{"Manichaean"}
|
||||
Maya{"Mayan hieroglyphs"}
|
||||
Mero{"Meroitic"}
|
||||
Mlym{"Malayalam"}
|
||||
|
@ -1996,12 +2001,14 @@ en{
|
|||
Osma{"Osmanya"}
|
||||
Perm{"Old Permic"}
|
||||
Phag{"Phags-pa"}
|
||||
Phlv{"Book Pahlavi"}
|
||||
Phnx{"Phoenician"}
|
||||
Plrd{"Pollard Phonetic"}
|
||||
Qaai{"Inherited"}
|
||||
Rjng{"Rejang"}
|
||||
Roro{"Rongorongo"}
|
||||
Runr{"Runic"}
|
||||
Samr{"Samaritan"}
|
||||
Sara{"Sarati"}
|
||||
Saur{"Saurashtra"}
|
||||
Sgnw{"SignWriting"}
|
||||
|
@ -2057,6 +2064,7 @@ en{
|
|||
Variants{
|
||||
1606NICT{"Late Middle French to 1606"}
|
||||
1901{"Traditional German orthography"}
|
||||
1994{"Standardized Resian orthography"}
|
||||
1996{"German orthography of 1996"}
|
||||
AREVELA{"Eastern Armenian"}
|
||||
BAKU1926{"Unified Turkic Latin Alphabet"}
|
||||
|
@ -2067,6 +2075,7 @@ en{
|
|||
GAULISH{"Gaulish"}
|
||||
GUOYU{"Mandarin or Standard Chinese"}
|
||||
HAKKA{"Hakka"}
|
||||
LIPAW{"The Lipovaz dialect of Resian"}
|
||||
LOJBAN{"Lojban"}
|
||||
MONOTON{"Monotonic"}
|
||||
NEDIS{"Natisone dialect"}
|
||||
|
@ -2077,12 +2086,13 @@ en{
|
|||
REVISED{"Revised Orthography"}
|
||||
ROZAJ{"Resian"}
|
||||
SAAHO{"Saho"}
|
||||
SCOTLAND{"Scottish Standard English"}
|
||||
SCOUSE{"Scouse"}
|
||||
SOLBA{"Stolvizza/Solbica dialect"}
|
||||
TARASK{"Taraskievica orthography"}
|
||||
XIANG{"Xiang or Hunanese"}
|
||||
}
|
||||
Version{"1.158"}
|
||||
Version{"1.161"}
|
||||
calendar{
|
||||
gregorian{
|
||||
AmPmMarkers{
|
||||
|
@ -2253,8 +2263,8 @@ en{
|
|||
"meta:Acre"{
|
||||
ld{"Acre Summer Time"}
|
||||
ls{"Acre Time"}
|
||||
sd{"ACST"}
|
||||
ss{"ACT"}
|
||||
sd{"ACST (Acre)"}
|
||||
ss{"ACT (Acre)"}
|
||||
}
|
||||
"meta:Afghanistan"{
|
||||
ls{"Afghanistan Time"}
|
||||
|
|
|
@ -23,7 +23,7 @@ en_AU{
|
|||
"#,##0%",
|
||||
"#E0",
|
||||
}
|
||||
Version{"1.45"}
|
||||
Version{"1.46"}
|
||||
calendar{
|
||||
gregorian{
|
||||
DateTimeElements:intvector{
|
||||
|
|
|
@ -17,7 +17,7 @@ en_CA{
|
|||
"US Dollar",
|
||||
}
|
||||
}
|
||||
Version{"1.53"}
|
||||
Version{"1.54"}
|
||||
calendar{
|
||||
gregorian{
|
||||
DateTimeElements:intvector{
|
||||
|
|
|
@ -13,7 +13,7 @@ en_GB{
|
|||
"#,##0%",
|
||||
"#E0",
|
||||
}
|
||||
Version{"1.54"}
|
||||
Version{"1.55"}
|
||||
calendar{
|
||||
gregorian{
|
||||
DateTimePatterns{
|
||||
|
|
|
@ -23,7 +23,7 @@ en_NZ{
|
|||
"#,##0%",
|
||||
"#E0",
|
||||
}
|
||||
Version{"1.48"}
|
||||
Version{"1.49"}
|
||||
calendar{
|
||||
gregorian{
|
||||
DateTimeElements:intvector{
|
||||
|
|
|
@ -13,7 +13,7 @@ en_ZA{
|
|||
"#,##0%",
|
||||
"#E0",
|
||||
}
|
||||
Version{"1.49"}
|
||||
Version{"1.50"}
|
||||
calendar{
|
||||
gregorian{
|
||||
DateTimeElements:intvector{
|
||||
|
|
|
@ -19,7 +19,7 @@ en_ZW{
|
|||
"#,##0%",
|
||||
"#E0",
|
||||
}
|
||||
Version{"1.42"}
|
||||
Version{"1.43"}
|
||||
calendar{
|
||||
gregorian{
|
||||
DateTimeElements:intvector{
|
||||
|
|
|
@ -1953,7 +1953,7 @@ es{
|
|||
Variants{
|
||||
REVISED{"Ortografía revisada"}
|
||||
}
|
||||
Version{"1.98"}
|
||||
Version{"1.99"}
|
||||
calendar{
|
||||
gregorian{
|
||||
AmPmMarkers{
|
||||
|
@ -2496,7 +2496,7 @@ es{
|
|||
"meta:China"{
|
||||
ld{"Hora de verano de China"}
|
||||
ls{"Hora estándar de China"}
|
||||
ss{"CTT"}
|
||||
ss{"CST (China)"}
|
||||
}
|
||||
"meta:Europe_Central"{
|
||||
ld{"Hora de verano de Europa Central"}
|
||||
|
@ -2514,11 +2514,8 @@ es{
|
|||
ls{"Hora media de Greenwich"}
|
||||
ss{"GMT"}
|
||||
}
|
||||
"meta:Hawaii"{
|
||||
"meta:Hawaii_Aleutian"{
|
||||
cu:int{1}
|
||||
ld{"Hora de verano de Hawai"}
|
||||
ls{"Hora estándar de Hawai"}
|
||||
sd{"HDT"}
|
||||
ss{"HST"}
|
||||
}
|
||||
"meta:Israel"{
|
||||
|
@ -2536,7 +2533,7 @@ es{
|
|||
"meta:Newfoundland"{
|
||||
ld{"Hora de verano de Newfoundland"}
|
||||
ls{"Hora estándar de Newfoundland"}
|
||||
ss{"CNT"}
|
||||
ss{"NST"}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1056,7 +1056,7 @@ fa{
|
|||
1996{"رسمالخط آلمانی ۱۹۹۶ میلادی"}
|
||||
REVISED{"رسمالخط تجدیدنظرشده"}
|
||||
}
|
||||
Version{"1.78"}
|
||||
Version{"1.79"}
|
||||
calendar{
|
||||
gregorian{
|
||||
AmPmMarkers{
|
||||
|
@ -1615,8 +1615,8 @@ fa{
|
|||
ec{"تاهیتی"}
|
||||
}
|
||||
"meta:Afghanistan"{
|
||||
lg{"وقت افغانستان"}
|
||||
sg{"AFT"}
|
||||
ls{"وقت افغانستان"}
|
||||
ss{"AFT"}
|
||||
}
|
||||
"meta:Iran"{
|
||||
ld{"وقت تابستانی ایران"}
|
||||
|
|
|
@ -2069,7 +2069,7 @@ fi{
|
|||
SCOUSE{"englannin scouse-murre"}
|
||||
VALENCIA{"katalaanin valencia-murre"}
|
||||
}
|
||||
Version{"1.95"}
|
||||
Version{"1.96"}
|
||||
calendar{
|
||||
gregorian{
|
||||
AmPmMarkers{
|
||||
|
@ -2756,13 +2756,6 @@ fi{
|
|||
"meta:Guyana"{
|
||||
cu:int{0}
|
||||
}
|
||||
"meta:Hawaii"{
|
||||
cu:int{0}
|
||||
ld{"Havaijin kesäaika"}
|
||||
ls{"Havaijin normaaliaika"}
|
||||
sd{"HDT"}
|
||||
ss{"HST"}
|
||||
}
|
||||
"meta:Hawaii_Aleutian"{
|
||||
cu:int{0}
|
||||
}
|
||||
|
|
|
@ -2023,7 +2023,7 @@ fr{
|
|||
SCOUSE{"dialecte scouse"}
|
||||
VALENCIA{"valencien"}
|
||||
}
|
||||
Version{"1.106"}
|
||||
Version{"1.107"}
|
||||
calendar{
|
||||
chinese{
|
||||
monthNames{
|
||||
|
@ -2639,13 +2639,6 @@ fr{
|
|||
sd{"HAEE"}
|
||||
ss{"HEE"}
|
||||
}
|
||||
"meta:Hawaii"{
|
||||
ld{"Heure avancée d’Hawaï"}
|
||||
lg{"Heure d’Hawaï"}
|
||||
ls{"Heure normale d’Hawaï"}
|
||||
sd{"HDT"}
|
||||
ss{"HST"}
|
||||
}
|
||||
"meta:Israel"{
|
||||
ld{"Heure avancée d’Israël"}
|
||||
ls{"Heure normale d’Israël"}
|
||||
|
|
|
@ -23,7 +23,7 @@ fr_CA{
|
|||
"#,##0 %",
|
||||
"#E0",
|
||||
}
|
||||
Version{"1.49"}
|
||||
Version{"1.50"}
|
||||
calendar{
|
||||
gregorian{
|
||||
DateTimeElements:intvector{
|
||||
|
|
|
@ -1748,7 +1748,7 @@ hu{
|
|||
NEDIS{"Natisone dialektus"}
|
||||
REVISED{"Átdolgozott helyesírás"}
|
||||
}
|
||||
Version{"1.88"}
|
||||
Version{"1.89"}
|
||||
calendar{
|
||||
buddhist{
|
||||
eras{
|
||||
|
|
|
@ -1404,7 +1404,7 @@ is{
|
|||
traditional{"Hefðbundin"}
|
||||
}
|
||||
}
|
||||
Version{"1.76"}
|
||||
Version{"1.77"}
|
||||
calendar{
|
||||
gregorian{
|
||||
DateTimePatterns{
|
||||
|
|
|
@ -1956,7 +1956,7 @@ it{
|
|||
ROZAJ{"resiano"}
|
||||
SAAHO{"saho"}
|
||||
}
|
||||
Version{"1.92"}
|
||||
Version{"1.93"}
|
||||
calendar{
|
||||
gregorian{
|
||||
AmPmMarkers{
|
||||
|
@ -2325,7 +2325,7 @@ it{
|
|||
ls{"Ora Standard Alaska"}
|
||||
}
|
||||
"meta:China"{
|
||||
ld{"Ora Standard Cina"}
|
||||
ld{"Ora Legale Cina"}
|
||||
ls{"Ora Standard Cina"}
|
||||
sd{"CDT (Cina)"}
|
||||
ss{"CST (Cina)"}
|
||||
|
|
|
@ -1975,7 +1975,7 @@ ja{
|
|||
POSIX{"コンピュータ"}
|
||||
REVISED{"改訂版"}
|
||||
}
|
||||
Version{"1.114"}
|
||||
Version{"1.115"}
|
||||
calendar{
|
||||
gregorian{
|
||||
AmPmMarkers{
|
||||
|
@ -3044,12 +3044,6 @@ ja{
|
|||
ls{"グリニッジ標準時"}
|
||||
ss{"GMT"}
|
||||
}
|
||||
"meta:Hawaii"{
|
||||
ld{"ハワイ夏時間"}
|
||||
ls{"ハワイ標準時"}
|
||||
sd{"HDT"}
|
||||
ss{"HST"}
|
||||
}
|
||||
"meta:Israel"{
|
||||
ld{"イスラエル夏時間"}
|
||||
ls{"イスラエル標準時"}
|
||||
|
|
|
@ -1906,7 +1906,7 @@ ko{
|
|||
Variants{
|
||||
REVISED{"개정"}
|
||||
}
|
||||
Version{"1.95"}
|
||||
Version{"1.96"}
|
||||
calendar{
|
||||
buddhist{
|
||||
eras{
|
||||
|
@ -2951,12 +2951,6 @@ ko{
|
|||
ls{"그리니치 표준시"}
|
||||
ss{"GMT"}
|
||||
}
|
||||
"meta:Hawaii"{
|
||||
ld{"하와이 하계 표준시"}
|
||||
ls{"하와이 표준시"}
|
||||
sd{"HDT"}
|
||||
ss{"HST"}
|
||||
}
|
||||
"meta:Israel"{
|
||||
ld{"이스라엘 하계 표준시"}
|
||||
ls{"이스라엘 표준시"}
|
||||
|
|
|
@ -1996,7 +1996,7 @@ nl{
|
|||
SAAHO{"Saho"}
|
||||
SCOUSE{"Liverpools (Scouse)"}
|
||||
}
|
||||
Version{"1.93"}
|
||||
Version{"1.94"}
|
||||
calendar{
|
||||
gregorian{
|
||||
DateTimePatterns{
|
||||
|
@ -2516,12 +2516,6 @@ nl{
|
|||
ls{"Greenwich Mean Time"}
|
||||
ss{"GMT"}
|
||||
}
|
||||
"meta:Hawaii"{
|
||||
ld{"Hawaï-zomertijd"}
|
||||
ls{"Hawaï-standaardtijd"}
|
||||
sd{"HDT"}
|
||||
ss{"HST"}
|
||||
}
|
||||
"meta:Israel"{
|
||||
ld{"Israëlische zomertijd"}
|
||||
ls{"Israëlische standaardtijd"}
|
||||
|
|
|
@ -1991,7 +1991,7 @@ pt{
|
|||
SAAHO{"saho"}
|
||||
SCOUSE{"scouse"}
|
||||
}
|
||||
Version{"1.89"}
|
||||
Version{"1.90"}
|
||||
calendar{
|
||||
buddhist{
|
||||
DateTimePatterns{
|
||||
|
@ -2443,7 +2443,7 @@ pt{
|
|||
lg{"Horário da Austrália Central"}
|
||||
ls{"Horário Padrão da Austrália Central"}
|
||||
sd{"ACDT"}
|
||||
ss{"ACST"}
|
||||
ss{"ACST (Austrália)"}
|
||||
}
|
||||
"meta:Australia_Eastern"{
|
||||
ld{"Horário de Verão da Austrália Oriental"}
|
||||
|
@ -2611,21 +2611,9 @@ pt{
|
|||
ls{"Horário Padrão de Gulf"}
|
||||
ss{"GST"}
|
||||
}
|
||||
"meta:Hawaii"{
|
||||
ld{"Horário de Verão do Havaí"}
|
||||
lg{"Horário do Havaí"}
|
||||
ls{"Horário Padrão do Havaí"}
|
||||
sd{"HDT"}
|
||||
sg{"HT"}
|
||||
ss{"HST"}
|
||||
}
|
||||
"meta:Hawaii_Aleutian"{
|
||||
ld{"Horário de Verão do Havaí-Aleuta"}
|
||||
lg{"Horário do Havaí-Aleuta"}
|
||||
ls{"Horário Padrão do Havaí-Aleuta"}
|
||||
sd{"HADT"}
|
||||
sg{"HAT"}
|
||||
ss{"HAST"}
|
||||
ss{"HST"}
|
||||
}
|
||||
"meta:India"{
|
||||
ls{"Horário Padrão da Índia"}
|
||||
|
@ -2647,7 +2635,7 @@ pt{
|
|||
ld{"Horário de Verão de Israel"}
|
||||
ls{"Horário Padrão de Israel"}
|
||||
sd{"IDT"}
|
||||
ss{"IST"}
|
||||
ss{"IST (Israel)"}
|
||||
}
|
||||
"meta:Japan"{
|
||||
ld{"Horário de Verão do Japão"}
|
||||
|
|
|
@ -199,7 +199,7 @@ pt_PT{
|
|||
phonebook{"Ordem da Lista Telefónica"}
|
||||
}
|
||||
}
|
||||
Version{"1.63"}
|
||||
Version{"1.64"}
|
||||
calendar{
|
||||
buddhist{
|
||||
DateTimePatterns{
|
||||
|
@ -400,10 +400,6 @@ pt_PT{
|
|||
"meta:Europe_Central"{
|
||||
ls{"Horário Padrão da Europa Central"}
|
||||
}
|
||||
"meta:Hawaii"{
|
||||
ld{"Horário de Verão do Havai"}
|
||||
ls{"Horário Padrão do Havai"}
|
||||
}
|
||||
"meta:Newfoundland"{
|
||||
ld{"Horário de Verão da Terra Nova"}
|
||||
ls{"Horário Padrão da Terra Nova"}
|
||||
|
|
|
@ -16,13 +16,11 @@ GENRB_CLDR_VERSION = 1.5
|
|||
# * To add an additional locale to the list:
|
||||
# _____________________________________________________
|
||||
# | GENRB_SOURCE_LOCAL = myLocale.txt ...
|
||||
# | GENRB_ALIAS_SOURCE_LOCAL = myAliasLocale.txt ...
|
||||
#
|
||||
# * To REPLACE the default list and only build with a few
|
||||
# locale:
|
||||
# _____________________________________________________
|
||||
# | GENRB_SOURCE = ar.txt ar_AE.txt en.txt de.txt zh.txt
|
||||
# | GENRB_ALIAS_SOURCE = az_AZ.txt zh_CN.txt ...
|
||||
#
|
||||
#
|
||||
# Generated by LDML2ICUConverter, from LDML source files.
|
||||
|
|
|
@ -70,7 +70,7 @@ root{
|
|||
297,
|
||||
210,
|
||||
}
|
||||
Version{"1.121"}
|
||||
Version{"1.123"}
|
||||
calendar{
|
||||
buddhist{
|
||||
AmPmMarkers{
|
||||
|
@ -5075,7 +5075,7 @@ root{
|
|||
"1994-04-30 21:00",
|
||||
}
|
||||
mz3{
|
||||
"Moscow",
|
||||
"Europe_Eastern",
|
||||
"1997-03-30 01:00",
|
||||
"9999-12-31 23:59",
|
||||
}
|
||||
|
|
|
@ -2048,7 +2048,7 @@ sv{
|
|||
SCOUSE{"scouse"}
|
||||
VALENCIA{"valensisk dialekt"}
|
||||
}
|
||||
Version{"1.108"}
|
||||
Version{"1.109"}
|
||||
calendar{
|
||||
gregorian{
|
||||
AmPmMarkers{
|
||||
|
@ -2497,29 +2497,25 @@ sv{
|
|||
lg{"västbrasiliansk tid"}
|
||||
}
|
||||
"meta:Africa_Central"{
|
||||
lg{"centralafrikansk tid"}
|
||||
ls{"centralafrikansk tid"}
|
||||
sg{"CAT"}
|
||||
ss{"CAT"}
|
||||
}
|
||||
"meta:Africa_Eastern"{
|
||||
lg{"östafrikansk tid"}
|
||||
ls{"östafrikansk normaltid"}
|
||||
sg{"EAT"}
|
||||
ss{"EAT"}
|
||||
}
|
||||
"meta:Africa_Southern"{
|
||||
lg{"sydafrikansk tid"}
|
||||
ls{"sydafrikansk normaltid"}
|
||||
sd{"sydafrikansk sommartid"}
|
||||
ss{"SAT"}
|
||||
sg{"SAT"}
|
||||
ss{"SAST"}
|
||||
}
|
||||
"meta:Africa_Western"{
|
||||
ld{"västafrikansk sommartid"}
|
||||
lg{"västafrikansk tid"}
|
||||
ls{"västafrikansk normaltid"}
|
||||
sd{"VAST"}
|
||||
sg{"WAT"}
|
||||
ss{"WAT"}
|
||||
}
|
||||
"meta:Alaska"{
|
||||
|
@ -2568,8 +2564,8 @@ sv{
|
|||
ld{"saudiarabisk sommartid"}
|
||||
lg{"saudiarabisk tid"}
|
||||
ls{"saudiarabisk normaltid"}
|
||||
sg{"AT"}
|
||||
ss{"AST"}
|
||||
sg{"AT (saudiarabisk)"}
|
||||
ss{"AST (saudiarabisk)"}
|
||||
}
|
||||
"meta:Argentina"{
|
||||
lg{"östargentinsk tid"}
|
||||
|
@ -2660,7 +2656,6 @@ sv{
|
|||
lg{"centraleuropeisk tid"}
|
||||
ls{"Centraleuropa, normaltid"}
|
||||
sd{"CEST"}
|
||||
sg{"CET"}
|
||||
ss{"CET"}
|
||||
}
|
||||
"meta:Europe_Eastern"{
|
||||
|
@ -2669,7 +2664,6 @@ sv{
|
|||
lg{"östeuropeisk tid"}
|
||||
ls{"Östeuropa, normaltid"}
|
||||
sd{"EEST"}
|
||||
sg{"EET"}
|
||||
ss{"EET"}
|
||||
}
|
||||
"meta:Europe_Western"{
|
||||
|
@ -2678,16 +2672,11 @@ sv{
|
|||
lg{"västeuropeisk tid"}
|
||||
ls{"västeuropeisk normaltid"}
|
||||
sd{"WEST"}
|
||||
sg{"WET"}
|
||||
ss{"WET"}
|
||||
}
|
||||
"meta:GMT"{
|
||||
cu:int{1}
|
||||
ld{"greenwichtid"}
|
||||
lg{"greenwichtid"}
|
||||
ls{"Greenwichtid"}
|
||||
sd{"GMT"}
|
||||
sg{"GMT"}
|
||||
ss{"GMT"}
|
||||
}
|
||||
"meta:Galapagos"{
|
||||
|
@ -2714,13 +2703,6 @@ sv{
|
|||
"meta:Guam"{
|
||||
lg{"Guamtid"}
|
||||
}
|
||||
"meta:Hawaii"{
|
||||
ld{"Hawaii, sommartid"}
|
||||
lg{"hawaiiansk tid"}
|
||||
ls{"Hawaii, normaltid"}
|
||||
sd{"HDT"}
|
||||
ss{"HST"}
|
||||
}
|
||||
"meta:India"{
|
||||
lg{"indisk tid"}
|
||||
}
|
||||
|
@ -2741,7 +2723,7 @@ sv{
|
|||
lg{"israelisk tid"}
|
||||
ls{"Israel, normaltid"}
|
||||
sd{"IDT"}
|
||||
ss{"IST"}
|
||||
ss{"IST (Israel)"}
|
||||
}
|
||||
"meta:Japan"{
|
||||
ld{"Japan, sommartid"}
|
||||
|
@ -2776,8 +2758,8 @@ sv{
|
|||
ld{"Newfoundland, sommartid"}
|
||||
lg{"New Foundland-tid"}
|
||||
ls{"Newfoundland, normaltid"}
|
||||
sd{"CDT"}
|
||||
ss{"CNT"}
|
||||
sd{"NDT"}
|
||||
ss{"NST"}
|
||||
}
|
||||
"meta:Pakistan"{
|
||||
lg{"pakistansk tid"}
|
||||
|
|
|
@ -1964,7 +1964,7 @@ th{
|
|||
ROZAJ{"เรเซียน"}
|
||||
SAAHO{"ซาโฮ"}
|
||||
}
|
||||
Version{"1.94"}
|
||||
Version{"1.95"}
|
||||
calendar{
|
||||
buddhist{
|
||||
DateTimePatterns{
|
||||
|
|
|
@ -2041,7 +2041,7 @@ tr{
|
|||
SAAHO{"Saho"}
|
||||
SCOUSE{"Scouse"}
|
||||
}
|
||||
Version{"1.91"}
|
||||
Version{"1.92"}
|
||||
calendar{
|
||||
coptic{
|
||||
monthNames{
|
||||
|
@ -2435,8 +2435,8 @@ tr{
|
|||
"meta:Acre"{
|
||||
ld{"Acre Yaz Saati"}
|
||||
ls{"Acre Saati"}
|
||||
sd{"ACST"}
|
||||
ss{"ACT"}
|
||||
sd{"ACST (Acre)"}
|
||||
ss{"ACT (Acre)"}
|
||||
}
|
||||
"meta:Afghanistan"{
|
||||
ls{"Afganistan Saati"}
|
||||
|
@ -2842,21 +2842,9 @@ tr{
|
|||
ls{"Guyana Saati"}
|
||||
ss{"GYT"}
|
||||
}
|
||||
"meta:Hawaii"{
|
||||
ld{"Hawaii Yaz Saati"}
|
||||
lg{"Hawaii Saati"}
|
||||
ls{"Hawaii Standart Saati"}
|
||||
sd{"HDT"}
|
||||
sg{"HT"}
|
||||
ss{"HST"}
|
||||
}
|
||||
"meta:Hawaii_Aleutian"{
|
||||
ld{"Hawaii-Aleutian Yaz Saati"}
|
||||
lg{"Hawaii-Aleutian Saati"}
|
||||
ls{"Hawaii-Aleutian Standart Saati"}
|
||||
sd{"HADT"}
|
||||
sg{"HAT"}
|
||||
ss{"HAST"}
|
||||
ss{"HST"}
|
||||
}
|
||||
"meta:Hong_Kong"{
|
||||
ld{"Hong Kong Yaz Saati"}
|
||||
|
@ -3207,7 +3195,7 @@ tr{
|
|||
}
|
||||
"meta:South_Georgia"{
|
||||
ls{"Güney Georgia Saati"}
|
||||
ss{"GST (S. Georgia)"}
|
||||
ss{"GST (Güney Georgia)"}
|
||||
}
|
||||
"meta:Suriname"{
|
||||
ls{"Surinam Saati"}
|
||||
|
|
|
@ -2026,7 +2026,7 @@ zh{
|
|||
REVISED{"已修订的拼字学"}
|
||||
SAAHO{"萨霍"}
|
||||
}
|
||||
Version{"1.104"}
|
||||
Version{"1.105"}
|
||||
calendar{
|
||||
gregorian{
|
||||
AmPmMarkers{
|
||||
|
@ -3278,17 +3278,14 @@ zh{
|
|||
ls{"Acre 标准时间"}
|
||||
}
|
||||
"meta:Africa_Central"{
|
||||
ld{"非洲中部夏令时间"}
|
||||
lg{"非洲中部时间"}
|
||||
ls{"中部非洲标准时间"}
|
||||
}
|
||||
"meta:Africa_Eastern"{
|
||||
ld{"非洲东部夏令时间"}
|
||||
lg{"非洲东部时间"}
|
||||
ls{"东部非洲标准时间"}
|
||||
}
|
||||
"meta:Africa_Southern"{
|
||||
ld{"非洲南部夏令时间"}
|
||||
lg{"非洲南部时间"}
|
||||
ls{"南部非洲标准时间"}
|
||||
}
|
||||
|
@ -3375,17 +3372,11 @@ zh{
|
|||
ls{"格林尼治标准时间"}
|
||||
ss{"GMT"}
|
||||
}
|
||||
"meta:Hawaii"{
|
||||
ld{"夏威夷夏令时间"}
|
||||
ls{"夏威夷标准时间"}
|
||||
sd{"HDT"}
|
||||
ss{"HST"}
|
||||
}
|
||||
"meta:Israel"{
|
||||
ld{"以色列夏令时间"}
|
||||
ls{"以色列标准时间"}
|
||||
sd{"IDT"}
|
||||
ss{"IST"}
|
||||
ss{"IST (Israel)"}
|
||||
}
|
||||
"meta:Japan"{
|
||||
ld{"日本夏令时间"}
|
||||
|
|
|
@ -1662,7 +1662,7 @@ zh_Hant{
|
|||
REVISED{"已修訂"}
|
||||
SAAHO{"SAAHO"}
|
||||
}
|
||||
Version{"1.89"}
|
||||
Version{"1.90"}
|
||||
calendar{
|
||||
gregorian{
|
||||
DateTimePatterns{
|
||||
|
@ -2511,9 +2511,6 @@ zh_Hant{
|
|||
"meta:GMT"{
|
||||
ls{"格林威治標準時間"}
|
||||
}
|
||||
"meta:Hawaii"{
|
||||
ls{"夏威夷標準時間"}
|
||||
}
|
||||
"meta:Israel"{
|
||||
ls{"以色列標準時間"}
|
||||
}
|
||||
|
|
3719
icu4c/source/data/misc/metazoneInfo.txt
Executable file
3719
icu4c/source/data/misc/metazoneInfo.txt
Executable file
File diff suppressed because it is too large
Load diff
|
@ -23,4 +23,4 @@
|
|||
#
|
||||
|
||||
MISC_SOURCE = \
|
||||
zoneinfo.txt supplementalData.txt
|
||||
zoneinfo.txt supplementalData.txt metazoneInfo.txt
|
||||
|
|
|
@ -516,6 +516,26 @@ supplementalData:table(nofallback){
|
|||
}
|
||||
}
|
||||
}
|
||||
BL{
|
||||
{
|
||||
id{"EUR"}
|
||||
from:intvector{ /** 1999-01-01 */
|
||||
213,
|
||||
320825952,
|
||||
}
|
||||
}
|
||||
{
|
||||
id{"FRF"}
|
||||
from:intvector{ /** 1960-01-01 */
|
||||
-74,
|
||||
-2086527392,
|
||||
}
|
||||
to:intvector{ /** 2002-02-17 */
|
||||
235,
|
||||
1908405440,
|
||||
}
|
||||
}
|
||||
}
|
||||
BM{
|
||||
{
|
||||
id{"BMD"}
|
||||
|
@ -654,6 +674,19 @@ supplementalData:table(nofallback){
|
|||
}
|
||||
}
|
||||
}
|
||||
BU{
|
||||
{
|
||||
id{"BUK"}
|
||||
from:intvector{ /** 1952-07-01 */
|
||||
-133,
|
||||
-1143896928,
|
||||
}
|
||||
to:intvector{ /** 1989-06-18 */
|
||||
139,
|
||||
-210261440,
|
||||
}
|
||||
}
|
||||
}
|
||||
BV{
|
||||
{
|
||||
id{"NOK"}
|
||||
|
@ -875,10 +908,10 @@ supplementalData:table(nofallback){
|
|||
}
|
||||
CS{
|
||||
{
|
||||
id{"EUR"}
|
||||
from:intvector{ /** 2003-02-04 */
|
||||
242,
|
||||
-2038532928,
|
||||
id{"CSD"}
|
||||
from:intvector{ /** 2002-05-15 */
|
||||
235,
|
||||
1735785440,
|
||||
}
|
||||
to:intvector{ /** 2006-06-03 */
|
||||
264,
|
||||
|
@ -886,10 +919,10 @@ supplementalData:table(nofallback){
|
|||
}
|
||||
}
|
||||
{
|
||||
id{"CSD"}
|
||||
from:intvector{ /** 2002-05-15 */
|
||||
235,
|
||||
1735785440,
|
||||
id{"EUR"}
|
||||
from:intvector{ /** 2003-02-04 */
|
||||
242,
|
||||
-2038532928,
|
||||
}
|
||||
to:intvector{ /** 2006-06-03 */
|
||||
264,
|
||||
|
@ -997,6 +1030,19 @@ supplementalData:table(nofallback){
|
|||
}
|
||||
}
|
||||
}
|
||||
DD{
|
||||
{
|
||||
id{"DDM"}
|
||||
from:intvector{ /** 1948-07-20 */
|
||||
-162,
|
||||
-1178645344,
|
||||
}
|
||||
to:intvector{ /** 1990-10-02 */
|
||||
146,
|
||||
-121192512,
|
||||
}
|
||||
}
|
||||
}
|
||||
DE{
|
||||
{
|
||||
id{"EUR"}
|
||||
|
@ -1424,9 +1470,9 @@ supplementalData:table(nofallback){
|
|||
GP{
|
||||
{
|
||||
id{"EUR"}
|
||||
from:intvector{ /** 1999 */
|
||||
from:intvector{ /** 1999-01-01 */
|
||||
213,
|
||||
320765952,
|
||||
320825952,
|
||||
}
|
||||
}
|
||||
{
|
||||
|
@ -2210,6 +2256,26 @@ supplementalData:table(nofallback){
|
|||
}
|
||||
}
|
||||
}
|
||||
MF{
|
||||
{
|
||||
id{"EUR"}
|
||||
from:intvector{ /** 1999-01-01 */
|
||||
213,
|
||||
320825952,
|
||||
}
|
||||
}
|
||||
{
|
||||
id{"FRF"}
|
||||
from:intvector{ /** 1960-01-01 */
|
||||
-74,
|
||||
-2086527392,
|
||||
}
|
||||
to:intvector{ /** 2002-02-17 */
|
||||
235,
|
||||
1908405440,
|
||||
}
|
||||
}
|
||||
}
|
||||
MG{
|
||||
{
|
||||
id{"MGA"}
|
||||
|
@ -2920,6 +2986,15 @@ supplementalData:table(nofallback){
|
|||
}
|
||||
}
|
||||
}
|
||||
QU{
|
||||
{
|
||||
id{"EUR"}
|
||||
from:intvector{ /** 1999-01-01 */
|
||||
213,
|
||||
320825952,
|
||||
}
|
||||
}
|
||||
}
|
||||
RE{
|
||||
{
|
||||
id{"EUR"}
|
||||
|
@ -3296,6 +3371,19 @@ supplementalData:table(nofallback){
|
|||
}
|
||||
}
|
||||
}
|
||||
SU{
|
||||
{
|
||||
id{"SUR"}
|
||||
from:intvector{ /** 1961-01-01 */
|
||||
-67,
|
||||
-528898464,
|
||||
}
|
||||
to:intvector{ /** 1991-12-25 */
|
||||
154,
|
||||
-957610880,
|
||||
}
|
||||
}
|
||||
}
|
||||
SV{
|
||||
{
|
||||
id{"SVC"}
|
||||
|
@ -3495,6 +3583,30 @@ supplementalData:table(nofallback){
|
|||
}
|
||||
}
|
||||
}
|
||||
TP{
|
||||
{
|
||||
id{"TPE"}
|
||||
from:intvector{ /** 1959-01-02 */
|
||||
-81,
|
||||
823610976,
|
||||
}
|
||||
to:intvector{ /** 2002-05-20 */
|
||||
235,
|
||||
-2127181856,
|
||||
}
|
||||
}
|
||||
{
|
||||
id{"IDR"}
|
||||
from:intvector{ /** 1975-12-07 */
|
||||
36,
|
||||
-628269952,
|
||||
}
|
||||
to:intvector{ /** 2002-05-20 */
|
||||
235,
|
||||
-2127181856,
|
||||
}
|
||||
}
|
||||
}
|
||||
TR{
|
||||
{
|
||||
id{"TRY"}
|
||||
|
@ -3814,6 +3926,41 @@ supplementalData:table(nofallback){
|
|||
}
|
||||
}
|
||||
}
|
||||
YU{
|
||||
{
|
||||
id{"YUM"}
|
||||
from:intvector{ /** 1994-01-24 */
|
||||
176,
|
||||
-839551392,
|
||||
}
|
||||
to:intvector{ /** 2002-05-15 */
|
||||
235,
|
||||
1735785440,
|
||||
}
|
||||
}
|
||||
{
|
||||
id{"YUN"}
|
||||
from:intvector{ /** 1990-01-01 */
|
||||
146,
|
||||
-208132512,
|
||||
}
|
||||
to:intvector{ /** 1992-07-24 */
|
||||
162,
|
||||
426918048,
|
||||
}
|
||||
}
|
||||
{
|
||||
id{"YUD"}
|
||||
from:intvector{ /** 1966-01-01 */
|
||||
-30,
|
||||
-1676288416,
|
||||
}
|
||||
to:intvector{ /** 1990-01-01 */
|
||||
146,
|
||||
-208132512,
|
||||
}
|
||||
}
|
||||
}
|
||||
ZA{
|
||||
{
|
||||
id{"ZAR"}
|
||||
|
@ -3832,6 +3979,30 @@ supplementalData:table(nofallback){
|
|||
}
|
||||
}
|
||||
}
|
||||
ZR{
|
||||
{
|
||||
id{"ZRN"}
|
||||
from:intvector{ /** 1993-11-01 */
|
||||
168,
|
||||
-2413024,
|
||||
}
|
||||
to:intvector{ /** 1998-07 */
|
||||
205,
|
||||
-1150042976,
|
||||
}
|
||||
}
|
||||
{
|
||||
id{"ZRZ"}
|
||||
from:intvector{ /** 1971-10-27 */
|
||||
7,
|
||||
-576738368,
|
||||
}
|
||||
to:intvector{ /** 1993-11-01 */
|
||||
168,
|
||||
-2413024,
|
||||
}
|
||||
}
|
||||
}
|
||||
ZW{
|
||||
{
|
||||
id{"ZWD"}
|
||||
|
@ -4258,13 +4429,6 @@ supplementalData:table(nofallback){
|
|||
}
|
||||
}
|
||||
}
|
||||
auv{
|
||||
secondary{
|
||||
territories{
|
||||
"FR",
|
||||
}
|
||||
}
|
||||
}
|
||||
av{
|
||||
primary{
|
||||
scripts{
|
||||
|
@ -5361,6 +5525,7 @@ supplementalData:table(nofallback){
|
|||
"BF",
|
||||
"BI",
|
||||
"BJ",
|
||||
"BL",
|
||||
"CA",
|
||||
"CD",
|
||||
"CF",
|
||||
|
@ -5381,6 +5546,7 @@ supplementalData:table(nofallback){
|
|||
"LU",
|
||||
"MA",
|
||||
"MC",
|
||||
"MF",
|
||||
"MG",
|
||||
"ML",
|
||||
"MQ",
|
||||
|
@ -6136,6 +6302,13 @@ supplementalData:table(nofallback){
|
|||
}
|
||||
}
|
||||
}
|
||||
kg{
|
||||
secondary{
|
||||
territories{
|
||||
"CD",
|
||||
}
|
||||
}
|
||||
}
|
||||
kha{
|
||||
primary{
|
||||
scripts{
|
||||
|
@ -6312,13 +6485,6 @@ supplementalData:table(nofallback){
|
|||
}
|
||||
}
|
||||
}
|
||||
kon{
|
||||
secondary{
|
||||
territories{
|
||||
"CD",
|
||||
}
|
||||
}
|
||||
}
|
||||
kos{
|
||||
primary{
|
||||
scripts{
|
||||
|
@ -7307,6 +7473,11 @@ supplementalData:table(nofallback){
|
|||
"Latn",
|
||||
}
|
||||
}
|
||||
secondary{
|
||||
territories{
|
||||
"FR",
|
||||
}
|
||||
}
|
||||
}
|
||||
om{
|
||||
primary{
|
||||
|
@ -9097,7 +9268,6 @@ supplementalData:table(nofallback){
|
|||
"meta:Europe_Western_EH"{"Africa/El_Aaiun"}
|
||||
"meta:Europe_Western_FO"{"Atlantic/Faeroe"}
|
||||
"meta:Europe_Western_MA"{"Africa/Casablanca"}
|
||||
"meta:Europe_Western_PT"{"Europe/Lisbon"}
|
||||
"meta:Falkland_001"{"Atlantic/Stanley"}
|
||||
"meta:Fiji_001"{"Pacific/Fiji"}
|
||||
"meta:French_Guiana_001"{"America/Cayenne"}
|
||||
|
@ -9257,7 +9427,7 @@ supplementalData:table(nofallback){
|
|||
"America:Buenos_Aires"{"SA Eastern"}
|
||||
"America:Caracas"{"SA Western"}
|
||||
"America:Chicago"{"Central"}
|
||||
"America:Chihuahua"{"Mountain Standard Time (Mexico)"}
|
||||
"America:Chihuahua"{"Mexico Standard Time 2"}
|
||||
"America:Denver"{"Mountain"}
|
||||
"America:Godthab"{"Greenland"}
|
||||
"America:Guatemala"{"Central America"}
|
||||
|
@ -9265,7 +9435,7 @@ supplementalData:table(nofallback){
|
|||
"America:Indianapolis"{"US Eastern"}
|
||||
"America:Los_Angeles"{"Pacific"}
|
||||
"America:Manaus"{"Central Brazilian"}
|
||||
"America:Mexico_City"{"Central Standard Time (Mexico)"}
|
||||
"America:Mexico_City"{"Mexico"}
|
||||
"America:Montevideo"{"Montevideo"}
|
||||
"America:New_York"{"Eastern"}
|
||||
"America:Noronha"{"Mid-Atlantic"}
|
||||
|
@ -9473,6 +9643,7 @@ supplementalData:table(nofallback){
|
|||
"AN",
|
||||
"AW",
|
||||
"BB",
|
||||
"BL",
|
||||
"BS",
|
||||
"CU",
|
||||
"DM",
|
||||
|
@ -9484,6 +9655,7 @@ supplementalData:table(nofallback){
|
|||
"KN",
|
||||
"KY",
|
||||
"LC",
|
||||
"MF",
|
||||
"MQ",
|
||||
"MS",
|
||||
"PR",
|
||||
|
@ -10466,9 +10638,6 @@ supplementalData:table(nofallback){
|
|||
}
|
||||
"Antarctica:McMurdo"{
|
||||
territory{"AQ"}
|
||||
aliases{
|
||||
"Antarctica/South_Pole",
|
||||
}
|
||||
}
|
||||
"Antarctica:Palmer"{
|
||||
territory{"AQ"}
|
||||
|
@ -10476,6 +10645,9 @@ supplementalData:table(nofallback){
|
|||
"Antarctica:Rothera"{
|
||||
territory{"AQ"}
|
||||
}
|
||||
"Antarctica:South_Pole"{
|
||||
territory{"AQ"}
|
||||
}
|
||||
"Antarctica:Syowa"{
|
||||
territory{"AQ"}
|
||||
}
|
||||
|
|
|
@ -78,7 +78,7 @@ name2uni.o uni2name.o nortrans.o quant.o transreg.o \
|
|||
regexcmp.o rematch.o repattrn.o regexst.o udatpg.o uregex.o uregexc.o \
|
||||
ulocdata.o measfmt.o currfmt.o curramt.o currunit.o measure.o utmscale.o \
|
||||
csdetect.o csmatch.o csr2022.o csrecog.o csrmbcs.o csrsbcs.o csrucode.o csrutf8.o inputext.o \
|
||||
windtfmt.o winnmfmt.o basictz.o dtrule.o rbtz.o tzrule.o tztrans.o vtzone.o
|
||||
windtfmt.o winnmfmt.o basictz.o dtrule.o rbtz.o tzrule.o tztrans.o vtzone.o zonemeta.o zstrfmt.o
|
||||
|
||||
## Header files to install
|
||||
HEADERS = $(srcdir)/unicode/*.h
|
||||
|
|
|
@ -512,6 +512,15 @@ error:
|
|||
transitionRules = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
BasicTimeZone::getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt,
|
||||
int32_t& rawOffset, int32_t& dstOffset, UErrorCode& status) /*const*/ {
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
status = U_UNSUPPORTED_ERROR;
|
||||
}
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
|
|
@ -1094,7 +1094,7 @@ void Calendar::computeFields(UErrorCode &ec)
|
|||
double localMillis = internalGetTime();
|
||||
int32_t rawOffset, dstOffset;
|
||||
getTimeZone().getOffset(localMillis, FALSE, rawOffset, dstOffset, ec);
|
||||
localMillis += rawOffset;
|
||||
localMillis += (rawOffset + dstOffset);
|
||||
|
||||
// Mark fields as set. Do this before calling handleComputeFields().
|
||||
uint32_t mask = //fInternalSetMask;
|
||||
|
@ -1134,33 +1134,8 @@ void Calendar::computeFields(UErrorCode &ec)
|
|||
//__FILE__, __LINE__, fFields[UCAL_JULIAN_DAY], localMillis);
|
||||
#endif
|
||||
|
||||
// In some cases we will have to call this method again below to
|
||||
// adjust for DST pushing us into the next Julian day.
|
||||
computeGregorianAndDOWFields(fFields[UCAL_JULIAN_DAY], ec);
|
||||
|
||||
int32_t millisInDay = (int32_t) (localMillis - (days * kOneDay));
|
||||
if (millisInDay < 0) millisInDay += (int32_t)kOneDay;
|
||||
|
||||
// Adjust our millisInDay for DST. dstOffset will be zero if DST
|
||||
// is not in effect at this time of year, or if our zone does not
|
||||
// use DST.
|
||||
millisInDay += dstOffset;
|
||||
|
||||
// If DST has pushed us into the next day, we must call
|
||||
// computeGregorianAndDOWFields() again. This happens in DST between
|
||||
// 12:00 am and 1:00 am every day. The first call to
|
||||
// computeGregorianAndDOWFields() will give the wrong day, since the
|
||||
// Standard time is in the previous day.
|
||||
if (millisInDay >= (int32_t)kOneDay) {
|
||||
millisInDay -= (int32_t)kOneDay; // ASSUME dstOffset < 24:00
|
||||
|
||||
// We don't worry about overflow of JULIAN_DAY because the
|
||||
// allowable range of JULIAN_DAY has slop at the ends (that is,
|
||||
// the max is less that 0x7FFFFFFF and the min is greater than
|
||||
// -0x80000000).
|
||||
computeGregorianAndDOWFields(++fFields[UCAL_JULIAN_DAY], ec);
|
||||
}
|
||||
|
||||
// Call framework method to have subclass compute its fields.
|
||||
// These must include, at a minimum, MONTH, DAY_OF_MONTH,
|
||||
// EXTENDED_YEAR, YEAR, DAY_OF_YEAR. This method will call internalSet(),
|
||||
|
@ -1174,6 +1149,7 @@ void Calendar::computeFields(UErrorCode &ec)
|
|||
// Compute time-related fields. These are indepent of the date and
|
||||
// of the subclass algorithm. They depend only on the local zone
|
||||
// wall milliseconds in day.
|
||||
int32_t millisInDay = (int32_t) (localMillis - (days * kOneDay));
|
||||
fFields[UCAL_MILLISECONDS_IN_DAY] = millisInDay;
|
||||
fFields[UCAL_MILLISECOND] = millisInDay % 1000;
|
||||
millisInDay /= 1000;
|
||||
|
@ -2348,11 +2324,11 @@ void Calendar::computeTime(UErrorCode& status) {
|
|||
// 1. The transition into DST. Here, a designated time of 2:00 am - 2:59 am
|
||||
// can be in standard or in DST depending. However, 2:00 am is an invalid
|
||||
// representation (the representation jumps from 1:59:59 am Std to 3:00:00 am DST).
|
||||
// We assume standard time.
|
||||
// We assume standard time, that is, 2:30 am is interpreted as 3:30 am DST.
|
||||
// 2. The transition out of DST. Here, a designated time of 1:00 am - 1:59 am
|
||||
// can be in standard or DST. Both are valid representations (the rep
|
||||
// jumps from 1:59:59 DST to 1:00:00 Std).
|
||||
// Again, we assume standard time.
|
||||
// Again, we assume standard time, that is, 1:30 am is interpreted as 1:30 am Std.
|
||||
// We use the TimeZone object, unless the user has explicitly set the ZONE_OFFSET
|
||||
// or DST_OFFSET fields; then we use those fields.
|
||||
if (fStamp[UCAL_ZONE_OFFSET] >= ((int32_t)kMinimumUserStamp) ||
|
||||
|
|
|
@ -170,24 +170,32 @@ UDate
|
|||
DateFormat::parse(const UnicodeString& text,
|
||||
ParsePosition& pos) const
|
||||
{
|
||||
UDate d = 0; // Error return UDate is 0 (the epoch)
|
||||
if (fCalendar != NULL) {
|
||||
int32_t start = pos.getIndex();
|
||||
|
||||
// Parse may update TimeZone used by the calendar.
|
||||
TimeZone *tzsav = (TimeZone*)fCalendar->getTimeZone().clone();
|
||||
|
||||
fCalendar->clear();
|
||||
parse(text, *fCalendar, pos);
|
||||
if (pos.getIndex() != start) {
|
||||
UErrorCode ec = U_ZERO_ERROR;
|
||||
UDate d = fCalendar->getTime(ec);
|
||||
if (U_SUCCESS(ec)) {
|
||||
return d; // Successful function exit
|
||||
d = fCalendar->getTime(ec);
|
||||
if (U_FAILURE(ec)) {
|
||||
// We arrive here if fCalendar is non-lenient and there
|
||||
// is an out-of-range field. We don't know which field
|
||||
// was illegal so we set the error index to the start.
|
||||
pos.setIndex(start);
|
||||
pos.setErrorIndex(start);
|
||||
d = 0;
|
||||
}
|
||||
// We arrive here if fCalendar is non-lenient and there
|
||||
// is an out-of-range field. We don't know which field
|
||||
// was illegal so we set the error index to the start.
|
||||
pos.setIndex(start);
|
||||
pos.setErrorIndex(start);
|
||||
}
|
||||
|
||||
// Restore TimeZone
|
||||
fCalendar->adoptTimeZone(tzsav);
|
||||
}
|
||||
return 0; // Error return UDate is 0 (the epoch)
|
||||
return d;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1646,6 +1646,22 @@
|
|||
RelativePath=".\winnmfmt.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zonemeta.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zonemeta.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zstrfmt.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\zstrfmt.h"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="misc"
|
||||
|
|
|
@ -317,11 +317,11 @@ int32_t OlsonTimeZone::getOffset(uint8_t era, int32_t year, int32_t month,
|
|||
millis, monthLength, ec);
|
||||
}
|
||||
|
||||
// Compute local epoch seconds from input fields
|
||||
double time = Grego::fieldsToDay(year, month, dom) * SECONDS_PER_DAY +
|
||||
uprv_floor(millis / (double) U_MILLIS_PER_SECOND);
|
||||
|
||||
return zoneOffset(findTransition(time, TRUE)) * U_MILLIS_PER_SECOND;
|
||||
// Compute local epoch millis from input fields
|
||||
UDate date = (UDate)(Grego::fieldsToDay(year, month, dom) * U_MILLIS_PER_DAY + millis);
|
||||
int32_t rawoff, dstoff;
|
||||
getHistoricalOffset(date, TRUE, kDaylight, kStandard, rawoff, dstoff);
|
||||
return rawoff + dstoff;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -332,40 +332,30 @@ void OlsonTimeZone::getOffset(UDate date, UBool local, int32_t& rawoff,
|
|||
if (U_FAILURE(ec)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The check against finalMillis will suffice most of the time, except
|
||||
// for the case in which finalMillis == DBL_MAX, date == DBL_MAX,
|
||||
// and finalZone == 0. For this case we add "&& finalZone != 0".
|
||||
if (date >= finalMillis && finalZone != 0) {
|
||||
int32_t year, month, dom, dow;
|
||||
double millis;
|
||||
double days = Math::floorDivide(date, (double)U_MILLIS_PER_DAY, millis);
|
||||
|
||||
Grego::dayToFields(days, year, month, dom, dow);
|
||||
finalZone->getOffset(date, local, rawoff, dstoff, ec);
|
||||
} else {
|
||||
getHistoricalOffset(date, local, kFormer, kLatter, rawoff, dstoff);
|
||||
}
|
||||
}
|
||||
|
||||
rawoff = finalZone->getRawOffset();
|
||||
|
||||
if (!local) {
|
||||
// Adjust from GMT to local
|
||||
date += rawoff;
|
||||
double days2 = Math::floorDivide(date, (double)U_MILLIS_PER_DAY, millis);
|
||||
if (days2 != days) {
|
||||
Grego::dayToFields(days2, year, month, dom, dow);
|
||||
}
|
||||
}
|
||||
|
||||
dstoff = finalZone->getOffset(
|
||||
GregorianCalendar::AD, year, month,
|
||||
dom, (uint8_t) dow, (int32_t) millis, ec) - rawoff;
|
||||
void
|
||||
OlsonTimeZone::getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt,
|
||||
int32_t& rawoff, int32_t& dstoff, UErrorCode& ec) /*const*/ {
|
||||
if (U_FAILURE(ec)) {
|
||||
return;
|
||||
}
|
||||
|
||||
double secs = uprv_floor(date / U_MILLIS_PER_SECOND);
|
||||
int16_t i = findTransition(secs, local);
|
||||
rawoff = rawOffset(i) * U_MILLIS_PER_SECOND;
|
||||
dstoff = dstOffset(i) * U_MILLIS_PER_SECOND;
|
||||
if (date >= finalMillis && finalZone != 0) {
|
||||
finalZone->getOffsetFromLocal(date, nonExistingTimeOpt, duplicatedTimeOpt, rawoff, dstoff, ec);
|
||||
} else {
|
||||
getHistoricalOffset(date, TRUE, nonExistingTimeOpt, duplicatedTimeOpt, rawoff, dstoff);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* TimeZone API.
|
||||
*/
|
||||
|
@ -394,69 +384,84 @@ void printTime(double ms) {
|
|||
double days = Math::floorDivide(((double)ms), (double)U_MILLIS_PER_DAY, millis);
|
||||
|
||||
Grego::dayToFields(days, year, month, dom, dow);
|
||||
U_DEBUG_TZ_MSG((" findTransition: time %.1f (%04d.%02d.%02d+%.1fh)\n", ms,
|
||||
U_DEBUG_TZ_MSG((" getHistoricalOffset: time %.1f (%04d.%02d.%02d+%.1fh)\n", ms,
|
||||
year, month+1, dom, (millis/kOneHour)));
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Find the smallest i (in 0..transitionCount-1) such that time >=
|
||||
* transition(i), where transition(i) is either the GMT or the local
|
||||
* transition time, as specified by `local'.
|
||||
* @param time epoch seconds, either GMT or local wall
|
||||
* @param local if TRUE, `time' is in local wall units, otherwise it
|
||||
* is GMT
|
||||
* @return an index i, where 0 <= i < transitionCount, and
|
||||
* transition(i) <= time < transition(i+1), or i == 0 if
|
||||
* transitionCount == 0 or time < transition(0).
|
||||
*/
|
||||
int16_t OlsonTimeZone::findTransition(double time, UBool local) const {
|
||||
int16_t i = 0;
|
||||
U_DEBUG_TZ_MSG(("findTransition(%.1f, %s)\n", time, local?"T":"F"));
|
||||
void
|
||||
OlsonTimeZone::getHistoricalOffset(UDate date, UBool local,
|
||||
int32_t NonExistingTimeOpt, int32_t DuplicatedTimeOpt,
|
||||
int32_t& rawoff, int32_t& dstoff) const {
|
||||
U_DEBUG_TZ_MSG(("getHistoricalOffset(%.1f, %s, %d, %d, raw, dst)\n",
|
||||
date, local?"T":"F", NonExistingTimeOpt, DuplicatedTimeOpt));
|
||||
#if defined U_DEBUG_TZ
|
||||
printTime(time*1000.0);
|
||||
printTime(date*1000.0);
|
||||
#endif
|
||||
|
||||
if (transitionCount != 0) {
|
||||
double sec = uprv_floor(date / U_MILLIS_PER_SECOND);
|
||||
// Linear search from the end is the fastest approach, since
|
||||
// most lookups will happen at/near the end.
|
||||
int16_t i;
|
||||
for (i = transitionCount - 1; i > 0; --i) {
|
||||
int32_t transition = transitionTimes[i];
|
||||
if (local) {
|
||||
int32_t zoneOffsetPrev = zoneOffset(typeData[i-1]);
|
||||
int32_t zoneOffsetCurr = zoneOffset(typeData[i]);
|
||||
|
||||
// use the lowest offset ( == standard time ). as per tzregts.cpp which says:
|
||||
|
||||
/**
|
||||
* @bug 4084933
|
||||
* The expected behavior of TimeZone around the boundaries is:
|
||||
* (Assume transition time of 2:00 AM)
|
||||
* day of onset 1:59 AM STD = display name 1:59 AM ST
|
||||
* 2:00 AM STD = display name 3:00 AM DT
|
||||
* day of end 0:59 AM STD = display name 1:59 AM DT
|
||||
* 1:00 AM STD = display name 1:00 AM ST
|
||||
*/
|
||||
if(zoneOffsetPrev<zoneOffsetCurr) {
|
||||
transition += zoneOffsetPrev;
|
||||
if (local) {
|
||||
int32_t offsetBefore = zoneOffset(typeData[i-1]);
|
||||
UBool dstBefore = dstOffset(typeData[i-1]) != 0;
|
||||
|
||||
int32_t offsetAfter = zoneOffset(typeData[i]);
|
||||
UBool dstAfter = dstOffset(typeData[i]) != 0;
|
||||
|
||||
UBool dstToStd = dstBefore && !dstAfter;
|
||||
UBool stdToDst = !dstBefore && dstAfter;
|
||||
|
||||
if (offsetAfter - offsetBefore >= 0) {
|
||||
// Positive transition, which makes a non-existing local time range
|
||||
if (((NonExistingTimeOpt & kStdDstMask) == kStandard && dstToStd)
|
||||
|| ((NonExistingTimeOpt & kStdDstMask) == kDaylight && stdToDst)) {
|
||||
transition += offsetBefore;
|
||||
} else if (((NonExistingTimeOpt & kStdDstMask) == kStandard && stdToDst)
|
||||
|| ((NonExistingTimeOpt & kStdDstMask) == kDaylight && dstToStd)) {
|
||||
transition += offsetAfter;
|
||||
} else if ((NonExistingTimeOpt & kFormerLatterMask) == kLatter) {
|
||||
transition += offsetBefore;
|
||||
} else {
|
||||
// Interprets the time with rule before the transition,
|
||||
// default for non-existing time range
|
||||
transition += offsetAfter;
|
||||
}
|
||||
} else {
|
||||
transition += zoneOffsetCurr;
|
||||
// Negative transition, which makes a duplicated local time range
|
||||
if (((DuplicatedTimeOpt & kStdDstMask) == kStandard && dstToStd)
|
||||
|| ((DuplicatedTimeOpt & kStdDstMask) == kDaylight && stdToDst)) {
|
||||
transition += offsetAfter;
|
||||
} else if (((DuplicatedTimeOpt & kStdDstMask) == kStandard && stdToDst)
|
||||
|| ((DuplicatedTimeOpt & kStdDstMask) == kDaylight && dstToStd)) {
|
||||
transition += offsetBefore;
|
||||
} else if ((DuplicatedTimeOpt & kFormerLatterMask) == kFormer) {
|
||||
transition += offsetBefore;
|
||||
} else {
|
||||
// Interprets the time with rule after the transition,
|
||||
// default for duplicated local time range
|
||||
transition += offsetAfter;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (time >= transition) {
|
||||
U_DEBUG_TZ_MSG(("Found@%d: time=%.1f, localtransition=%d (orig %d) dz %d\n", i, time, transition, transitionTimes[i],
|
||||
if (sec >= transition) {
|
||||
U_DEBUG_TZ_MSG(("Found@%d: time=%.1f, localtransition=%d (orig %d) dz %d\n", i, sec, transition, transitionTimes[i],
|
||||
zoneOffset(typeData[i-1])));
|
||||
#if defined U_DEBUG_TZ
|
||||
printTime(transition*1000.0);
|
||||
printTime(transitionTimes[i]*1000.0);
|
||||
printTime(transition*1000.0);
|
||||
printTime(transitionTimes[i]*1000.0);
|
||||
#endif
|
||||
break;
|
||||
} else {
|
||||
U_DEBUG_TZ_MSG(("miss@%d: time=%.1f, localtransition=%d (orig %d) dz %d\n", i, time, transition, transitionTimes[i],
|
||||
U_DEBUG_TZ_MSG(("miss@%d: time=%.1f, localtransition=%d (orig %d) dz %d\n", i, sec, transition, transitionTimes[i],
|
||||
zoneOffset(typeData[i-1])));
|
||||
#if defined U_DEBUG_TZ
|
||||
printTime(transition*1000.0);
|
||||
printTime(transitionTimes[i]*1000.0);
|
||||
printTime(transition*1000.0);
|
||||
printTime(transitionTimes[i]*1000.0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -465,17 +470,25 @@ int16_t OlsonTimeZone::findTransition(double time, UBool local) const {
|
|||
|
||||
// Check invariants for GMT times; if these pass for GMT times
|
||||
// the local logic should be working too.
|
||||
U_ASSERT(local || time < transitionTimes[0] || time >= transitionTimes[i]);
|
||||
U_ASSERT(local || i == transitionCount-1 || time < transitionTimes[i+1]);
|
||||
U_ASSERT(local || sec < transitionTimes[0] || sec >= transitionTimes[i]);
|
||||
U_ASSERT(local || i == transitionCount-1 || sec < transitionTimes[i+1]);
|
||||
|
||||
U_DEBUG_TZ_MSG(("findTransition(%.1f, %s)= trans %d\n", time, local?"T":"F", i));
|
||||
i = typeData[i];
|
||||
U_DEBUG_TZ_MSG(("getHistoricalOffset(%.1f, %s, %d, %d, raw, dst) - trans %d\n",
|
||||
date, local?"T":"F", NonExistingTimeOpt, DuplicatedTimeOpt, i));
|
||||
|
||||
// Since ICU tzdata 2007c, the first transition data is actually not a
|
||||
// transition, but used for representing the initial offset. So the code
|
||||
// below works even if i == 0.
|
||||
int16_t index = typeData[i];
|
||||
rawoff = rawOffset(index) * U_MILLIS_PER_SECOND;
|
||||
dstoff = dstOffset(index) * U_MILLIS_PER_SECOND;
|
||||
} else {
|
||||
// No transitions, single pair of offsets only
|
||||
rawoff = rawOffset(0) * U_MILLIS_PER_SECOND;
|
||||
dstoff = dstOffset(0) * U_MILLIS_PER_SECOND;
|
||||
}
|
||||
|
||||
U_ASSERT(i>=0 && i<typeCount);
|
||||
|
||||
U_DEBUG_TZ_MSG(("findTransition(%.1f, %s)=%d, offset %d\n", time, local?"T":"F", i, zoneOffset(i)));
|
||||
return i;
|
||||
U_DEBUG_TZ_MSG(("getHistoricalOffset(%.1f, %s, %d, %d, raw, dst) - raw=%d, dst=%d\n",
|
||||
date, local?"T":"F", NonExistingTimeOpt, DuplicatedTimeOpt, rawoff, dstoff));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -181,6 +181,12 @@ class OlsonTimeZone: public BasicTimeZone {
|
|||
virtual void getOffset(UDate date, UBool local, int32_t& rawOffset,
|
||||
int32_t& dstOffset, UErrorCode& ec) const;
|
||||
|
||||
/**
|
||||
* BasicTimeZone API.
|
||||
*/
|
||||
virtual void getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt,
|
||||
int32_t& rawoff, int32_t& dstoff, UErrorCode& ec) /*const*/;
|
||||
|
||||
/**
|
||||
* TimeZone API. This method has no effect since objects of this
|
||||
* class are quasi-immutable (the base class allows the ID to be
|
||||
|
@ -279,7 +285,9 @@ private:
|
|||
|
||||
void constructEmpty();
|
||||
|
||||
int16_t findTransition(double time, UBool local) const;
|
||||
void getHistoricalOffset(UDate date, UBool local,
|
||||
int32_t NonExistingTimeOpt, int32_t DuplicatedTimeOpt,
|
||||
int32_t& rawoff, int32_t& dstoff) const;
|
||||
|
||||
int32_t zoneOffset(int16_t index) const;
|
||||
int32_t rawOffset(int16_t index) const;
|
||||
|
|
|
@ -46,14 +46,6 @@ static UBool compareRules(UVector* rules1, UVector* rules2) {
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static UDate getTransitionTime(Transition* transition, UBool local) {
|
||||
UDate time = transition->time;
|
||||
if (local) {
|
||||
time += transition->from->getRawOffset() + transition->from->getDSTSavings();
|
||||
}
|
||||
return time;
|
||||
}
|
||||
|
||||
UOBJECT_DEFINE_RTTI_IMPLEMENTATION(RuleBasedTimeZone)
|
||||
|
||||
RuleBasedTimeZone::RuleBasedTimeZone(const UnicodeString& id, InitialTimeZoneRule* initialRule)
|
||||
|
@ -183,7 +175,7 @@ RuleBasedTimeZone::complete(UErrorCode& status) {
|
|||
for (i = 0; i < historicCount; i++) {
|
||||
done[i] = FALSE;
|
||||
}
|
||||
while (true) {
|
||||
while (TRUE) {
|
||||
int32_t curStdOffset = curRule->getRawOffset();
|
||||
int32_t curDstSavings = curRule->getDSTSavings();
|
||||
UDate nextTransitionTime = MAX_MILLIS;
|
||||
|
@ -377,7 +369,7 @@ RuleBasedTimeZone::getOffset(uint8_t era, int32_t year, int32_t month, int32_t d
|
|||
}
|
||||
int32_t rawOffset, dstOffset;
|
||||
UDate time = (UDate)Grego::fieldsToDay(year, month, day) * U_MILLIS_PER_DAY + millis;
|
||||
getOffset(time, true, rawOffset, dstOffset, status);
|
||||
getOffsetInternal(time, TRUE, kDaylight, kStandard, rawOffset, dstOffset, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
|
@ -387,6 +379,24 @@ RuleBasedTimeZone::getOffset(uint8_t era, int32_t year, int32_t month, int32_t d
|
|||
void
|
||||
RuleBasedTimeZone::getOffset(UDate date, UBool local, int32_t& rawOffset,
|
||||
int32_t& dstOffset, UErrorCode& status) const {
|
||||
getOffsetInternal(date, local, kFormer, kLatter, rawOffset, dstOffset, status);
|
||||
}
|
||||
|
||||
void
|
||||
RuleBasedTimeZone::getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt,
|
||||
int32_t& rawOffset, int32_t& dstOffset, UErrorCode& status) /*const*/ {
|
||||
getOffsetInternal(date, TRUE, nonExistingTimeOpt, duplicatedTimeOpt, rawOffset, dstOffset, status);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The internal getOffset implementation
|
||||
*/
|
||||
void
|
||||
RuleBasedTimeZone::getOffsetInternal(UDate date, UBool local,
|
||||
int32_t NonExistingTimeOpt, int32_t DuplicatedTimeOpt,
|
||||
int32_t& rawOffset, int32_t& dstOffset,
|
||||
UErrorCode& status) const {
|
||||
rawOffset = 0;
|
||||
dstOffset = 0;
|
||||
|
||||
|
@ -404,15 +414,17 @@ RuleBasedTimeZone::getOffset(UDate date, UBool local, int32_t& rawOffset,
|
|||
if (fHistoricTransitions == NULL) {
|
||||
rule = fInitialRule;
|
||||
} else {
|
||||
UDate tstart = getTransitionTime((Transition*)fHistoricTransitions->elementAt(0), local);
|
||||
UDate tstart = getTransitionTime((Transition*)fHistoricTransitions->elementAt(0),
|
||||
local, NonExistingTimeOpt, DuplicatedTimeOpt);
|
||||
if (date < tstart) {
|
||||
rule = fInitialRule;
|
||||
} else {
|
||||
int32_t idx = fHistoricTransitions->size() - 1;
|
||||
UDate tend = getTransitionTime((Transition*)fHistoricTransitions->elementAt(idx), local);
|
||||
UDate tend = getTransitionTime((Transition*)fHistoricTransitions->elementAt(idx),
|
||||
local, NonExistingTimeOpt, DuplicatedTimeOpt);
|
||||
if (date > tend) {
|
||||
if (fFinalRules != NULL) {
|
||||
rule = findRuleInFinal(date, local);
|
||||
rule = findRuleInFinal(date, local, NonExistingTimeOpt, DuplicatedTimeOpt);
|
||||
} else {
|
||||
// no final rule, use the last rule
|
||||
rule = ((Transition*)fHistoricTransitions->elementAt(idx))->to;
|
||||
|
@ -420,7 +432,8 @@ RuleBasedTimeZone::getOffset(UDate date, UBool local, int32_t& rawOffset,
|
|||
} else {
|
||||
// Find a historical transition
|
||||
while (idx >= 0) {
|
||||
if (date >= getTransitionTime((Transition*)fHistoricTransitions->elementAt(idx), local)) {
|
||||
if (date >= getTransitionTime((Transition*)fHistoricTransitions->elementAt(idx),
|
||||
local, NonExistingTimeOpt, DuplicatedTimeOpt)) {
|
||||
break;
|
||||
}
|
||||
idx--;
|
||||
|
@ -651,7 +664,8 @@ RuleBasedTimeZone::copyRules(UVector* source) {
|
|||
}
|
||||
|
||||
TimeZoneRule*
|
||||
RuleBasedTimeZone::findRuleInFinal(UDate date, UBool local) const {
|
||||
RuleBasedTimeZone::findRuleInFinal(UDate date, UBool local,
|
||||
int32_t NonExistingTimeOpt, int32_t DuplicatedTimeOpt) const {
|
||||
if (fFinalRules == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -664,12 +678,25 @@ RuleBasedTimeZone::findRuleInFinal(UDate date, UBool local) const {
|
|||
|
||||
UDate start0, start1;
|
||||
UDate base;
|
||||
int32_t localDelta;
|
||||
|
||||
base = local ? date - fr1->getRawOffset() - fr1->getDSTSavings() : date;
|
||||
UBool avail0 = fr0->getPreviousStart(base, fr1->getRawOffset(), fr1->getDSTSavings(), true, start0);
|
||||
base = date;
|
||||
if (local) {
|
||||
localDelta = getLocalDelta(fr1->getRawOffset(), fr1->getDSTSavings(),
|
||||
fr0->getRawOffset(), fr0->getDSTSavings(),
|
||||
NonExistingTimeOpt, DuplicatedTimeOpt);
|
||||
base -= localDelta;
|
||||
}
|
||||
UBool avail0 = fr0->getPreviousStart(base, fr1->getRawOffset(), fr1->getDSTSavings(), TRUE, start0);
|
||||
|
||||
base = local ? date - fr0->getRawOffset() - fr0->getDSTSavings() : date;
|
||||
UBool avail1 = fr1->getPreviousStart(base, fr0->getRawOffset(), fr0->getDSTSavings(), true, start1);
|
||||
base = date;
|
||||
if (local) {
|
||||
localDelta = getLocalDelta(fr0->getRawOffset(), fr0->getDSTSavings(),
|
||||
fr1->getRawOffset(), fr1->getDSTSavings(),
|
||||
NonExistingTimeOpt, DuplicatedTimeOpt);
|
||||
base -= localDelta;
|
||||
}
|
||||
UBool avail1 = fr1->getPreviousStart(base, fr0->getRawOffset(), fr0->getDSTSavings(), TRUE, start1);
|
||||
|
||||
if (avail0 && (!avail1 || start0 > start1)) {
|
||||
return fr0;
|
||||
|
@ -689,14 +716,14 @@ RuleBasedTimeZone::findNext(UDate base, UBool inclusive, UDate& transitionTime,
|
|||
UBool found = FALSE;
|
||||
Transition result;
|
||||
Transition *tzt = (Transition*)fHistoricTransitions->elementAt(0);
|
||||
UDate tt = getTransitionTime(tzt, FALSE);
|
||||
UDate tt = tzt->time;
|
||||
if (tt > base || (inclusive && tt == base)) {
|
||||
result = *tzt;
|
||||
found = TRUE;
|
||||
} else {
|
||||
int32_t idx = fHistoricTransitions->size() - 1;
|
||||
tzt = (Transition*)fHistoricTransitions->elementAt(idx);
|
||||
tt = getTransitionTime(tzt, FALSE);
|
||||
tt = tzt->time;
|
||||
if (inclusive && tt == base) {
|
||||
result = *tzt;
|
||||
found = TRUE;
|
||||
|
@ -730,7 +757,7 @@ RuleBasedTimeZone::findNext(UDate base, UBool inclusive, UDate& transitionTime,
|
|||
Transition *prev = tzt;
|
||||
while (idx > 0) {
|
||||
tzt = (Transition*)fHistoricTransitions->elementAt(idx);
|
||||
tt = getTransitionTime(tzt, FALSE);
|
||||
tt = tzt->time;
|
||||
if (tt < base || (!inclusive && tt == base)) {
|
||||
break;
|
||||
}
|
||||
|
@ -772,14 +799,14 @@ RuleBasedTimeZone::findPrev(UDate base, UBool inclusive, UDate& transitionTime,
|
|||
UBool found = FALSE;
|
||||
Transition result;
|
||||
Transition *tzt = (Transition*)fHistoricTransitions->elementAt(0);
|
||||
UDate tt = getTransitionTime(tzt, FALSE);
|
||||
UDate tt = tzt->time;
|
||||
if (inclusive && tt == base) {
|
||||
result = *tzt;
|
||||
found = TRUE;
|
||||
} else if (tt < base) {
|
||||
int32_t idx = fHistoricTransitions->size() - 1;
|
||||
tzt = (Transition*)fHistoricTransitions->elementAt(idx);
|
||||
tt = getTransitionTime(tzt, FALSE);
|
||||
tt = tzt->time;
|
||||
if (inclusive && tt == base) {
|
||||
result = *tzt;
|
||||
found = TRUE;
|
||||
|
@ -813,7 +840,7 @@ RuleBasedTimeZone::findPrev(UDate base, UBool inclusive, UDate& transitionTime,
|
|||
idx--;
|
||||
while (idx >= 0) {
|
||||
tzt = (Transition*)fHistoricTransitions->elementAt(idx);
|
||||
tt = getTransitionTime(tzt, FALSE);
|
||||
tt = tzt->time;
|
||||
if (tt < base || (inclusive && tt == base)) {
|
||||
break;
|
||||
}
|
||||
|
@ -839,6 +866,63 @@ RuleBasedTimeZone::findPrev(UDate base, UBool inclusive, UDate& transitionTime,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
UDate
|
||||
RuleBasedTimeZone::getTransitionTime(Transition* transition, UBool local,
|
||||
int32_t NonExistingTimeOpt, int32_t DuplicatedTimeOpt) const {
|
||||
UDate time = transition->time;
|
||||
if (local) {
|
||||
time += getLocalDelta(transition->from->getRawOffset(), transition->from->getDSTSavings(),
|
||||
transition->to->getRawOffset(), transition->to->getDSTSavings(),
|
||||
NonExistingTimeOpt, DuplicatedTimeOpt);
|
||||
}
|
||||
return time;
|
||||
}
|
||||
|
||||
int32_t
|
||||
RuleBasedTimeZone::getLocalDelta(int32_t rawBefore, int32_t dstBefore, int32_t rawAfter, int32_t dstAfter,
|
||||
int32_t NonExistingTimeOpt, int32_t DuplicatedTimeOpt) const {
|
||||
int32_t delta = 0;
|
||||
|
||||
int32_t offsetBefore = rawBefore + dstBefore;
|
||||
int32_t offsetAfter = rawAfter + dstAfter;
|
||||
|
||||
UBool dstToStd = (dstBefore != 0) && (dstAfter == 0);
|
||||
UBool stdToDst = (dstBefore == 0) && (dstAfter != 0);
|
||||
|
||||
if (offsetAfter - offsetBefore >= 0) {
|
||||
// Positive transition, which makes a non-existing local time range
|
||||
if (((NonExistingTimeOpt & kStdDstMask) == kStandard && dstToStd)
|
||||
|| ((NonExistingTimeOpt & kStdDstMask) == kDaylight && stdToDst)) {
|
||||
delta = offsetBefore;
|
||||
} else if (((NonExistingTimeOpt & kStdDstMask) == kStandard && stdToDst)
|
||||
|| ((NonExistingTimeOpt & kStdDstMask) == kDaylight && dstToStd)) {
|
||||
delta = offsetAfter;
|
||||
} else if ((NonExistingTimeOpt & kFormerLatterMask) == kLatter) {
|
||||
delta = offsetBefore;
|
||||
} else {
|
||||
// Interprets the time with rule before the transition,
|
||||
// default for non-existing time range
|
||||
delta = offsetAfter;
|
||||
}
|
||||
} else {
|
||||
// Negative transition, which makes a duplicated local time range
|
||||
if (((DuplicatedTimeOpt & kStdDstMask) == kStandard && dstToStd)
|
||||
|| ((DuplicatedTimeOpt & kStdDstMask) == kDaylight && stdToDst)) {
|
||||
delta = offsetAfter;
|
||||
} else if (((DuplicatedTimeOpt & kStdDstMask) == kStandard && stdToDst)
|
||||
|| ((DuplicatedTimeOpt & kStdDstMask) == kDaylight && dstToStd)) {
|
||||
delta = offsetBefore;
|
||||
} else if ((DuplicatedTimeOpt & kFormerLatterMask) == kFormer) {
|
||||
delta = offsetBefore;
|
||||
} else {
|
||||
// Interprets the time with rule after the transition,
|
||||
// default for duplicated local time range
|
||||
delta = offsetAfter;
|
||||
}
|
||||
}
|
||||
return delta;
|
||||
}
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
|
|
@ -502,6 +502,55 @@ SimpleTimeZone::getOffset(uint8_t era, int32_t year, int32_t month, int32_t day,
|
|||
return result;
|
||||
}
|
||||
|
||||
void
|
||||
SimpleTimeZone::getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt,
|
||||
int32_t& rawOffsetGMT, int32_t& savingsDST, UErrorCode& status) /*const*/ {
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
rawOffsetGMT = getRawOffset();
|
||||
int32_t year, month, dom, dow;
|
||||
double day = uprv_floor(date / U_MILLIS_PER_DAY);
|
||||
int32_t millis = (int32_t) (date - day * U_MILLIS_PER_DAY);
|
||||
|
||||
Grego::dayToFields(day, year, month, dom, dow);
|
||||
|
||||
savingsDST = getOffset(GregorianCalendar::AD, year, month, dom,
|
||||
(uint8_t) dow, millis,
|
||||
Grego::monthLength(year, month),
|
||||
status) - rawOffsetGMT;
|
||||
if (U_FAILURE(status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
UBool recalc = FALSE;
|
||||
|
||||
// Now we need some adjustment
|
||||
if (savingsDST > 0) {
|
||||
if ((nonExistingTimeOpt & kStdDstMask) == kStandard
|
||||
|| (nonExistingTimeOpt & kStdDstMask) != kDaylight && (nonExistingTimeOpt & kFormerLatterMask) != kLatter) {
|
||||
date -= getDSTSavings();
|
||||
recalc = TRUE;
|
||||
}
|
||||
} else {
|
||||
if ((duplicatedTimeOpt & kStdDstMask) == kDaylight
|
||||
|| (duplicatedTimeOpt & kStdDstMask) != kStandard && (duplicatedTimeOpt & kFormerLatterMask) == kFormer) {
|
||||
date -= getDSTSavings();
|
||||
recalc = TRUE;
|
||||
}
|
||||
}
|
||||
if (recalc) {
|
||||
day = uprv_floor(date / U_MILLIS_PER_DAY);
|
||||
millis = (int32_t) (date - day * U_MILLIS_PER_DAY);
|
||||
Grego::dayToFields(day, year, month, dom, dow);
|
||||
savingsDST = getOffset(GregorianCalendar::AD, year, month, dom,
|
||||
(uint8_t) dow, millis,
|
||||
Grego::monthLength(year, month),
|
||||
status) - rawOffsetGMT;
|
||||
}
|
||||
}
|
||||
|
||||
// -------------------------------------
|
||||
|
||||
/**
|
||||
|
@ -966,8 +1015,8 @@ SimpleTimeZone::getPreviousTransition(UDate base, UBool inclusive, TimeZoneTrans
|
|||
return FALSE;
|
||||
}
|
||||
UDate stdDate, dstDate;
|
||||
UBool stdAvail = stdRule->getPreviousStart(base, dstRule->getRawOffset(), dstRule->getDSTSavings(), false, stdDate);
|
||||
UBool dstAvail = dstRule->getPreviousStart(base, stdRule->getRawOffset(), stdRule->getDSTSavings(), false, dstDate);
|
||||
UBool stdAvail = stdRule->getPreviousStart(base, dstRule->getRawOffset(), dstRule->getDSTSavings(), inclusive, stdDate);
|
||||
UBool dstAvail = dstRule->getPreviousStart(base, stdRule->getRawOffset(), stdRule->getDSTSavings(), inclusive, dstDate);
|
||||
if (stdAvail && (!dstAvail || stdDate > dstDate)) {
|
||||
result.setTime(stdDate);
|
||||
result.setFrom((const TimeZoneRule&)*dstRule);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -88,6 +88,7 @@ static char gStrBuf[256];
|
|||
#define kDEFAULT "Default"
|
||||
#define kMAX_CUSTOM_HOUR 23
|
||||
#define kMAX_CUSTOM_MIN 59
|
||||
#define kMAX_CUSTOM_SEC 59
|
||||
#define MINUS 0x002D
|
||||
#define PLUS 0x002B
|
||||
#define ZERO_DIGIT 0x0030
|
||||
|
@ -687,36 +688,40 @@ void TimeZone::getOffset(UDate date, UBool local, int32_t& rawOffset,
|
|||
}
|
||||
|
||||
rawOffset = getRawOffset();
|
||||
|
||||
// Convert to local wall millis if necessary
|
||||
if (!local) {
|
||||
date += rawOffset; // now in local standard millis
|
||||
}
|
||||
|
||||
// When local==FALSE, we might have to recompute. This loop is
|
||||
// executed once, unless a recomputation is required; then it is
|
||||
// executed twice.
|
||||
// When local == TRUE, date might not be in local standard
|
||||
// millis. getOffset taking 7 parameters used here assume
|
||||
// the given time in day is local standard time.
|
||||
// At STD->DST transition, there is a range of time which
|
||||
// does not exist. When 'date' is in this time range
|
||||
// (and local == TRUE), this method interprets the specified
|
||||
// local time as DST. At DST->STD transition, there is a
|
||||
// range of time which occurs twice. In this case, this
|
||||
// method interprets the specified local time as STD.
|
||||
// To support the behavior above, we need to call getOffset
|
||||
// (with 7 args) twice when local == true and DST is
|
||||
// detected in the initial call.
|
||||
for (int32_t pass=0; ; ++pass) {
|
||||
int32_t year, month, dom, dow;
|
||||
double day = uprv_floor(date / U_MILLIS_PER_DAY);
|
||||
int32_t millis = (int32_t) (date - day * U_MILLIS_PER_DAY);
|
||||
|
||||
|
||||
Grego::dayToFields(day, year, month, dom, dow);
|
||||
|
||||
|
||||
dstOffset = getOffset(GregorianCalendar::AD, year, month, dom,
|
||||
(uint8_t) dow, millis,
|
||||
Grego::monthLength(year, month),
|
||||
ec) - rawOffset;
|
||||
|
||||
// Recompute if local==FALSE, dstOffset!=0, and addition of
|
||||
// the dstOffset puts us in a different day.
|
||||
if (pass!=0 || local || dstOffset==0) {
|
||||
break;
|
||||
}
|
||||
date += dstOffset;
|
||||
if (uprv_floor(date / U_MILLIS_PER_DAY) == day) {
|
||||
// Recompute if local==TRUE, dstOffset!=0.
|
||||
if (pass!=0 || !local || dstOffset == 0) {
|
||||
break;
|
||||
}
|
||||
// adjust to local standard millis
|
||||
date -= dstOffset;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1093,6 +1098,33 @@ TimeZone::getEquivalentID(const UnicodeString& id, int32_t index) {
|
|||
|
||||
// ---------------------------------------
|
||||
|
||||
UnicodeString&
|
||||
TimeZone::getOlsonCanonicalID(const UnicodeString &id, UnicodeString &canonical) {
|
||||
UErrorCode ec = U_ZERO_ERROR;
|
||||
canonical.remove();
|
||||
UResourceBundle *top = ures_openDirect(0, kZONEINFO, &ec);
|
||||
UResourceBundle *res = getZoneByName(top, id, NULL, ec);
|
||||
if (U_SUCCESS(ec)) {
|
||||
if (ures_getSize(res) == 1) {
|
||||
int32_t deref = ures_getInt(res, &ec);
|
||||
UResourceBundle *nres = ures_getByKey(top, kNAMES, NULL, &ec); // dereference Names section
|
||||
int32_t len;
|
||||
const UChar* tmp = ures_getStringByIndex(nres, deref, &len, &ec);
|
||||
if (U_SUCCESS(ec)) {
|
||||
canonical.setTo(tmp, len);
|
||||
}
|
||||
ures_close(nres);
|
||||
} else {
|
||||
canonical.setTo(id);
|
||||
}
|
||||
}
|
||||
ures_close(res);
|
||||
ures_close(top);
|
||||
return canonical;
|
||||
}
|
||||
|
||||
// ---------------------------------------
|
||||
|
||||
|
||||
UnicodeString&
|
||||
TimeZone::getDisplayName(UnicodeString& result) const
|
||||
|
@ -1192,11 +1224,12 @@ TimeZone::createCustomTimeZone(const UnicodeString& id)
|
|||
UBool negative = FALSE;
|
||||
int32_t hour = 0;
|
||||
int32_t min = 0;
|
||||
int32_t sec = 0;
|
||||
|
||||
if (id[pos.getIndex()] == MINUS /*'-'*/)
|
||||
negative = TRUE;
|
||||
else if (id[pos.getIndex()] != PLUS /*'+'*/)
|
||||
return 0;
|
||||
return NULL;
|
||||
pos.setIndex(pos.getIndex() + 1);
|
||||
|
||||
UErrorCode success = U_ZERO_ERROR;
|
||||
|
@ -1215,75 +1248,125 @@ TimeZone::createCustomTimeZone(const UnicodeString& id)
|
|||
numberFormat->parse(id, n, pos);
|
||||
if (pos.getIndex() == start) {
|
||||
delete numberFormat;
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
hour = n.getLong();
|
||||
|
||||
if (pos.getIndex() < id.length() &&
|
||||
id[pos.getIndex()] == 0x003A /*':'*/)
|
||||
{
|
||||
if (pos.getIndex() < id.length()) {
|
||||
if (pos.getIndex() - start > 2
|
||||
|| id[pos.getIndex()] != 0x003A /*':'*/) {
|
||||
delete numberFormat;
|
||||
return NULL;
|
||||
}
|
||||
// hh:mm
|
||||
pos.setIndex(pos.getIndex() + 1);
|
||||
int32_t oldPos = pos.getIndex();
|
||||
n.setLong(kParseFailed);
|
||||
numberFormat->parse(id, n, pos);
|
||||
if (pos.getIndex() == oldPos) {
|
||||
if ((pos.getIndex() - oldPos) != 2) {
|
||||
// must be 2 digits
|
||||
delete numberFormat;
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
min = n.getLong();
|
||||
}
|
||||
else
|
||||
{
|
||||
// hhmm or hh
|
||||
if (pos.getIndex() < id.length()) {
|
||||
if (id[pos.getIndex()] != 0x003A /*':'*/) {
|
||||
delete numberFormat;
|
||||
return NULL;
|
||||
}
|
||||
// [:ss]
|
||||
pos.setIndex(pos.getIndex() + 1);
|
||||
oldPos = pos.getIndex();
|
||||
n.setLong(kParseFailed);
|
||||
numberFormat->parse(id, n, pos);
|
||||
if (pos.getIndex() != id.length()
|
||||
|| (pos.getIndex() - oldPos) != 2) {
|
||||
delete numberFormat;
|
||||
return NULL;
|
||||
}
|
||||
sec = n.getLong();
|
||||
}
|
||||
} else {
|
||||
// Supported formats are below -
|
||||
//
|
||||
// HHmmss
|
||||
// Hmmss
|
||||
// HHmm
|
||||
// Hmm
|
||||
// HH
|
||||
// H
|
||||
|
||||
// Be strict about interpreting something as hh; it must be
|
||||
// an offset < 23, and it must be one or two digits. Thus
|
||||
// 0010 is interpreted as 00:10, but 10 is interpreted as
|
||||
// 10:00.
|
||||
if (hour > kMAX_CUSTOM_HOUR || (pos.getIndex() - start) > 2) {
|
||||
min = hour % 100;
|
||||
hour /= 100;
|
||||
int32_t length = pos.getIndex() - start;
|
||||
if (length <= 0 || 6 < length) {
|
||||
// invalid length
|
||||
delete numberFormat;
|
||||
return NULL;
|
||||
}
|
||||
switch (length) {
|
||||
case 1:
|
||||
case 2:
|
||||
// already set to hour
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
min = hour % 100;
|
||||
hour /= 100;
|
||||
break;
|
||||
case 5:
|
||||
case 6:
|
||||
sec = hour % 100;
|
||||
min = (hour/100) % 100;
|
||||
hour /= 10000;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
delete numberFormat;
|
||||
|
||||
if (hour > kMAX_CUSTOM_HOUR || min > kMAX_CUSTOM_MIN) {
|
||||
if (hour > kMAX_CUSTOM_HOUR || min > kMAX_CUSTOM_MIN || sec > kMAX_CUSTOM_SEC) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Create time zone ID in RFC822 format - GMT[+|-]hhmm
|
||||
UnicodeString tzRFC(GMT_ID);
|
||||
if (hour|min) {
|
||||
// Create time zone ID - GMT[+|-]hhmm[ss]
|
||||
UnicodeString tzID(GMT_ID);
|
||||
if (hour | min | sec) {
|
||||
if (negative) {
|
||||
tzRFC += (UChar)MINUS;
|
||||
tzID += (UChar)MINUS;
|
||||
} else {
|
||||
tzRFC += (UChar)PLUS;
|
||||
tzID += (UChar)PLUS;
|
||||
}
|
||||
|
||||
if (hour < 10) {
|
||||
tzRFC += (UChar)ZERO_DIGIT;
|
||||
tzID += (UChar)ZERO_DIGIT;
|
||||
} else {
|
||||
tzRFC += (UChar)(ZERO_DIGIT + hour/10);
|
||||
tzID += (UChar)(ZERO_DIGIT + hour/10);
|
||||
}
|
||||
tzRFC += (UChar)(ZERO_DIGIT + hour%10);
|
||||
tzID += (UChar)(ZERO_DIGIT + hour%10);
|
||||
|
||||
if (min < 10) {
|
||||
tzRFC += (UChar)ZERO_DIGIT;
|
||||
tzID += (UChar)ZERO_DIGIT;
|
||||
} else {
|
||||
tzRFC += (UChar)(ZERO_DIGIT + min/10);
|
||||
tzID += (UChar)(ZERO_DIGIT + min/10);
|
||||
}
|
||||
tzID += (UChar)(ZERO_DIGIT + min%10);
|
||||
|
||||
if (sec) {
|
||||
if (sec < 10) {
|
||||
tzID += (UChar)ZERO_DIGIT;
|
||||
} else {
|
||||
tzID += (UChar)(ZERO_DIGIT + sec/10);
|
||||
}
|
||||
tzID += (UChar)(ZERO_DIGIT + sec%10);
|
||||
}
|
||||
tzRFC += (UChar)(ZERO_DIGIT + min%10);
|
||||
}
|
||||
|
||||
int32_t offset = (hour * 60 + min) * 60 * 1000;
|
||||
if(negative) {
|
||||
int32_t offset = ((hour * 60 + min) * 60 + sec) * 1000;
|
||||
if (negative) {
|
||||
offset = -offset;
|
||||
}
|
||||
return new SimpleTimeZone(offset, tzRFC);
|
||||
return new SimpleTimeZone(offset, tzID);
|
||||
}
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -40,6 +40,8 @@ typedef enum ECleanupI18NType {
|
|||
UCLN_I18N_UCOL,
|
||||
UCLN_I18N_UCOL_BLD,
|
||||
UCLN_I18N_CSDET,
|
||||
UCLN_I18N_ZONEMETA,
|
||||
UCLN_I18N_ZSFORMAT,
|
||||
UCLN_I18N_COUNT /* This must be last */
|
||||
} ECleanupI18NType;
|
||||
|
||||
|
|
|
@ -140,7 +140,36 @@ public:
|
|||
virtual void getSimpleRulesNear(UDate date, InitialTimeZoneRule*& initial,
|
||||
AnnualTimeZoneRule*& std, AnnualTimeZoneRule*& dst, UErrorCode& status) /*const*/;
|
||||
|
||||
|
||||
/**
|
||||
* The time type option bit flags used by getOffsetFromLocal
|
||||
* @internal
|
||||
*/
|
||||
enum {
|
||||
kStandard = 0x01,
|
||||
kDaylight = 0x03,
|
||||
kFormer = 0x04,
|
||||
kLatter = 0x0C
|
||||
};
|
||||
|
||||
/**
|
||||
* Get time zone offsets from local wall time.
|
||||
* @internal
|
||||
*/
|
||||
virtual void getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt,
|
||||
int32_t& rawOffset, int32_t& dstOffset, UErrorCode& status) /*const*/;
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
* The time type option bit masks used by getOffsetFromLocal
|
||||
* @internal
|
||||
*/
|
||||
enum {
|
||||
kStdDstMask = kDaylight,
|
||||
kFormerLatterMask = kLatter
|
||||
};
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
* @draft ICU 3.8
|
||||
|
|
|
@ -37,6 +37,8 @@ U_NAMESPACE_BEGIN
|
|||
/* forward declaration */
|
||||
class SimpleDateFormat;
|
||||
class Hashtable;
|
||||
class ZoneStringFormat;
|
||||
class SafeZoneStringFormatPtr;
|
||||
|
||||
/**
|
||||
* DateFormatSymbols is a public class for encapsulating localizable date-time
|
||||
|
@ -445,100 +447,6 @@ public:
|
|||
*/
|
||||
static UClassID U_EXPORT2 getStaticClassID();
|
||||
|
||||
/**
|
||||
* The translation type of the translated zone strings
|
||||
* @internal ICU 3.6
|
||||
*/
|
||||
enum TimeZoneTranslationType {
|
||||
TIMEZONE_SHORT_GENERIC,
|
||||
TIMEZONE_SHORT_STANDARD,
|
||||
TIMEZONE_SHORT_DAYLIGHT,
|
||||
TIMEZONE_LONG_GENERIC,
|
||||
TIMEZONE_LONG_STANDARD,
|
||||
TIMEZONE_LONG_DAYLIGHT,
|
||||
TIMEZONE_EXEMPLAR_CITY,
|
||||
TIMEZONE_COUNT
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an enumeration of time zone IDs. The object is owned by the caller and should delete it after use.
|
||||
* The time zone IDs are just for programmatic lookup. NOT LOCALIZED!!!
|
||||
* @param status Input/output parameter, set to success or
|
||||
* failure code upon return.
|
||||
* @return A new StringEnumeration object
|
||||
* @internal ICU 3.6
|
||||
*/
|
||||
virtual StringEnumeration* createZoneStringIDs(UErrorCode &status);
|
||||
|
||||
/**
|
||||
* Gets timezone string give the key and translation type
|
||||
* @param ID The ID of zone strings, e.g: "America/Los_Angeles".
|
||||
* The time zone ID is for programmatic lookup.
|
||||
* @param type The translation type requested
|
||||
* @param result Output parameter to recieve the translation string
|
||||
* @param status Input/output parameter, set to success or
|
||||
* failure code upon return.
|
||||
* @return the input UnicodeString parameter for chaining
|
||||
* @internal ICU 3.8
|
||||
*/
|
||||
UnicodeString& getZoneString(const UnicodeString &ID, const TimeZoneTranslationType type, UnicodeString &result, UErrorCode &status);
|
||||
|
||||
/**
|
||||
* Gets metazone string given the key and translation type and calendar
|
||||
* @param ID The ID of zone strings, e.g: "America/Los_Angeles".
|
||||
* The time zone ID is for programmatic lookup.
|
||||
* @param type The translation type requested
|
||||
* @param cal The calendar
|
||||
* @param result Output parameter to recieve the translation string
|
||||
* @param status Input/output parameter, set to success or
|
||||
* failure code upon return.
|
||||
* @return the input UnicodeString parameter for chaining
|
||||
* @internal ICU 3.8
|
||||
*/
|
||||
UnicodeString getMetazoneString(const UnicodeString &ID, const TimeZoneTranslationType type, Calendar &cal, UnicodeString &result, UErrorCode &status);
|
||||
|
||||
/**
|
||||
* Gets fallback string given the key
|
||||
* @param ID The ID of zone strings, e.g: "America/Los_Angeles".
|
||||
* The time zone ID is for programmatic lookup.
|
||||
* @param result Output parameter to recieve the translation string
|
||||
* @param status Input/output parameter, set to success or
|
||||
* failure code upon return.
|
||||
* @return the input UnicodeString parameter for chaining
|
||||
* @internal ICU 3.8
|
||||
*/
|
||||
UnicodeString& getFallbackString(const UnicodeString &ID, UnicodeString &result, UErrorCode &status);
|
||||
|
||||
/**
|
||||
* Sets timezone string for the given the ID and translation type
|
||||
* @param ID The ID of zone strings, e.g: "America/Los_Angeles".
|
||||
* The time zone ID is for programmatic lookup.
|
||||
* @param type The translation type to set the value for
|
||||
* @param value The string with which current translation needs to be replaced
|
||||
* @param status Input/output parameter, set to success or
|
||||
* @internal ICU 3.6
|
||||
*/
|
||||
|
||||
/**
|
||||
* Determines if the Commonly Used flag is set for this zone
|
||||
* @param zid The ID of zone strings, e.g: "America/Los_Angeles".
|
||||
* The time zone ID is for programmatic lookup.
|
||||
* @return A boolean value indicating if the zone is commonlyUsed or not.
|
||||
* @internal ICU 3.8
|
||||
*/
|
||||
UBool isCommonlyUsed(const UnicodeString &zid);
|
||||
|
||||
/**
|
||||
* Sets timezone string for the given the ID and translation type
|
||||
* @param ID The ID of zone strings, e.g: "America/Los_Angeles".
|
||||
* The time zone ID is for programmatic lookup.
|
||||
* @param type The translation type to set the value for
|
||||
* @param value The string with which current translation needs to be replaced
|
||||
* @param status Input/output parameter, set to success or
|
||||
* @internal ICU 3.6
|
||||
*/
|
||||
void setZoneString(const UnicodeString &ID, const TimeZoneTranslationType type, const UnicodeString &value, UErrorCode &status);
|
||||
|
||||
private:
|
||||
|
||||
friend class SimpleDateFormat;
|
||||
|
@ -661,13 +569,34 @@ private:
|
|||
/**
|
||||
* The format data of all the timezones in this locale.
|
||||
*/
|
||||
UnicodeString** fZoneStrings;
|
||||
UnicodeString **fZoneStrings; // Zone string array set by setZoneStrings
|
||||
UnicodeString **fLocaleZoneStrings; // Zone string array created by the locale
|
||||
int32_t fZoneStringsRowCount;
|
||||
int32_t fZoneStringsColCount;
|
||||
StringEnumeration* fZoneIDEnumeration;
|
||||
Hashtable* fZoneStringsHash;
|
||||
UResourceBundle* fResourceBundle;
|
||||
const char* fCountry;
|
||||
|
||||
const ZoneStringFormat *fZoneStringFormat;
|
||||
ZoneStringFormat *fZSFLocal; // Local ZoneStringFormat instance
|
||||
SafeZoneStringFormatPtr *fZSFCachePtr; // Cached ZoneStringFormat
|
||||
Locale fZSFLocale; // Locale used for getting ZoneStringFormat
|
||||
|
||||
/**
|
||||
* Pattern string used for localized time zone GMT format. For example, "GMT{0}"
|
||||
*/
|
||||
UnicodeString fGmtFormat;
|
||||
|
||||
/**
|
||||
* Pattern strings used for formatting zone offset in a localized time zone GMT string.
|
||||
*/
|
||||
UnicodeString *fGmtHourFormats;
|
||||
int32_t fGmtHourFormatsCount;
|
||||
|
||||
enum GMTHourType {
|
||||
GMT_NEGATIVE_HMS = 0,
|
||||
GMT_NEGATIVE_HM,
|
||||
GMT_POSITIVE_HMS,
|
||||
GMT_POSITIVE_HM,
|
||||
GMT_HOUR_COUNT
|
||||
};
|
||||
|
||||
/**
|
||||
* Localized date-time pattern characters. For example: use 'u' as 'y'.
|
||||
|
@ -728,21 +657,6 @@ private:
|
|||
*/
|
||||
void createZoneStrings(const UnicodeString *const * otherStrings);
|
||||
|
||||
/**
|
||||
* Package private: used by SimpleDateFormat
|
||||
* Gets the index for the given time zone ID to obtain the timezone
|
||||
* strings for formatting. The time zone ID is just for programmatic
|
||||
* lookup. NOT LOCALIZED!!!
|
||||
* @param ID the given time zone ID.
|
||||
* @return the index of the given time zone ID. Returns -1 if
|
||||
* the given time zone ID can't be located in the DateFormatSymbols object.
|
||||
* @see java.util.SimpleTimeZone
|
||||
*/
|
||||
int32_t getZoneIndex(const UnicodeString& ID) const;
|
||||
|
||||
// Internal method; see source for documentation
|
||||
int32_t _getZoneIndex(const UnicodeString& id) const;
|
||||
|
||||
/**
|
||||
* Delete all the storage owned by this object.
|
||||
*/
|
||||
|
@ -754,67 +668,26 @@ private:
|
|||
*/
|
||||
void copyData(const DateFormatSymbols& other);
|
||||
|
||||
|
||||
/**
|
||||
* Returns a ZoneStringFormat, used only by SimpleDateFormat for now.
|
||||
*/
|
||||
const ZoneStringFormat* getZoneStringFormat(void) const;
|
||||
|
||||
/**
|
||||
* Create a ZoneStringFormat by locale if not yet availble
|
||||
*/
|
||||
void initZoneStringFormat(void);
|
||||
|
||||
/**
|
||||
* Create zone strings array by locale if not yet available
|
||||
*/
|
||||
void initZoneStringsArray(void);
|
||||
|
||||
/**
|
||||
* Delete just the zone strings.
|
||||
*/
|
||||
void disposeZoneStrings(void);
|
||||
|
||||
/**
|
||||
* Initializes the zoneStrings hash and keys StringEnumeration after reading the zoneStrings resource
|
||||
*/
|
||||
void initZoneStrings(UErrorCode &status);
|
||||
/**
|
||||
* initialzes the zoneStrings has and keys enumeration after reading the strings[][]. Required for backwards
|
||||
* compatibility of setZoneStrings method
|
||||
*/
|
||||
void initZoneStrings(const UnicodeString** strings, int32_t rowCount, int32_t collumnCount, UErrorCode& status);
|
||||
/**
|
||||
* initialization of the fZoneStrings data member
|
||||
*/
|
||||
void initZoneStringsArray(UErrorCode& status);
|
||||
/**
|
||||
* Creates a deep clone of the Hashtable
|
||||
*/
|
||||
Hashtable* createZoneStringsHash(const Hashtable* otherHash);
|
||||
|
||||
/**
|
||||
* Fetches the key from the hashtable for a given ID.
|
||||
* e.g: for a given ID such as PST returns "Americal/Los_Angeles"
|
||||
* Used by SimpleDateFormat class.
|
||||
* @param ID The id of the time zone for which the key needs to be fetched
|
||||
* @param result Output parameter to recieve the key.
|
||||
* @return the input UnicodeString object for chaining
|
||||
*/
|
||||
UnicodeString& getZoneID(const UnicodeString& zid, UnicodeString& result, UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Fetches the zone type and zone string from the hashtable for a given key.
|
||||
* e.g: for key: "Americal/Los_Angeles", text: "2004/1/1 PT 1:00" and start:9
|
||||
* returns TIMEZONE_SHORT_GENERIC and "PT".
|
||||
* Used by SimpleDateFormat class.
|
||||
* @param ID the name of the timezone
|
||||
* @param text the string containing the time zone translation
|
||||
* @param start The position in string where time zone string starts
|
||||
* @param type output parameter to recieve the type of time zone string
|
||||
* @param value output parameter to recieve the the acutal time zone string
|
||||
*/
|
||||
void getZoneType(const UnicodeString& zid, const UnicodeString& text, int32_t start, TimeZoneTranslationType& type, UnicodeString& value, UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Fetches the zone type and zone string from the hashtable by cycling through all elements in the hashtable.
|
||||
* e.g: text: "2004/1/1 PT 1:00" and start:9
|
||||
* returns "Americal/Los_Angeles", TIMEZONE_SHORT_GENERIC and "PT". Used by SimpleDateFormat class.
|
||||
* Used by SimpleDateFormat class.
|
||||
* @param ID output parameter to recieve the key name of the time zone
|
||||
* @param text the string containing the time zone translation
|
||||
* @param start The position in string where time zone string starts
|
||||
* @param type output parameter to recieve the type of time zone string
|
||||
* @param value output parameter to recieve the the acutal time zone string
|
||||
* @param status output parameter to recive the error information
|
||||
*/
|
||||
void findZoneIDTypeValue(UnicodeString& zid, const UnicodeString& text, int32_t start, TimeZoneTranslationType& type, UnicodeString& value, UErrorCode& status);
|
||||
|
||||
UnicodeString resolveParsedMetazone(const UnicodeString& zid);
|
||||
};
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
|
|
@ -23,6 +23,7 @@ U_NAMESPACE_BEGIN
|
|||
|
||||
// forward declaration
|
||||
class UVector;
|
||||
struct Transition;
|
||||
|
||||
class U_I18N_API RuleBasedTimeZone : public BasicTimeZone {
|
||||
public:
|
||||
|
@ -289,13 +290,27 @@ public:
|
|||
virtual void getTimeZoneRules(const InitialTimeZoneRule*& initial,
|
||||
const TimeZoneRule* trsrules[], int32_t& trscount, UErrorCode& status) /*const*/;
|
||||
|
||||
/**
|
||||
* Get time zone offsets from local wall time.
|
||||
* @internal
|
||||
*/
|
||||
virtual void getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt,
|
||||
int32_t& rawOffset, int32_t& dstOffset, UErrorCode& status) /*const*/;
|
||||
|
||||
private:
|
||||
void deleteRules(void);
|
||||
void deleteTransitions(void);
|
||||
UVector* copyRules(UVector* source);
|
||||
TimeZoneRule* findRuleInFinal(UDate date, UBool local) const;
|
||||
TimeZoneRule* findRuleInFinal(UDate date, UBool local,
|
||||
int32_t NonExistingTimeOpt, int32_t DuplicatedTimeOpt) const;
|
||||
UBool findNext(UDate base, UBool inclusive, UDate& time, TimeZoneRule*& from, TimeZoneRule*& to) const;
|
||||
UBool findPrev(UDate base, UBool inclusive, UDate& time, TimeZoneRule*& from, TimeZoneRule*& to) const;
|
||||
int32_t getLocalDelta(int32_t rawBefore, int32_t dstBefore, int32_t rawAfter, int32_t dstAfter,
|
||||
int32_t NonExistingTimeOpt, int32_t DuplicatedTimeOpt) const;
|
||||
UDate getTransitionTime(Transition* transition, UBool local,
|
||||
int32_t NonExistingTimeOpt, int32_t DuplicatedTimeOpt) const;
|
||||
void getOffsetInternal(UDate date, UBool local, int32_t NonExistingTimeOpt, int32_t DuplicatedTimeOpt,
|
||||
int32_t& rawOffset, int32_t& dstOffset, UErrorCode& ec) const;
|
||||
|
||||
InitialTimeZoneRule *fInitialRule;
|
||||
UVector *fHistoricRules;
|
||||
|
|
|
@ -616,6 +616,13 @@ public:
|
|||
virtual void getOffset(UDate date, UBool local, int32_t& rawOffset,
|
||||
int32_t& dstOffset, UErrorCode& ec) const;
|
||||
|
||||
/**
|
||||
* Get time zone offsets from local wall time.
|
||||
* @internal
|
||||
*/
|
||||
virtual void getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt,
|
||||
int32_t& rawOffset, int32_t& dstOffset, UErrorCode& status) /*const*/;
|
||||
|
||||
/**
|
||||
* Returns the TimeZone's raw GMT offset (i.e., the number of milliseconds to add
|
||||
* to GMT to get local time, before taking daylight savings time into account).
|
||||
|
|
|
@ -38,6 +38,7 @@ U_NAMESPACE_BEGIN
|
|||
|
||||
class DateFormatSymbols;
|
||||
class DateFormat;
|
||||
class MessageFormat;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -649,13 +650,6 @@ private:
|
|||
Calendar& cal,
|
||||
UErrorCode& status) const; // in case of illegal argument
|
||||
|
||||
/**
|
||||
* Used to resolve Time Zone aliases
|
||||
*
|
||||
* @param zid Time Zone ID to Canonicalize ( resolve aliases )
|
||||
*/
|
||||
void zoneIDCanonicalize( UnicodeString & ) const;
|
||||
|
||||
/**
|
||||
* Used by subFormat() to format a numeric value.
|
||||
* Appends to toAppendTo a string representation of "value"
|
||||
|
@ -767,6 +761,12 @@ private:
|
|||
ParsePosition& pos,
|
||||
UBool allowNegative) const;
|
||||
|
||||
void parseInt(const UnicodeString& text,
|
||||
Formattable& number,
|
||||
int32_t maxDigits,
|
||||
ParsePosition& pos,
|
||||
UBool allowNegative) const;
|
||||
|
||||
/**
|
||||
* Translate a pattern, mapping each character in the from string to the
|
||||
* corresponding character in the to string. Return an error if the original
|
||||
|
@ -793,25 +793,22 @@ private:
|
|||
* if the operation succeeds.
|
||||
*/
|
||||
void parseAmbiguousDatesAsAfter(UDate startDate, UErrorCode& status);
|
||||
|
||||
/**
|
||||
* Given text, a start in the text, and a row index, return the column index that
|
||||
* of the zone name that matches (case insensitive) at start, or 0 if none matches.
|
||||
*
|
||||
int32_t matchZoneString(const UnicodeString& text, int32_t start, int32_t zi) const;
|
||||
*/
|
||||
|
||||
/**
|
||||
* Given text, a start in the text, and a calendar, return the next offset in the text
|
||||
* after matching the zone string. If we fail to match, return 0. Update the calendar
|
||||
* as appropriate.
|
||||
*/
|
||||
int32_t subParseZoneString(const UnicodeString& text, int32_t start, Calendar& cal, UErrorCode& status) const;
|
||||
|
||||
/**
|
||||
* append the gmt string
|
||||
* Private methods for formatting/parsing GMT string
|
||||
*/
|
||||
inline void appendGMT(UnicodeString &appendTo, Calendar& cal, UErrorCode& status) const;
|
||||
void appendGMT(UnicodeString &appendTo, Calendar& cal, UErrorCode& status) const;
|
||||
void formatGMTDefault(UnicodeString &appendTo, int32_t offset) const;
|
||||
int32_t parseGMT(const UnicodeString &text, ParsePosition &pos) const;
|
||||
int32_t parseGMTDefault(const UnicodeString &text, ParsePosition &pos) const;
|
||||
UBool isDefaultGMTFormat() const;
|
||||
|
||||
void formatRFC822TZ(UnicodeString &appendTo, int32_t offset) const;
|
||||
|
||||
/**
|
||||
* Initialize MessageFormat instances used for GMT formatting/parsing
|
||||
*/
|
||||
void initGMTFormatters(UErrorCode &status);
|
||||
|
||||
/**
|
||||
* Used to map pattern characters to Calendar field identifiers.
|
||||
|
@ -854,7 +851,18 @@ private:
|
|||
*/
|
||||
/*transient*/ int32_t fDefaultCenturyStartYear;
|
||||
|
||||
/*transient*/ TimeZone* parsedTimeZone; // here to avoid api change
|
||||
enum ParsedTZType {
|
||||
TZTYPE_UNK,
|
||||
TZTYPE_STD,
|
||||
TZTYPE_DST
|
||||
};
|
||||
|
||||
ParsedTZType tztype; // here to avoid api change
|
||||
|
||||
/*
|
||||
* MessageFormat instances used for localized GMT format
|
||||
*/
|
||||
MessageFormat **fGMTFormatters;
|
||||
|
||||
UBool fHaveDefaultCentury;
|
||||
};
|
||||
|
|
|
@ -670,6 +670,15 @@ protected:
|
|||
static UResourceBundle* loadRule(const UResourceBundle* top, const UnicodeString& ruleid, UResourceBundle* oldbundle, UErrorCode&status);
|
||||
|
||||
private:
|
||||
friend class ZoneMeta;
|
||||
|
||||
/**
|
||||
* Get a canonical Olson zone ID for the given ID. If the given ID is not valid,
|
||||
* this method returns empty string as the result. If the given ID is a link, then the
|
||||
* referenced ID (canonical ID) is returned.
|
||||
*/
|
||||
static UnicodeString& getOlsonCanonicalID(const UnicodeString &id, UnicodeString &canonical);
|
||||
|
||||
static TimeZone* createCustomTimeZone(const UnicodeString&); // Creates a time zone based on the string.
|
||||
|
||||
/**
|
||||
|
|
930
icu4c/source/i18n/zonemeta.cpp
Normal file
930
icu4c/source/i18n/zonemeta.cpp
Normal file
|
@ -0,0 +1,930 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2007, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
#if !UCONFIG_NO_FORMATTING
|
||||
|
||||
#include "zonemeta.h"
|
||||
|
||||
#include "unicode/timezone.h"
|
||||
#include "unicode/ustring.h"
|
||||
#include "unicode/putil.h"
|
||||
|
||||
#include "umutex.h"
|
||||
#include "uvector.h"
|
||||
#include "cmemory.h"
|
||||
#include "gregoimp.h"
|
||||
#include "cstring.h"
|
||||
#include "ucln_in.h"
|
||||
|
||||
static UBool gZoneMetaInitialized = FALSE;
|
||||
|
||||
// Metazone mapping tables
|
||||
static UMTX gZoneMetaLock = NULL;
|
||||
static U_NAMESPACE_QUALIFIER Hashtable *gCanonicalMap = NULL;
|
||||
static U_NAMESPACE_QUALIFIER Hashtable *gOlsonToMeta = NULL;
|
||||
static U_NAMESPACE_QUALIFIER Hashtable *gMetaToOlson = NULL;
|
||||
|
||||
U_CDECL_BEGIN
|
||||
/**
|
||||
* Cleanup callback func
|
||||
*/
|
||||
static UBool U_CALLCONV zoneMeta_cleanup(void)
|
||||
{
|
||||
umtx_destroy(&gZoneMetaLock);
|
||||
|
||||
if (gCanonicalMap != NULL) {
|
||||
delete (U_NAMESPACE_QUALIFIER Hashtable*) gCanonicalMap;
|
||||
gCanonicalMap = NULL;
|
||||
}
|
||||
|
||||
if (gOlsonToMeta != NULL) {
|
||||
delete (U_NAMESPACE_QUALIFIER Hashtable*) gOlsonToMeta;
|
||||
gOlsonToMeta = NULL;
|
||||
}
|
||||
|
||||
if (gMetaToOlson != NULL) {
|
||||
delete (U_NAMESPACE_QUALIFIER Hashtable*) gMetaToOlson;
|
||||
gMetaToOlson = NULL;
|
||||
}
|
||||
|
||||
gZoneMetaInitialized = FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deleter for UVector
|
||||
*/
|
||||
static void U_CALLCONV
|
||||
deleteUVector(void *obj) {
|
||||
delete (U_NAMESPACE_QUALIFIER UVector*) obj;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deleter for CanonicalMapEntry
|
||||
*/
|
||||
static void U_CALLCONV
|
||||
deleteCanonicalMapEntry(void *obj) {
|
||||
U_NAMESPACE_QUALIFIER CanonicalMapEntry *entry = (U_NAMESPACE_QUALIFIER CanonicalMapEntry*)obj;
|
||||
uprv_free(entry->id);
|
||||
if (entry->country != NULL) {
|
||||
uprv_free(entry->country);
|
||||
}
|
||||
uprv_free(entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deleter for OlsonToMetaMappingEntry
|
||||
*/
|
||||
static void U_CALLCONV
|
||||
deleteOlsonToMetaMappingEntry(void *obj) {
|
||||
U_NAMESPACE_QUALIFIER OlsonToMetaMappingEntry *entry = (U_NAMESPACE_QUALIFIER OlsonToMetaMappingEntry*)obj;
|
||||
uprv_free(entry->mzid);
|
||||
uprv_free(entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deleter for MetaToOlsonMappingEntry
|
||||
*/
|
||||
static void U_CALLCONV
|
||||
deleteMetaToOlsonMappingEntry(void *obj) {
|
||||
U_NAMESPACE_QUALIFIER MetaToOlsonMappingEntry *entry = (U_NAMESPACE_QUALIFIER MetaToOlsonMappingEntry*)obj;
|
||||
uprv_free(entry->id);
|
||||
uprv_free(entry->territory);
|
||||
uprv_free(entry);
|
||||
}
|
||||
U_CDECL_END
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
#define ZID_KEY_MAX 128
|
||||
static const char gZoneStringsTag[] = "zoneStrings";
|
||||
static const char gUseMetazoneTag[] = "um";
|
||||
|
||||
static const char gSupplementalData[] = "supplementalData";
|
||||
static const char gMapTimezonesTag[] = "mapTimezones";
|
||||
static const char gMetazonesTag[] = "metazones";
|
||||
static const char gZoneFormattingTag[] = "zoneFormatting";
|
||||
static const char gTerritoryTag[] = "territory";
|
||||
static const char gAliasesTag[] = "aliases";
|
||||
static const char gMultizoneTag[] = "multizone";
|
||||
|
||||
static const char gMetazoneInfo[] = "metazoneInfo";
|
||||
static const char gMetazoneMappings[] = "metazoneMappings";
|
||||
|
||||
#define MZID_PREFIX_LEN 5
|
||||
static const char gMetazoneIdPrefix[] = "meta:";
|
||||
|
||||
static const UChar gWorld[] = {0x30, 0x30, 0x31, 0x00}; // "001"
|
||||
|
||||
#define ASCII_DIGIT(c) (((c)>=0x30 && (c)<=0x39) ? (c)-0x30 : -1)
|
||||
|
||||
/*
|
||||
* Convert a date string used by metazone mappings to UDate.
|
||||
* The format used by CLDR metazone mapping is "yyyy-MM-dd HH:mm".
|
||||
*/
|
||||
static UDate parseDate (const UChar *text, UErrorCode &status) {
|
||||
if (U_FAILURE(status)) {
|
||||
return 0;
|
||||
}
|
||||
int32_t year = 0, month = 0, day = 0, hour = 0, min = 0, n;
|
||||
int32_t idx;
|
||||
|
||||
// "yyyy" (0 - 3)
|
||||
for (idx = 0; idx <= 3 && U_SUCCESS(status); idx++) {
|
||||
n = ASCII_DIGIT(text[idx]);
|
||||
if (n >= 0) {
|
||||
year = 10*year + n;
|
||||
} else {
|
||||
status = U_INVALID_FORMAT_ERROR;
|
||||
}
|
||||
}
|
||||
// "MM" (5 - 6)
|
||||
for (idx = 5; idx <= 6 && U_SUCCESS(status); idx++) {
|
||||
n = ASCII_DIGIT(text[idx]);
|
||||
if (n >= 0) {
|
||||
month = 10*month + n;
|
||||
} else {
|
||||
status = U_INVALID_FORMAT_ERROR;
|
||||
}
|
||||
}
|
||||
// "dd" (8 - 9)
|
||||
for (idx = 8; idx <= 9 && U_SUCCESS(status); idx++) {
|
||||
n = ASCII_DIGIT(text[idx]);
|
||||
if (n >= 0) {
|
||||
day = 10*day + n;
|
||||
} else {
|
||||
status = U_INVALID_FORMAT_ERROR;
|
||||
}
|
||||
}
|
||||
// "HH" (11 - 12)
|
||||
for (idx = 11; idx <= 12 && U_SUCCESS(status); idx++) {
|
||||
n = ASCII_DIGIT(text[idx]);
|
||||
if (n >= 0) {
|
||||
hour = 10*hour + n;
|
||||
} else {
|
||||
status = U_INVALID_FORMAT_ERROR;
|
||||
}
|
||||
}
|
||||
// "mm" (14 - 15)
|
||||
for (idx = 14; idx <= 15 && U_SUCCESS(status); idx++) {
|
||||
n = ASCII_DIGIT(text[idx]);
|
||||
if (n >= 0) {
|
||||
min = 10*min + n;
|
||||
} else {
|
||||
status = U_INVALID_FORMAT_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (U_SUCCESS(status)) {
|
||||
UDate date = Grego::fieldsToDay(year, month - 1, day) * U_MILLIS_PER_DAY
|
||||
+ hour * U_MILLIS_PER_HOUR + min * U_MILLIS_PER_MINUTE;
|
||||
return date;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize global objects
|
||||
*/
|
||||
void
|
||||
ZoneMeta::initialize(void) {
|
||||
UBool initialized;
|
||||
UMTX_CHECK(&gZoneMetaLock, gZoneMetaInitialized, initialized);
|
||||
if (initialized) {
|
||||
return;
|
||||
}
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
// Initialize hash tables
|
||||
Hashtable *tmpCanonicalMap = createCanonicalMap();
|
||||
Hashtable *tmpOlsonToMeta = createOlsonToMetaMap();
|
||||
if (tmpOlsonToMeta == NULL) {
|
||||
// With ICU 3.8 data
|
||||
createOlsonToMetaMapOld();
|
||||
}
|
||||
Hashtable *tmpMetaToOlson = createMetaToOlsonMap();
|
||||
|
||||
umtx_lock(&gZoneMetaLock);
|
||||
if (gZoneMetaInitialized) {
|
||||
// Another thread already created mappings
|
||||
delete tmpCanonicalMap;
|
||||
delete tmpOlsonToMeta;
|
||||
delete tmpMetaToOlson;
|
||||
} else {
|
||||
gZoneMetaInitialized = TRUE;
|
||||
gCanonicalMap = tmpCanonicalMap;
|
||||
gOlsonToMeta = tmpOlsonToMeta;
|
||||
gMetaToOlson = tmpMetaToOlson;
|
||||
ucln_i18n_registerCleanup(UCLN_I18N_ZONEMETA, zoneMeta_cleanup);
|
||||
}
|
||||
umtx_unlock(&gZoneMetaLock);
|
||||
}
|
||||
|
||||
Hashtable*
|
||||
ZoneMeta::createCanonicalMap(void) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
Hashtable *canonicalMap = NULL;
|
||||
UResourceBundle *supplementalDataBundle = NULL;
|
||||
UResourceBundle *zoneFormatting = NULL;
|
||||
UResourceBundle *tzitem = NULL;
|
||||
UResourceBundle *aliases = NULL;
|
||||
|
||||
canonicalMap = new Hashtable(uhash_compareUnicodeString, NULL, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return NULL;
|
||||
}
|
||||
canonicalMap->setValueDeleter(deleteCanonicalMapEntry);
|
||||
|
||||
supplementalDataBundle = ures_openDirect(NULL, gSupplementalData, &status);
|
||||
zoneFormatting = ures_getByKey(supplementalDataBundle, gZoneFormattingTag, NULL, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
goto error_cleanup;
|
||||
}
|
||||
|
||||
while (ures_hasNext(zoneFormatting)) {
|
||||
tzitem = ures_getNextResource(zoneFormatting, NULL, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
ures_close(tzitem);
|
||||
tzitem = NULL;
|
||||
status = U_ZERO_ERROR;
|
||||
continue;
|
||||
}
|
||||
if (ures_getType(tzitem) != URES_TABLE) {
|
||||
ures_close(tzitem);
|
||||
tzitem = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
int32_t territoryLen;
|
||||
const UChar *territory = ures_getStringByKey(tzitem, gTerritoryTag, &territoryLen, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
territory = NULL;
|
||||
status = U_ZERO_ERROR;
|
||||
}
|
||||
|
||||
int32_t tzidLen = 0;
|
||||
char tzid[ZID_KEY_MAX];
|
||||
const char *tzkey = ures_getKey(tzitem);
|
||||
uprv_strcpy(tzid, tzkey);
|
||||
// Replace ':' with '/'
|
||||
char *p = tzid;
|
||||
while (*p) {
|
||||
if (*p == ':') {
|
||||
*p = '/';
|
||||
}
|
||||
p++;
|
||||
tzidLen++;
|
||||
}
|
||||
|
||||
// Create canonical map entry
|
||||
CanonicalMapEntry *entry = (CanonicalMapEntry*)uprv_malloc(sizeof(CanonicalMapEntry));
|
||||
if (entry == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
goto error_cleanup;
|
||||
}
|
||||
entry->id = (UChar*)uprv_malloc((tzidLen + 1) * sizeof(UChar));
|
||||
if (entry->id == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
uprv_free(entry);
|
||||
goto error_cleanup;
|
||||
}
|
||||
u_charsToUChars(tzid, entry->id, tzidLen + 1);
|
||||
|
||||
if (territory == NULL || u_strcmp(territory, gWorld) == 0) {
|
||||
entry->country = NULL;
|
||||
} else {
|
||||
entry->country = (UChar*)uprv_malloc((territoryLen + 1) * sizeof(UChar));
|
||||
if (entry->country == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
deleteCanonicalMapEntry(entry);
|
||||
goto error_cleanup;
|
||||
}
|
||||
u_strcpy(entry->country, territory);
|
||||
}
|
||||
|
||||
// Put this entry to the table
|
||||
canonicalMap->put(UnicodeString(tzid), entry, status);
|
||||
if (U_FAILURE(status)) {
|
||||
deleteCanonicalMapEntry(entry);
|
||||
goto error_cleanup;
|
||||
}
|
||||
|
||||
// Get aliases
|
||||
aliases = ures_getByKey(tzitem, gAliasesTag, NULL, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
// No aliases
|
||||
status = U_ZERO_ERROR;
|
||||
ures_close(tzitem);
|
||||
continue;
|
||||
}
|
||||
|
||||
while (ures_hasNext(aliases)) {
|
||||
int32_t aliasLen;
|
||||
const UChar* alias = ures_getNextString(aliases, &aliasLen, NULL, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
status = U_ZERO_ERROR;
|
||||
continue;
|
||||
}
|
||||
// Create canonical map entry for this alias
|
||||
entry = (CanonicalMapEntry*)uprv_malloc(sizeof(CanonicalMapEntry));
|
||||
if (entry == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
goto error_cleanup;
|
||||
}
|
||||
entry->id = (UChar*)uprv_malloc((tzidLen + 1) * sizeof(UChar));
|
||||
if (entry->id == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
uprv_free(entry);
|
||||
goto error_cleanup;
|
||||
}
|
||||
u_charsToUChars(tzid, entry->id, tzidLen + 1);
|
||||
|
||||
if (territory == NULL || u_strcmp(territory, gWorld) == 0) {
|
||||
entry->country = NULL;
|
||||
} else {
|
||||
entry->country = (UChar*)uprv_malloc((territoryLen + 1) * sizeof(UChar));
|
||||
if (entry->country == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
deleteCanonicalMapEntry(entry);
|
||||
goto error_cleanup;
|
||||
}
|
||||
u_strcpy(entry->country, territory);
|
||||
}
|
||||
canonicalMap->put(UnicodeString(alias), entry, status);
|
||||
if (U_FAILURE(status)) {
|
||||
deleteCanonicalMapEntry(entry);
|
||||
goto error_cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
ures_close(aliases);
|
||||
ures_close(tzitem);
|
||||
}
|
||||
|
||||
ures_close(zoneFormatting);
|
||||
ures_close(supplementalDataBundle);
|
||||
return canonicalMap;
|
||||
|
||||
error_cleanup:
|
||||
ures_close(aliases);
|
||||
ures_close(tzitem);
|
||||
ures_close(zoneFormatting);
|
||||
ures_close(supplementalDataBundle);
|
||||
delete canonicalMap;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creating Olson tzid to metazone mappings from resource (3.8.1 and beyond)
|
||||
*/
|
||||
Hashtable*
|
||||
ZoneMeta::createOlsonToMetaMap(void) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
Hashtable *olsonToMeta = NULL;
|
||||
UResourceBundle *metazoneInfoBundle = NULL;
|
||||
UResourceBundle *metazoneMappings = NULL;
|
||||
StringEnumeration *tzids = NULL;
|
||||
|
||||
olsonToMeta = new Hashtable(uhash_compareUnicodeString, NULL, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return NULL;
|
||||
}
|
||||
olsonToMeta->setValueDeleter(deleteUVector);
|
||||
|
||||
// Read metazone mappings from metazoneInfo bundle
|
||||
metazoneInfoBundle = ures_openDirect(NULL, gMetazoneInfo, &status);
|
||||
metazoneMappings = ures_getByKey(metazoneInfoBundle, gMetazoneMappings, NULL, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
goto error_cleanup;
|
||||
}
|
||||
|
||||
// Walk through all canonical tzids
|
||||
char zidkey[ZID_KEY_MAX];
|
||||
|
||||
tzids = TimeZone::createEnumeration();
|
||||
const char *tzid;
|
||||
while ((tzid = tzids->next(NULL, status))) {
|
||||
if (U_FAILURE(status)) {
|
||||
goto error_cleanup;
|
||||
}
|
||||
// We may skip aliases, because the bundle
|
||||
// contains only canonical IDs. For now, try
|
||||
// all of them.
|
||||
uprv_strcpy(zidkey, tzid);
|
||||
|
||||
// Replace '/' with ':'
|
||||
UBool foundSep = FALSE;
|
||||
char *p = zidkey;
|
||||
while (*p) {
|
||||
if (*p == '/') {
|
||||
*p = ':';
|
||||
foundSep = TRUE;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
if (!foundSep) {
|
||||
// A valid time zone key has at least one separator
|
||||
continue;
|
||||
}
|
||||
|
||||
UResourceBundle *zoneItem = ures_getByKey(metazoneMappings, zidkey, NULL, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
status = U_ZERO_ERROR;
|
||||
ures_close(zoneItem);
|
||||
continue;
|
||||
}
|
||||
|
||||
UVector *mzMappings = NULL;
|
||||
while (ures_hasNext(zoneItem)) {
|
||||
UResourceBundle *mz = ures_getNextResource(zoneItem, NULL, &status);
|
||||
int32_t len;
|
||||
const UChar *mz_name = ures_getStringByIndex(mz, 0, &len, &status);
|
||||
const UChar *mz_from = ures_getStringByIndex(mz, 1, &len, &status);
|
||||
const UChar *mz_to = ures_getStringByIndex(mz, 2, &len, &status);
|
||||
ures_close(mz);
|
||||
|
||||
if(U_FAILURE(status)){
|
||||
status = U_ZERO_ERROR;
|
||||
continue;
|
||||
}
|
||||
// We do not want to use SimpleDateformat to parse boundary dates,
|
||||
// because this code could be triggered by the initialization code
|
||||
// used by SimpleDateFormat.
|
||||
UDate from = parseDate(mz_from, status);
|
||||
UDate to = parseDate(mz_to, status);
|
||||
if (U_FAILURE(status)) {
|
||||
status = U_ZERO_ERROR;
|
||||
continue;
|
||||
}
|
||||
|
||||
OlsonToMetaMappingEntry *entry = (OlsonToMetaMappingEntry*)uprv_malloc(sizeof(OlsonToMetaMappingEntry));
|
||||
if (entry == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
break;
|
||||
}
|
||||
entry->mzid = (UChar*)uprv_malloc((u_strlen(mz_name) + 1) * sizeof(UChar));
|
||||
if (entry->mzid == NULL) {
|
||||
uprv_free(entry);
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
break;
|
||||
}
|
||||
u_strcpy(entry->mzid, mz_name);
|
||||
entry->from = from;
|
||||
entry->to = to;
|
||||
|
||||
if (mzMappings == NULL) {
|
||||
mzMappings = new UVector(deleteOlsonToMetaMappingEntry, NULL, status);
|
||||
if (U_FAILURE(status)) {
|
||||
delete mzMappings;
|
||||
deleteOlsonToMetaMappingEntry(entry);
|
||||
uprv_free(entry);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mzMappings->addElement(entry, status);
|
||||
if (U_FAILURE(status)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ures_close(zoneItem);
|
||||
|
||||
if (U_FAILURE(status)) {
|
||||
if (mzMappings != NULL) {
|
||||
delete mzMappings;
|
||||
}
|
||||
goto error_cleanup;
|
||||
}
|
||||
if (mzMappings != NULL) {
|
||||
olsonToMeta->put(UnicodeString(tzid), mzMappings, status);
|
||||
if (U_FAILURE(status)) {
|
||||
delete mzMappings;
|
||||
goto error_cleanup;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete tzids;
|
||||
ures_close(metazoneMappings);
|
||||
ures_close(metazoneInfoBundle);
|
||||
return olsonToMeta;
|
||||
|
||||
error_cleanup:
|
||||
if (tzids != NULL) {
|
||||
delete tzids;
|
||||
}
|
||||
ures_close(metazoneMappings);
|
||||
ures_close(metazoneInfoBundle);
|
||||
if (olsonToMeta != NULL) {
|
||||
delete olsonToMeta;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creating Olson tzid to metazone mappings from ICU resource (3.8)
|
||||
*/
|
||||
Hashtable*
|
||||
ZoneMeta::createOlsonToMetaMapOld(void) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
Hashtable *olsonToMeta = NULL;
|
||||
UResourceBundle *rootBundle = NULL;
|
||||
UResourceBundle *zoneStringsArray = NULL;
|
||||
StringEnumeration *tzids = NULL;
|
||||
|
||||
olsonToMeta = new Hashtable(uhash_compareUnicodeString, NULL, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return NULL;
|
||||
}
|
||||
olsonToMeta->setValueDeleter(deleteUVector);
|
||||
|
||||
// Read metazone mappings from root bundle
|
||||
rootBundle = ures_openDirect(NULL, "", &status);
|
||||
zoneStringsArray = ures_getByKey(rootBundle, gZoneStringsTag, NULL, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
goto error_cleanup;
|
||||
}
|
||||
|
||||
// Walk through all canonical tzids
|
||||
char zidkey[ZID_KEY_MAX];
|
||||
|
||||
tzids = TimeZone::createEnumeration();
|
||||
const char *tzid;
|
||||
while ((tzid = tzids->next(NULL, status))) {
|
||||
if (U_FAILURE(status)) {
|
||||
goto error_cleanup;
|
||||
}
|
||||
// We may skip aliases, because the bundle
|
||||
// contains only canonical IDs. For now, try
|
||||
// all of them.
|
||||
uprv_strcpy(zidkey, tzid);
|
||||
|
||||
// Replace '/' with ':'
|
||||
UBool foundSep = FALSE;
|
||||
char *p = zidkey;
|
||||
while (*p) {
|
||||
if (*p == '/') {
|
||||
*p = ':';
|
||||
foundSep = TRUE;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
if (!foundSep) {
|
||||
// A valid time zone key has at least one separator
|
||||
continue;
|
||||
}
|
||||
|
||||
UResourceBundle *zoneItem = ures_getByKey(zoneStringsArray, zidkey, NULL, &status);
|
||||
UResourceBundle *useMZ = ures_getByKey(zoneItem, gUseMetazoneTag, NULL, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
status = U_ZERO_ERROR;
|
||||
ures_close(zoneItem);
|
||||
ures_close(useMZ);
|
||||
continue;
|
||||
}
|
||||
|
||||
UVector *mzMappings = NULL;
|
||||
while (ures_hasNext(useMZ)) {
|
||||
UResourceBundle *mz = ures_getNextResource(useMZ, NULL, &status);
|
||||
int32_t len;
|
||||
const UChar *mz_name = ures_getStringByIndex(mz, 0, &len, &status);
|
||||
const UChar *mz_from = ures_getStringByIndex(mz, 1, &len, &status);
|
||||
const UChar *mz_to = ures_getStringByIndex(mz, 2, &len, &status);
|
||||
ures_close(mz);
|
||||
|
||||
if(U_FAILURE(status)){
|
||||
status = U_ZERO_ERROR;
|
||||
continue;
|
||||
}
|
||||
// We do not want to use SimpleDateformat to parse boundary dates,
|
||||
// because this code could be triggered by the initialization code
|
||||
// used by SimpleDateFormat.
|
||||
UDate from = parseDate(mz_from, status);
|
||||
UDate to = parseDate(mz_to, status);
|
||||
if (U_FAILURE(status)) {
|
||||
status = U_ZERO_ERROR;
|
||||
continue;
|
||||
}
|
||||
|
||||
OlsonToMetaMappingEntry *entry = (OlsonToMetaMappingEntry*)uprv_malloc(sizeof(OlsonToMetaMappingEntry));
|
||||
if (entry == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
break;
|
||||
}
|
||||
entry->mzid = (UChar*)uprv_malloc((u_strlen(mz_name) + 1) * sizeof(UChar));
|
||||
if (entry->mzid == NULL) {
|
||||
uprv_free(entry);
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
break;
|
||||
}
|
||||
u_strcpy(entry->mzid, mz_name);
|
||||
entry->from = from;
|
||||
entry->to = to;
|
||||
|
||||
if (mzMappings == NULL) {
|
||||
mzMappings = new UVector(deleteOlsonToMetaMappingEntry, NULL, status);
|
||||
if (U_FAILURE(status)) {
|
||||
delete mzMappings;
|
||||
deleteOlsonToMetaMappingEntry(entry);
|
||||
uprv_free(entry);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mzMappings->addElement(entry, status);
|
||||
if (U_FAILURE(status)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ures_close(zoneItem);
|
||||
ures_close(useMZ);
|
||||
|
||||
if (U_FAILURE(status)) {
|
||||
if (mzMappings != NULL) {
|
||||
delete mzMappings;
|
||||
}
|
||||
goto error_cleanup;
|
||||
}
|
||||
if (mzMappings != NULL) {
|
||||
olsonToMeta->put(UnicodeString(tzid), mzMappings, status);
|
||||
if (U_FAILURE(status)) {
|
||||
delete mzMappings;
|
||||
goto error_cleanup;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
delete tzids;
|
||||
ures_close(zoneStringsArray);
|
||||
ures_close(rootBundle);
|
||||
return olsonToMeta;
|
||||
|
||||
error_cleanup:
|
||||
if (tzids != NULL) {
|
||||
delete tzids;
|
||||
}
|
||||
ures_close(zoneStringsArray);
|
||||
ures_close(rootBundle);
|
||||
if (olsonToMeta != NULL) {
|
||||
delete olsonToMeta;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Hashtable*
|
||||
ZoneMeta::createMetaToOlsonMap(void) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
Hashtable *metaToOlson = NULL;
|
||||
UResourceBundle *supplementalDataBundle = NULL;
|
||||
UResourceBundle *mapTimezones = NULL;
|
||||
UResourceBundle *metazones = NULL;
|
||||
|
||||
metaToOlson = new Hashtable(uhash_compareUnicodeString, NULL, status);
|
||||
if (U_FAILURE(status)) {
|
||||
return NULL;
|
||||
}
|
||||
metaToOlson->setValueDeleter(deleteUVector);
|
||||
|
||||
supplementalDataBundle = ures_openDirect(NULL, gSupplementalData, &status);
|
||||
mapTimezones = ures_getByKey(supplementalDataBundle, gMapTimezonesTag, NULL, &status);
|
||||
metazones = ures_getByKey(mapTimezones, gMetazonesTag, NULL, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
goto error_cleanup;
|
||||
}
|
||||
|
||||
while (ures_hasNext(metazones)) {
|
||||
UResourceBundle *mz = ures_getNextResource(metazones, NULL, &status);
|
||||
if (U_FAILURE(status)) {
|
||||
ures_close(mz);
|
||||
status = U_ZERO_ERROR;
|
||||
continue;
|
||||
}
|
||||
const char *mzkey = ures_getKey(mz);
|
||||
if (uprv_strncmp(mzkey, gMetazoneIdPrefix, MZID_PREFIX_LEN) == 0) {
|
||||
const char *mzid = mzkey + MZID_PREFIX_LEN;
|
||||
const char *territory = uprv_strrchr(mzid, '_');
|
||||
int32_t mzidLen = 0;
|
||||
int32_t territoryLen = 0;
|
||||
if (territory) {
|
||||
mzidLen = territory - mzid;
|
||||
territory++;
|
||||
territoryLen = uprv_strlen(territory);
|
||||
}
|
||||
if (mzidLen > 0 && territoryLen > 0) {
|
||||
int32_t tzidLen;
|
||||
const UChar *tzid = ures_getStringByIndex(mz, 0, &tzidLen, &status);
|
||||
if (U_SUCCESS(status)) {
|
||||
// Create MetaToOlsonMappingEntry
|
||||
MetaToOlsonMappingEntry *entry = (MetaToOlsonMappingEntry*)uprv_malloc(sizeof(MetaToOlsonMappingEntry));
|
||||
if (entry == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
ures_close(mz);
|
||||
goto error_cleanup;
|
||||
}
|
||||
entry->id = (UChar*)uprv_malloc((tzidLen + 1) * sizeof(UChar));
|
||||
if (entry->id == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
uprv_free(entry);
|
||||
ures_close(mz);
|
||||
goto error_cleanup;
|
||||
}
|
||||
u_strcpy(entry->id, tzid);
|
||||
|
||||
entry->territory = (UChar*)uprv_malloc((territoryLen + 1) * sizeof(UChar));
|
||||
if (entry->territory == NULL) {
|
||||
status = U_MEMORY_ALLOCATION_ERROR;
|
||||
uprv_free(entry->id);
|
||||
uprv_free(entry);
|
||||
ures_close(mz);
|
||||
goto error_cleanup;
|
||||
}
|
||||
u_charsToUChars(territory, entry->territory, territoryLen + 1);
|
||||
|
||||
// Check if mapping entries for metazone is already available
|
||||
UnicodeString mzidStr(mzid, mzidLen);
|
||||
UVector *tzMappings = (UVector*)metaToOlson->get(mzidStr);
|
||||
if (tzMappings == NULL) {
|
||||
// Create new UVector and put it into the hashtable
|
||||
tzMappings = new UVector(deleteMetaToOlsonMappingEntry, NULL, status);
|
||||
metaToOlson->put(mzidStr, tzMappings, status);
|
||||
if (U_FAILURE(status)) {
|
||||
if (tzMappings != NULL) {
|
||||
delete tzMappings;
|
||||
}
|
||||
deleteMetaToOlsonMappingEntry(entry);
|
||||
ures_close(mz);
|
||||
goto error_cleanup;
|
||||
}
|
||||
}
|
||||
tzMappings->addElement(entry, status);
|
||||
if (U_FAILURE(status)) {
|
||||
goto error_cleanup;
|
||||
}
|
||||
} else {
|
||||
status = U_ZERO_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
ures_close(mz);
|
||||
}
|
||||
|
||||
ures_close(metazones);
|
||||
ures_close(mapTimezones);
|
||||
ures_close(supplementalDataBundle);
|
||||
return metaToOlson;
|
||||
|
||||
error_cleanup:
|
||||
ures_close(metazones);
|
||||
ures_close(mapTimezones);
|
||||
ures_close(supplementalDataBundle);
|
||||
if (metaToOlson != NULL) {
|
||||
delete metaToOlson;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
ZoneMeta::getCanonicalID(const UnicodeString &tzid, UnicodeString &canonicalID) {
|
||||
const CanonicalMapEntry *entry = getCanonicalInfo(tzid);
|
||||
if (entry != NULL) {
|
||||
canonicalID.setTo(entry->id);
|
||||
} else {
|
||||
// Use the input tzid
|
||||
canonicalID.setTo(tzid);
|
||||
}
|
||||
return canonicalID;
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
ZoneMeta::getCanonicalCountry(const UnicodeString &tzid, UnicodeString &canonicalCountry) {
|
||||
const CanonicalMapEntry *entry = getCanonicalInfo(tzid);
|
||||
if (entry != NULL && entry->country != NULL) {
|
||||
canonicalCountry.setTo(entry->country);
|
||||
} else {
|
||||
// Use the input tzid
|
||||
canonicalCountry.remove();
|
||||
}
|
||||
return canonicalCountry;
|
||||
}
|
||||
|
||||
const CanonicalMapEntry*
|
||||
ZoneMeta::getCanonicalInfo(const UnicodeString &tzid) {
|
||||
initialize();
|
||||
CanonicalMapEntry *entry = NULL;
|
||||
UnicodeString canonicalOlsonId;
|
||||
TimeZone::getOlsonCanonicalID(tzid, canonicalOlsonId);
|
||||
if (!canonicalOlsonId.isEmpty()) {
|
||||
if (gCanonicalMap != NULL) {
|
||||
entry = (CanonicalMapEntry*)gCanonicalMap->get(tzid);
|
||||
}
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
ZoneMeta::getSingleCountry(const UnicodeString &tzid, UnicodeString &country) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
// Get canonical country for the zone
|
||||
getCanonicalCountry(tzid, country);
|
||||
|
||||
if (!country.isEmpty()) {
|
||||
UResourceBundle *supplementalDataBundle = ures_openDirect(NULL, gSupplementalData, &status);
|
||||
UResourceBundle *zoneFormatting = ures_getByKey(supplementalDataBundle, gZoneFormattingTag, NULL, &status);
|
||||
UResourceBundle *multizone = ures_getByKey(zoneFormatting, gMultizoneTag, NULL, &status);
|
||||
|
||||
if (U_SUCCESS(status)) {
|
||||
while (ures_hasNext(multizone)) {
|
||||
int32_t len;
|
||||
const UChar* multizoneCountry = ures_getNextString(multizone, &len, NULL, &status);
|
||||
if (country.compare(multizoneCountry, len) == 0) {
|
||||
// Included in the multizone country list
|
||||
country.remove();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ures_close(multizone);
|
||||
ures_close(zoneFormatting);
|
||||
ures_close(supplementalDataBundle);
|
||||
}
|
||||
|
||||
return country;
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
ZoneMeta::getMetazoneID(const UnicodeString &tzid, UDate date, UnicodeString &result) {
|
||||
UBool isSet = FALSE;
|
||||
const UVector *mappings = getMetazoneMappings(tzid);
|
||||
if (mappings != NULL) {
|
||||
for (int32_t i = 0; i < mappings->size(); i++) {
|
||||
OlsonToMetaMappingEntry *mzm = (OlsonToMetaMappingEntry*)mappings->elementAt(i);
|
||||
if (mzm->from <= date && mzm->to > date) {
|
||||
result.setTo(mzm->mzid, -1);
|
||||
isSet = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isSet) {
|
||||
result.remove();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
const UVector*
|
||||
ZoneMeta::getMetazoneMappings(const UnicodeString &tzid) {
|
||||
initialize();
|
||||
const UVector *result;
|
||||
if (gOlsonToMeta != NULL) {
|
||||
result = (UVector*)gOlsonToMeta->get(tzid);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
UnicodeString&
|
||||
ZoneMeta::getZoneIdByMetazone(const UnicodeString &mzid, const UnicodeString ®ion, UnicodeString &result) {
|
||||
initialize();
|
||||
UBool isSet = FALSE;
|
||||
if (gMetaToOlson != NULL) {
|
||||
UVector *mappings = (UVector*)gMetaToOlson->get(mzid);
|
||||
if (mappings != NULL) {
|
||||
// Find a preferred time zone for the given region.
|
||||
for (int32_t i = 0; i < mappings->size(); i++) {
|
||||
MetaToOlsonMappingEntry *olsonmap = (MetaToOlsonMappingEntry*)mappings->elementAt(i);
|
||||
if (region.compare(olsonmap->territory, -1) == 0) {
|
||||
result.setTo(olsonmap->id);
|
||||
isSet = TRUE;
|
||||
break;
|
||||
} else if (u_strcmp(olsonmap->territory, gWorld) == 0) {
|
||||
result.setTo(olsonmap->id);
|
||||
isSet = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isSet) {
|
||||
result.remove();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
84
icu4c/source/i18n/zonemeta.h
Normal file
84
icu4c/source/i18n/zonemeta.h
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2007, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
#ifndef ZONEMETA_H
|
||||
#define ZONEMETA_H
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
#if !UCONFIG_NO_FORMATTING
|
||||
|
||||
#include "unicode/unistr.h"
|
||||
#include "hash.h"
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
typedef struct CanonicalMapEntry {
|
||||
UChar *id;
|
||||
UChar *country;
|
||||
} CanonicalMapEntry;
|
||||
|
||||
typedef struct OlsonToMetaMappingEntry {
|
||||
UChar *mzid;
|
||||
UDate from;
|
||||
UDate to;
|
||||
} OlsonToMetaMappingEntry;
|
||||
|
||||
typedef struct MetaToOlsonMappingEntry {
|
||||
UChar *id;
|
||||
UChar *territory;
|
||||
} MetaToOlsonMappingEntry;
|
||||
|
||||
class UVector;
|
||||
|
||||
class U_I18N_API ZoneMeta {
|
||||
public:
|
||||
/**
|
||||
* Return the canonical id for this tzid, which might be the id itself.
|
||||
* If there is no canonical id for it, return the passed-in id.
|
||||
*/
|
||||
static UnicodeString& getCanonicalID(const UnicodeString &tzid, UnicodeString &canonicalID);
|
||||
|
||||
/**
|
||||
* Return the canonical country code for this tzid. If we have none, or if the time zone
|
||||
* is not associated with a country, return null.
|
||||
*/
|
||||
static UnicodeString& getCanonicalCountry(const UnicodeString &tzid, UnicodeString &canonicalCountry);
|
||||
|
||||
/**
|
||||
* Return the country code if this is a 'single' time zone that can fallback to just
|
||||
* the country, otherwise return empty string. (Note, one must also check the locale data
|
||||
* to see that there is a localization for the country in order to implement
|
||||
* tr#35 appendix J step 5.)
|
||||
*/
|
||||
static UnicodeString& getSingleCountry(const UnicodeString &tzid, UnicodeString &country);
|
||||
|
||||
/**
|
||||
* Returns a CLDR metazone ID for the given Olson tzid and time.
|
||||
*/
|
||||
static UnicodeString& getMetazoneID(const UnicodeString &tzid, UDate date, UnicodeString &result);
|
||||
/**
|
||||
* Returns an Olson ID for the ginve metazone and region
|
||||
*/
|
||||
static UnicodeString& getZoneIdByMetazone(const UnicodeString &mzid, const UnicodeString ®ion, UnicodeString &result);
|
||||
|
||||
static const UVector* getMetazoneMappings(const UnicodeString &tzid);
|
||||
|
||||
private:
|
||||
static void initialize(void);
|
||||
|
||||
static const CanonicalMapEntry* getCanonicalInfo(const UnicodeString &tzid);
|
||||
|
||||
static Hashtable* createCanonicalMap(void);
|
||||
static Hashtable* createOlsonToMetaMapOld(void);
|
||||
static Hashtable* createOlsonToMetaMap(void);
|
||||
static Hashtable* createMetaToOlsonMap(void);
|
||||
};
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
#endif // ZONEMETA_H
|
1658
icu4c/source/i18n/zstrfmt.cpp
Normal file
1658
icu4c/source/i18n/zstrfmt.cpp
Normal file
File diff suppressed because it is too large
Load diff
439
icu4c/source/i18n/zstrfmt.h
Normal file
439
icu4c/source/i18n/zstrfmt.h
Normal file
|
@ -0,0 +1,439 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2007, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
#ifndef ZSTRFMT_H
|
||||
#define ZSTRFMT_H
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
#if !UCONFIG_NO_FORMATTING
|
||||
|
||||
#include "unicode/uobject.h"
|
||||
#include "unicode/unistr.h"
|
||||
#include "unicode/calendar.h"
|
||||
#include "hash.h"
|
||||
|
||||
U_NAMESPACE_BEGIN
|
||||
|
||||
class UVector;
|
||||
|
||||
/*
|
||||
* Character node used by TextTrieMap
|
||||
*/
|
||||
class CharacterNode : public UMemory {
|
||||
public:
|
||||
CharacterNode(UChar32 c, UObjectDeleter *fn);
|
||||
virtual ~CharacterNode();
|
||||
|
||||
inline UChar32 getCharacter(void) const;
|
||||
inline UVector* getValues(void) const;
|
||||
inline UVector* getChildNodes(void) const;
|
||||
|
||||
void addValue(void *value, UErrorCode &status);
|
||||
CharacterNode* addChildNode(UChar32 c, UErrorCode &status);
|
||||
CharacterNode* getChildNode(UChar32 c) const;
|
||||
|
||||
private:
|
||||
UChar32 fCharacter;
|
||||
UVector *fChildren;
|
||||
UVector *fValues;
|
||||
UObjectDeleter *fValueDeleter;
|
||||
};
|
||||
|
||||
inline UChar32 CharacterNode::getCharacter(void) const {
|
||||
return fCharacter;
|
||||
}
|
||||
|
||||
inline UVector* CharacterNode::getValues(void) const {
|
||||
return fValues;
|
||||
}
|
||||
|
||||
inline UVector* CharacterNode::getChildNodes(void) const {
|
||||
return fChildren;
|
||||
}
|
||||
|
||||
/*
|
||||
* Search result handler callback interface used by TextTrieMap search.
|
||||
*/
|
||||
class TextTrieMapSearchResultHandler {
|
||||
public:
|
||||
virtual UBool handleMatch(int32_t matchLength,
|
||||
const UVector *values, UErrorCode& status) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* TextTrieMap is a trie implementation for supporting
|
||||
* fast prefix match for the string key.
|
||||
*/
|
||||
class TextTrieMap : public UMemory {
|
||||
public:
|
||||
TextTrieMap(UBool ignoreCase, UObjectDeleter *valueDeleterFunc);
|
||||
virtual ~TextTrieMap();
|
||||
|
||||
void put(const UnicodeString &key, void *value, UErrorCode &status);
|
||||
void search(const UnicodeString &text, int32_t start,
|
||||
TextTrieMapSearchResultHandler *handler, UErrorCode& status) const;
|
||||
|
||||
private:
|
||||
UBool fIgnoreCase;
|
||||
UObjectDeleter *fValueDeleter;
|
||||
CharacterNode *fRoot;
|
||||
|
||||
void search(CharacterNode *node, const UnicodeString &text, int32_t start,
|
||||
int32_t index, TextTrieMapSearchResultHandler *handler, UErrorCode &status) const;
|
||||
};
|
||||
|
||||
// Name types, these bit flag are used for zone string lookup
|
||||
enum TimeZoneTranslationType {
|
||||
LOCATION = 0x0001,
|
||||
GENERIC_LONG = 0x0002,
|
||||
GENERIC_SHORT = 0x0004,
|
||||
STANDARD_LONG = 0x0008,
|
||||
STANDARD_SHORT = 0x0010,
|
||||
DAYLIGHT_LONG = 0x0020,
|
||||
DAYLIGHT_SHORT = 0x0040
|
||||
};
|
||||
|
||||
// Name type index, these constants are used for index in the zone strings array.
|
||||
enum TimeZoneTranslationTypeIndex {
|
||||
ZSIDX_LOCATION = 0,
|
||||
ZSIDX_LONG_STANDARD,
|
||||
ZSIDX_SHORT_STANDARD,
|
||||
ZSIDX_LONG_DAYLIGHT,
|
||||
ZSIDX_SHORT_DAYLIGHT,
|
||||
ZSIDX_LONG_GENERIC,
|
||||
ZSIDX_SHORT_GENERIC,
|
||||
|
||||
ZSIDX_COUNT
|
||||
};
|
||||
|
||||
class MessageFormat;
|
||||
|
||||
/*
|
||||
* ZoneStringInfo is a class holding a localized zone string
|
||||
* information.
|
||||
*/
|
||||
class ZoneStringInfo : public UMemory {
|
||||
public:
|
||||
virtual ~ZoneStringInfo();
|
||||
|
||||
inline UnicodeString& getID(UnicodeString &result) const;
|
||||
inline UnicodeString& getString(UnicodeString &result) const;
|
||||
inline UBool isStandard(void) const;
|
||||
inline UBool isDaylight(void) const;
|
||||
inline UBool isGeneric(void) const;
|
||||
|
||||
private:
|
||||
friend class ZoneStringFormat;
|
||||
friend class ZoneStringSearchResultHandler;
|
||||
|
||||
ZoneStringInfo(const UnicodeString &id, const UnicodeString &str, TimeZoneTranslationType type);
|
||||
|
||||
UnicodeString fId;
|
||||
UnicodeString fStr;
|
||||
TimeZoneTranslationType fType;
|
||||
};
|
||||
|
||||
inline UnicodeString& ZoneStringInfo::getID(UnicodeString &result) const {
|
||||
return result.setTo(fId);
|
||||
}
|
||||
|
||||
inline UnicodeString& ZoneStringInfo::getString(UnicodeString &result) const {
|
||||
return result.setTo(fStr);
|
||||
}
|
||||
|
||||
inline UBool ZoneStringInfo::isStandard(void) const {
|
||||
return (fType == STANDARD_LONG || fType == STANDARD_SHORT);
|
||||
}
|
||||
|
||||
inline UBool ZoneStringInfo::isDaylight(void) const {
|
||||
return (fType == DAYLIGHT_LONG || fType == DAYLIGHT_SHORT);
|
||||
}
|
||||
|
||||
inline UBool ZoneStringInfo::isGeneric(void) const {
|
||||
return (fType == LOCATION || fType == GENERIC_LONG || fType == GENERIC_SHORT);
|
||||
}
|
||||
|
||||
class SafeZoneStringFormatPtr;
|
||||
|
||||
class ZoneStringFormat : public UMemory {
|
||||
public:
|
||||
ZoneStringFormat(const UnicodeString* const* strings, int32_t rowCount, int32_t columnCount, UErrorCode &status);
|
||||
ZoneStringFormat(const Locale& locale, UErrorCode &status);
|
||||
virtual ~ZoneStringFormat();
|
||||
|
||||
static SafeZoneStringFormatPtr* getZoneStringFormat(const Locale& locale, UErrorCode &status);
|
||||
|
||||
/*
|
||||
* Create a snapshot of old zone strings array for the given date
|
||||
*/
|
||||
UnicodeString** createZoneStringsArray(UDate date, int32_t &rowCount, int32_t &colCount, UErrorCode &status) const;
|
||||
|
||||
const UnicodeString** getZoneStrings(int32_t &rowCount, int32_t &columnCount) const;
|
||||
|
||||
UnicodeString& getSpecificLongString(const Calendar &cal,
|
||||
UnicodeString &result, UErrorCode &status) const;
|
||||
|
||||
UnicodeString& getSpecificShortString(const Calendar &cal,
|
||||
UBool commonlyUsedOnly, UnicodeString &result, UErrorCode &status) const;
|
||||
|
||||
UnicodeString& getGenericLongString(const Calendar &cal,
|
||||
UnicodeString &result, UErrorCode &status) const;
|
||||
|
||||
UnicodeString& getGenericShortString(const Calendar &cal,
|
||||
UBool commonlyUsedOnly, UnicodeString &result, UErrorCode &status) const;
|
||||
|
||||
UnicodeString& getGenericLocationString(const Calendar &cal,
|
||||
UnicodeString &result, UErrorCode &status) const;
|
||||
|
||||
const ZoneStringInfo* findSpecificLong(const UnicodeString &text, int32_t start,
|
||||
int32_t &matchLength, UErrorCode &status) const;
|
||||
const ZoneStringInfo* findSpecificShort(const UnicodeString &text, int32_t start,
|
||||
int32_t &matchLength, UErrorCode &status) const;
|
||||
const ZoneStringInfo* findGenericLong(const UnicodeString &text, int32_t start,
|
||||
int32_t &matchLength, UErrorCode &status) const;
|
||||
const ZoneStringInfo* findGenericShort(const UnicodeString &text, int32_t start,
|
||||
int32_t &matchLength, UErrorCode &status) const;
|
||||
const ZoneStringInfo* findGenericLocation(const UnicodeString &text, int32_t start,
|
||||
int32_t &matchLength, UErrorCode &status) const;
|
||||
|
||||
// Following APIs are not used by SimpleDateFormat, but public for testing purpose
|
||||
inline UnicodeString& getLongStandard(const UnicodeString &tzid, UDate date,
|
||||
UnicodeString &result) const;
|
||||
inline UnicodeString& getLongDaylight(const UnicodeString &tzid, UDate date,
|
||||
UnicodeString &result) const;
|
||||
inline UnicodeString& getLongGenericNonLocation(const UnicodeString &tzid, UDate date,
|
||||
UnicodeString &result) const;
|
||||
inline UnicodeString& getLongGenericPartialLocation(const UnicodeString &tzid, UDate date,
|
||||
UnicodeString &result) const;
|
||||
inline UnicodeString& getShortStandard(const UnicodeString &tzid, UDate date, UBool commonlyUsedOnly,
|
||||
UnicodeString &result) const;
|
||||
inline UnicodeString& getShortDaylight(const UnicodeString &tzid, UDate date, UBool commonlyUsedOnly,
|
||||
UnicodeString &result) const;
|
||||
inline UnicodeString& getShortGenericNonLocation(const UnicodeString &tzid, UDate date, UBool commonlyUsedOnly,
|
||||
UnicodeString &result) const;
|
||||
inline UnicodeString& getShortGenericPartialLocation(const UnicodeString &tzid, UDate date, UBool commonlyUsedOnly,
|
||||
UnicodeString &result) const;
|
||||
inline UnicodeString& getGenericLocation(const UnicodeString &tzid, UnicodeString &result) const;
|
||||
|
||||
private:
|
||||
Locale fLocale;
|
||||
Hashtable *fTzidToStrings;
|
||||
Hashtable *fMzidToStrings;
|
||||
TextTrieMap *fZoneStringsTrie;
|
||||
|
||||
/*
|
||||
* Private method to get a zone string except generic partial location types.
|
||||
*/
|
||||
UnicodeString& getString(const UnicodeString &tzid, TimeZoneTranslationTypeIndex typeIdx, UDate date,
|
||||
UBool commonlyUsedOnly, UnicodeString& result) const;
|
||||
|
||||
/*
|
||||
* Private method to get a generic string, with fallback logic involved,
|
||||
* that is,
|
||||
*
|
||||
* 1. If a generic non-location string is avaiable for the zone, return it.
|
||||
* 2. If a generic non-location string is associated with a metazone and
|
||||
* the zone never use daylight time around the given date, use the standard
|
||||
* string (if available).
|
||||
*
|
||||
* Note: In CLDR1.5.1, the same localization is used for generic and standard.
|
||||
* In this case, we do not use the standard string and do the rest.
|
||||
*
|
||||
* 3. If a generic non-location string is associated with a metazone and
|
||||
* the offset at the given time is different from the preferred zone for the
|
||||
* current locale, then return the generic partial location string (if avaiable)
|
||||
* 4. If a generic non-location string is not available, use generic location
|
||||
* string.
|
||||
*/
|
||||
UnicodeString& getGenericString(const Calendar &cal, UBool isShort, UBool commonlyUsedOnly,
|
||||
UnicodeString &result, UErrorCode &status) const;
|
||||
|
||||
/*
|
||||
* Private method to get a generic partial location string
|
||||
*/
|
||||
UnicodeString& getGenericPartialLocationString(const UnicodeString &tzid, UBool isShort,
|
||||
UDate date, UBool commonlyUsedOnly, UnicodeString &result) const;
|
||||
|
||||
/*
|
||||
* Find a prefix matching time zone for the given zone string types.
|
||||
* @param text The text contains a time zone string
|
||||
* @param start The start index within the text
|
||||
* @param types The bit mask representing a set of requested types
|
||||
* @param matchLength Receives the match length
|
||||
* @param status
|
||||
* @return If any zone string matched for the requested types, returns a
|
||||
* ZoneStringInfo for the longest match. If no matches are found for
|
||||
* the requested types, returns a ZoneStringInfo for the longest match
|
||||
* for any other types. If nothing matches at all, returns null.
|
||||
*/
|
||||
const ZoneStringInfo* find(const UnicodeString &text, int32_t start, int32_t types,
|
||||
int32_t &matchLength, UErrorCode &status) const;
|
||||
|
||||
UnicodeString& getRegion(UnicodeString ®ion) const;
|
||||
|
||||
static MessageFormat* getFallbackFormat(const Locale &locale, UErrorCode &status);
|
||||
static MessageFormat* getRegionFormat(const Locale &locale, UErrorCode &status);
|
||||
static const UChar* getZoneStringFromBundle(const UResourceBundle *zoneitem, const char *key);
|
||||
static UBool isCommonlyUsed(const UResourceBundle *zoneitem);
|
||||
static UnicodeString& getLocalizedCountry(const UnicodeString &countryCode, const Locale &locale,
|
||||
UnicodeString &displayCountry);
|
||||
};
|
||||
|
||||
inline UnicodeString&
|
||||
ZoneStringFormat::getLongStandard(const UnicodeString &tzid, UDate date,
|
||||
UnicodeString &result) const {
|
||||
return getString(tzid, ZSIDX_LONG_STANDARD, date, FALSE /* not used */, result);
|
||||
}
|
||||
|
||||
inline UnicodeString&
|
||||
ZoneStringFormat::getLongDaylight(const UnicodeString &tzid, UDate date,
|
||||
UnicodeString &result) const {
|
||||
return getString(tzid, ZSIDX_LONG_DAYLIGHT, date, FALSE /* not used */, result);
|
||||
}
|
||||
|
||||
inline UnicodeString&
|
||||
ZoneStringFormat::getLongGenericNonLocation(const UnicodeString &tzid, UDate date,
|
||||
UnicodeString &result) const {
|
||||
return getString(tzid, ZSIDX_LONG_GENERIC, date, FALSE /* not used */, result);
|
||||
}
|
||||
|
||||
inline UnicodeString&
|
||||
ZoneStringFormat::getLongGenericPartialLocation(const UnicodeString &tzid, UDate date,
|
||||
UnicodeString &result) const {
|
||||
return getGenericPartialLocationString(tzid, FALSE, date, FALSE /* not used */, result);
|
||||
}
|
||||
|
||||
inline UnicodeString&
|
||||
ZoneStringFormat::getShortStandard(const UnicodeString &tzid, UDate date, UBool commonlyUsedOnly,
|
||||
UnicodeString &result) const {
|
||||
return getString(tzid, ZSIDX_SHORT_STANDARD, date, commonlyUsedOnly, result);
|
||||
}
|
||||
|
||||
inline UnicodeString&
|
||||
ZoneStringFormat::getShortDaylight(const UnicodeString &tzid, UDate date, UBool commonlyUsedOnly,
|
||||
UnicodeString &result) const {
|
||||
return getString(tzid, ZSIDX_SHORT_DAYLIGHT, date, commonlyUsedOnly, result);
|
||||
}
|
||||
|
||||
inline UnicodeString&
|
||||
ZoneStringFormat::getShortGenericNonLocation(const UnicodeString &tzid, UDate date, UBool commonlyUsedOnly,
|
||||
UnicodeString &result) const {
|
||||
return getString(tzid, ZSIDX_SHORT_GENERIC, date, commonlyUsedOnly, result);
|
||||
}
|
||||
|
||||
inline UnicodeString&
|
||||
ZoneStringFormat::getShortGenericPartialLocation(const UnicodeString &tzid, UDate date, UBool commonlyUsedOnly,
|
||||
UnicodeString &result) const {
|
||||
return getGenericPartialLocationString(tzid, TRUE, date, commonlyUsedOnly, result);
|
||||
}
|
||||
|
||||
inline UnicodeString&
|
||||
ZoneStringFormat::getGenericLocation(const UnicodeString &tzid, UnicodeString &result) const {
|
||||
return getString(tzid, ZSIDX_LOCATION, 0 /*not used*/, FALSE /*not used*/, result);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* ZooneStrings is a container of localized zone strings used by ZoneStringFormat
|
||||
*/
|
||||
class ZoneStrings : public UMemory {
|
||||
public:
|
||||
ZoneStrings(UnicodeString *strings, int32_t stringsCount, UBool commonlyUsed,
|
||||
UnicodeString **genericPartialLocationStrings, int32_t genericRowCount, int32_t genericColCount);
|
||||
virtual ~ZoneStrings();
|
||||
|
||||
UnicodeString& getString(int32_t typeIdx, UnicodeString &result) const;
|
||||
inline UBool isShortFormatCommonlyUsed(void) const;
|
||||
UnicodeString& getGenericPartialLocationString(const UnicodeString &mzid, UBool isShort,
|
||||
UBool commonlyUsedOnly, UnicodeString &result) const;
|
||||
|
||||
private:
|
||||
UnicodeString *fStrings;
|
||||
int32_t fStringsCount;
|
||||
UBool fIsCommonlyUsed;
|
||||
UnicodeString **fGenericPartialLocationStrings;
|
||||
int32_t fGenericPartialLocationRowCount;
|
||||
int32_t fGenericPartialLocationColCount;
|
||||
};
|
||||
|
||||
inline UBool
|
||||
ZoneStrings::isShortFormatCommonlyUsed(void) const {
|
||||
return fIsCommonlyUsed;
|
||||
}
|
||||
|
||||
/*
|
||||
* ZoneStringSearchResultHandler is an implementation of
|
||||
* TextTrieMapSearchHandler. This class is used by ZoneStringFormat
|
||||
* for collecting search results for localized zone strings.
|
||||
*/
|
||||
class ZoneStringSearchResultHandler : public UMemory, TextTrieMapSearchResultHandler {
|
||||
public:
|
||||
ZoneStringSearchResultHandler();
|
||||
virtual ~ZoneStringSearchResultHandler();
|
||||
|
||||
virtual UBool handleMatch(int32_t matchLength, const UVector *values, UErrorCode &status);
|
||||
int32_t countMatches(void);
|
||||
const ZoneStringInfo* getMatch(int32_t index, int32_t &matchLength);
|
||||
void clear(void);
|
||||
|
||||
private:
|
||||
UVector *fResults;
|
||||
int32_t fMatchLen[ZSIDX_COUNT];
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* ZoneStringFormat cache implementation
|
||||
*/
|
||||
class ZSFCacheEntry : public UMemory {
|
||||
public:
|
||||
~ZSFCacheEntry();
|
||||
|
||||
void delRef(void);
|
||||
const ZoneStringFormat* getZoneStringFormat(void);
|
||||
|
||||
private:
|
||||
friend class ZSFCache;
|
||||
|
||||
ZSFCacheEntry(const Locale &locale, ZoneStringFormat *zsf, ZSFCacheEntry *next);
|
||||
|
||||
Locale fLocale;
|
||||
ZoneStringFormat *fZoneStringFormat;
|
||||
ZSFCacheEntry *fNext;
|
||||
int32_t fRefCount;
|
||||
};
|
||||
|
||||
class SafeZoneStringFormatPtr : public UMemory {
|
||||
public:
|
||||
~SafeZoneStringFormatPtr();
|
||||
const ZoneStringFormat* get() const;
|
||||
|
||||
private:
|
||||
friend class ZSFCache;
|
||||
|
||||
SafeZoneStringFormatPtr(ZSFCacheEntry *cacheEntry);
|
||||
|
||||
ZSFCacheEntry *fCacheEntry;
|
||||
};
|
||||
|
||||
class ZSFCache : public UMemory {
|
||||
public:
|
||||
ZSFCache(int32_t capacity);
|
||||
~ZSFCache();
|
||||
|
||||
SafeZoneStringFormatPtr* get(const Locale &locale, UErrorCode &status);
|
||||
|
||||
private:
|
||||
int32_t fCapacity;
|
||||
ZSFCacheEntry *fFirst;
|
||||
};
|
||||
|
||||
U_NAMESPACE_END
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
||||
#endif // ZSTRFMT_H
|
|
@ -56,7 +56,7 @@ jamotest.o srchtest.o reptest.o regextst.o \
|
|||
itrbnf.o itrbnfrt.o itrbnfp.o ucaconf.o icusvtst.o \
|
||||
uobjtest.o idnaref.o idnaconf.o nptrans.o punyref.o testidn.o testidna.o incaltst.o \
|
||||
calcasts.o v32test.o uvectest.o textfile.o tokiter.o utxttest.o \
|
||||
windttst.o winnmtst.o winutil.o csdetest.o tzrulets.o
|
||||
windttst.o winnmtst.o winutil.o csdetest.o tzrulets.o tzoffloc.o tzfmttst.o
|
||||
|
||||
|
||||
DEPS = $(OBJECTS:.o=.d)
|
||||
|
|
|
@ -69,21 +69,20 @@ void DateFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &nam
|
|||
TESTCASE(23,TestGreekMay);
|
||||
TESTCASE(24,TestGenericTime);
|
||||
TESTCASE(25,TestGenericTimeZoneOrder);
|
||||
TESTCASE(26,TestTimeZoneStringsAPI);
|
||||
TESTCASE(27,TestHost);
|
||||
TESTCASE(28,TestEras);
|
||||
TESTCASE(29,TestNarrowNames);
|
||||
TESTCASE(30,TestStandAloneDays);
|
||||
TESTCASE(31,TestStandAloneMonths);
|
||||
TESTCASE(32,TestQuarters);
|
||||
TESTCASE(33,TestZTimeZoneParsing);
|
||||
TESTCASE(34,TestRelative);
|
||||
TESTCASE(35,TestRelativeClone);
|
||||
TESTCASE(36,TestHostClone);
|
||||
TESTCASE(37,TestTimeZoneDisplayName);
|
||||
TESTCASE(26,TestHost);
|
||||
TESTCASE(27,TestEras);
|
||||
TESTCASE(28,TestNarrowNames);
|
||||
TESTCASE(29,TestStandAloneDays);
|
||||
TESTCASE(30,TestStandAloneMonths);
|
||||
TESTCASE(31,TestQuarters);
|
||||
TESTCASE(32,TestZTimeZoneParsing);
|
||||
TESTCASE(33,TestRelative);
|
||||
TESTCASE(34,TestRelativeClone);
|
||||
TESTCASE(35,TestHostClone);
|
||||
TESTCASE(36,TestTimeZoneDisplayName);
|
||||
/*
|
||||
TESTCASE(38,TestRelativeError);
|
||||
TESTCASE(39,TestRelativeOther);
|
||||
TESTCASE(37,TestRelativeError);
|
||||
TESTCASE(38,TestRelativeOther);
|
||||
*/
|
||||
default: name = ""; break;
|
||||
}
|
||||
|
@ -100,7 +99,7 @@ void DateFormatTest::TestWallyWedel()
|
|||
/*
|
||||
* Computational variables.
|
||||
*/
|
||||
int32_t offset, hours, minutes;
|
||||
int32_t offset, hours, minutes, seconds;
|
||||
/*
|
||||
* Instantiate a SimpleDateFormat set up to produce a full time
|
||||
zone name.
|
||||
|
@ -141,8 +140,12 @@ void DateFormatTest::TestWallyWedel()
|
|||
}
|
||||
hours = offset/3600000;
|
||||
minutes = (offset%3600000)/60000;
|
||||
seconds = (offset%60000)/1000;
|
||||
UnicodeString dstOffset = (UnicodeString)"" + sign + (hours < 10 ? "0" : "") +
|
||||
(int32_t)hours + ":" + (minutes < 10 ? "0" : "") + (int32_t)minutes;
|
||||
if (seconds != 0) {
|
||||
dstOffset = dstOffset + ":" + (seconds < 10 ? "0" : "") + seconds;
|
||||
}
|
||||
/*
|
||||
* Instantiate a date so we can display the time zone name.
|
||||
*/
|
||||
|
@ -382,7 +385,7 @@ void DateFormatTest::TestFieldPosition() {
|
|||
"Wed", "225", "2", "33", "3", "PM", "2", "2", "PDT", "1997", "4", "1997", "2450674", "52452513", "-0700", "PT", "4", "8", "3", "3","PDT",
|
||||
|
||||
"Anno Domini", "1997", "August", "0013", "0014", "0014", "0034", "0012", "5130",
|
||||
"Wednesday", "0225", "0002", "0033", "0003", "PM", "0002", "0002", "Pacific Daylight Time", "1997", "0004", "1997", "2450674", "52452513", "-0700",
|
||||
"Wednesday", "0225", "0002", "0033", "0003", "PM", "0002", "0002", "Pacific Daylight Time", "1997", "0004", "1997", "2450674", "52452513", "GMT-07:00",
|
||||
"Pacific Time", "Wednesday", "August", "3rd quarter", "3rd quarter", "United States (Los Angeles)"
|
||||
};
|
||||
|
||||
|
@ -1752,7 +1755,7 @@ void DateFormatTest::TestGenericTime() {
|
|||
"y/M/d H:mm zzzz", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Standard Time",
|
||||
"y/M/d H:mm zzz", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 PST",
|
||||
"y/M/d H:mm vvvv", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 Pacific Time",
|
||||
"y/M/d H:mm vvv", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 PT",
|
||||
"y/M/d H:mm v", "F", "2004 01 01 01:00 PST", "2004/1/1 1:00 PT",
|
||||
// non-generic timezone string influences dst offset even if wrong for date/time
|
||||
"y/M/d H:mm zzz", "pf", "2004/1/1 1:00 PDT", "2004 01 01 01:00 PDT", "2004/1/1 0:00 PST",
|
||||
"y/M/d H:mm vvvv", "pf", "2004/1/1 1:00 PDT", "2004 01 01 01:00 PDT", "2004/1/1 0:00 Pacific Time",
|
||||
|
@ -1765,21 +1768,25 @@ void DateFormatTest::TestGenericTime() {
|
|||
"y/M/d H:mm vvvv", "pf", "2004/7/1 1:00 PT", "2004 07 01 01:00 PDT", "2004/7/1 1:00 Pacific Time",
|
||||
// daylight savings time transition edge cases.
|
||||
// time to parse does not really exist, PT interpreted as earlier time
|
||||
"y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PT", "2005 04 03 01:30 PST", "2005/4/3 1:30 PST", // adjust earlier
|
||||
"y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PT", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PDT",
|
||||
"y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PST", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PDT",
|
||||
"y/M/d H:mm zzz", "pf", "2005/4/3 2:30 PDT", "2005 04 03 01:30 PST", "2005/4/3 1:30 PST",
|
||||
"y/M/d H:mm vvv", "pf", "2005/4/3 2:30 PT", "2005 04 03 01:30 PST", "2005/4/3 1:30 PT", // adjust earlier
|
||||
"y/M/d H:mm vvv", "pf", "2005/4/3 2:30 PST", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PT",
|
||||
"y/M/d H:mm vvv", "pf", "2005/4/3 2:30 PDT", "2005 04 03 01:30 PST", "2005/4/3 1:30 PT",
|
||||
"y/M/d H:mm", "pf", "2005/4/3 2:30", "2005 04 03 01:30 PST", "2005/4/3 1:30",
|
||||
// time to parse is ambiguous, PT interpreted as LATER time (?)
|
||||
"y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PT", "2004 10 31 01:30 PST", "2004/10/31 1:30 PST", // 1:30a PT -> 1:30a PST (later)
|
||||
"y/M/d H:mm v", "pf", "2005/4/3 2:30 PT", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PT",
|
||||
"y/M/d H:mm v", "pf", "2005/4/3 2:30 PST", "2005 04 03 03:30 PDT", "2005/4/3 3:30 PT",
|
||||
"y/M/d H:mm v", "pf", "2005/4/3 2:30 PDT", "2005 04 03 01:30 PST", "2005/4/3 1:30 PT",
|
||||
"y/M/d H:mm", "pf", "2005/4/3 2:30", "2005 04 03 03:30 PDT", "2005/4/3 3:30",
|
||||
// time to parse is ambiguous, PT interpreted as later time
|
||||
"y/M/d H:mm zzz", "pf", "2005/10/30 1:30 PT", "2005 10 30 01:30 PST", "2005/10/30 1:30 PST",
|
||||
"y/M/d H:mm v", "pf", "2005/10/30 1:30 PT", "2005 10 30 01:30 PST", "2005/10/30 1:30 PT",
|
||||
"y/M/d H:mm", "pf", "2005/10/30 1:30 PT", "2005 10 30 01:30 PST", "2005/10/30 1:30",
|
||||
|
||||
"y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PT", "2004 10 31 01:30 PST", "2004/10/31 1:30 PST",
|
||||
"y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PST", "2004 10 31 01:30 PST", "2004/10/31 1:30 PST",
|
||||
"y/M/d H:mm zzz", "pf", "2004/10/31 1:30 PDT", "2004 10 31 01:30 PDT", "2004/10/31 1:30 PDT",
|
||||
"y/M/d H:mm vvv", "pf", "2004/10/31 1:30 PT", "2004 10 31 01:30 PST", "2004/10/31 1:30 PT", // 1:30a PT -> 1:30a PST (later)
|
||||
"y/M/d H:mm vvv", "pf", "2004/10/31 1:30 PST", "2004 10 31 01:30 PST", "2004/10/31 1:30 PT",
|
||||
"y/M/d H:mm vvv", "pf", "2004/10/31 1:30 PDT", "2004 10 31 01:30 PDT", "2004/10/31 1:30 PT",
|
||||
"y/M/d H:mm", "pf", "2004/10/31 1:30", "2004 10 31 01:30 PST", "2004/10/31 1:30", // 1:30a PT -> 1:30a PST (later)
|
||||
"y/M/d H:mm v", "pf", "2004/10/31 1:30 PT", "2004 10 31 01:30 PST", "2004/10/31 1:30 PT",
|
||||
"y/M/d H:mm v", "pf", "2004/10/31 1:30 PST", "2004 10 31 01:30 PST", "2004/10/31 1:30 PT",
|
||||
"y/M/d H:mm v", "pf", "2004/10/31 1:30 PDT", "2004 10 31 01:30 PDT", "2004/10/31 1:30 PT",
|
||||
"y/M/d H:mm", "pf", "2004/10/31 1:30", "2004 10 31 01:30 PST", "2004/10/31 1:30",
|
||||
};
|
||||
const int32_t ZDATA_length = sizeof(ZDATA)/ sizeof(ZDATA[0]);
|
||||
expect(ZDATA, ZDATA_length, en);
|
||||
|
@ -1864,66 +1871,6 @@ void DateFormatTest::TestGenericTimeZoneOrder() {
|
|||
expect(XDATA, XDATA_length, en);
|
||||
}
|
||||
|
||||
void DateFormatTest::TestTimeZoneStringsAPI() {
|
||||
// Verify data
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
DateFormatSymbols symbols(Locale::getUS(), status);
|
||||
StringEnumeration* keys = symbols.createZoneStringIDs(status);
|
||||
if(U_FAILURE(status)){
|
||||
errln("Could not create the StringEnumeration for Locale::getUS(). Error: %s", u_errorName(status));
|
||||
return;
|
||||
}
|
||||
|
||||
StringEnumeration* keys2 = symbols.createZoneStringIDs(status);
|
||||
ASSERT_OK(status);
|
||||
if(*keys2!=*keys){
|
||||
errln("operator!= failed for TimeZoneStringsEnum");
|
||||
}
|
||||
const UnicodeString* key = NULL;
|
||||
|
||||
while( (key = keys->snext(status))!=NULL){
|
||||
logln(prettify(*key));
|
||||
}
|
||||
if(U_FAILURE(status)){
|
||||
errln("Could not iterate over the StringEnumeration. Error: %s", u_errorName(status));
|
||||
return;
|
||||
}
|
||||
UnicodeString expectedKey("meta/Alaska");
|
||||
UnicodeString expectedStrs[DateFormatSymbols::TIMEZONE_COUNT];
|
||||
expectedStrs[DateFormatSymbols::TIMEZONE_SHORT_GENERIC].setTo("AKT");
|
||||
expectedStrs[DateFormatSymbols::TIMEZONE_SHORT_STANDARD].setTo("AKST");
|
||||
expectedStrs[DateFormatSymbols::TIMEZONE_SHORT_DAYLIGHT].setTo("AKDT");
|
||||
expectedStrs[DateFormatSymbols::TIMEZONE_LONG_GENERIC].setTo("Alaska Time");
|
||||
expectedStrs[DateFormatSymbols::TIMEZONE_LONG_STANDARD].setTo("Alaska Standard Time");
|
||||
expectedStrs[DateFormatSymbols::TIMEZONE_LONG_DAYLIGHT].setTo("Alaska Daylight Time");
|
||||
expectedStrs[DateFormatSymbols::TIMEZONE_EXEMPLAR_CITY].setTo("");
|
||||
for(int32_t i=0; i<DateFormatSymbols::TIMEZONE_COUNT; i++){
|
||||
UnicodeString result;
|
||||
result = symbols.getZoneString(expectedKey, (DateFormatSymbols::TimeZoneTranslationType)i, result,status);
|
||||
if(U_FAILURE(status)){
|
||||
errln("Could not retrieve display name. Error: %s", u_errorName(status));
|
||||
return;
|
||||
}
|
||||
if(expectedStrs[i] != result){
|
||||
errln("Did not get the expected string. Expected: "+expectedStrs[i]+ UnicodeString(" Got: ") + result );
|
||||
}
|
||||
}
|
||||
expectedKey.setTo("America/Los_Angeles",0);
|
||||
UnicodeString exemplarCity("Phoenix");
|
||||
UnicodeString result;
|
||||
symbols.setZoneString(expectedKey,DateFormatSymbols::TIMEZONE_EXEMPLAR_CITY, exemplarCity, status);
|
||||
if(U_FAILURE(status)){
|
||||
errln("setZoneString() did not succeed. Error: %s", u_errorName(status));
|
||||
return;
|
||||
}
|
||||
result = symbols.getZoneString(expectedKey, DateFormatSymbols::TIMEZONE_EXEMPLAR_CITY, result,status);
|
||||
if(result != exemplarCity){
|
||||
errln("setZoneString() did not succeed. Expected: " + exemplarCity + " Got: " + result);
|
||||
}
|
||||
delete keys;
|
||||
delete keys2;
|
||||
}
|
||||
|
||||
void DateFormatTest::TestZTimeZoneParsing(void) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
const Locale en("en");
|
||||
|
|
|
@ -789,6 +789,22 @@
|
|||
RelativePath=".\tzbdtest.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\tzfmttst.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\tzfmttst.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\tzoffloc.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\tzoffloc.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\tzregts.cpp"
|
||||
>
|
||||
|
|
|
@ -46,6 +46,8 @@
|
|||
#include "dadrcal.h" // DataDrivenCalendarTest
|
||||
#include "dadrfmt.h" // DataDrivenFormatTest
|
||||
#include "dtptngts.h" // IntlTestDateTimePatternGeneratorAPI
|
||||
#include "tzoffloc.h" // TimeZoneOffsetLocalTest
|
||||
#include "tzfmttst.h" // TimeZoneFormatTest
|
||||
|
||||
|
||||
#define TESTCLASS(id, TestClass) \
|
||||
|
@ -110,6 +112,8 @@ void IntlTestFormat::runIndexedTest( int32_t index, UBool exec, const char* &nam
|
|||
TESTCLASS(30,DataDrivenCalendarTest);
|
||||
TESTCLASS(31,DataDrivenFormatTest);
|
||||
TESTCLASS(32,IntlTestDateTimePatternGeneratorAPI);
|
||||
TESTCLASS(33,TimeZoneOffsetLocalTest);
|
||||
TESTCLASS(34,TimeZoneFormatTest);
|
||||
|
||||
|
||||
default: name = ""; break; //needed to end loop
|
||||
|
|
|
@ -857,8 +857,8 @@ LocaleTest::TestGetLangsAndCountries()
|
|||
;
|
||||
|
||||
/* TODO: Change this test to be more like the cloctst version? */
|
||||
if (testCount != 488)
|
||||
errln("Expected getISOLanguages() to return 488 languages; it returned %d", testCount);
|
||||
if (testCount != 489)
|
||||
errln("Expected getISOLanguages() to return 489 languages; it returned %d", testCount);
|
||||
else {
|
||||
for (i = 0; i < 15; i++) {
|
||||
int32_t j;
|
||||
|
|
|
@ -313,7 +313,7 @@ DateFormatMiscTests::test4117335()
|
|||
|
||||
UnicodeString jstShort = "JST";
|
||||
|
||||
UnicodeString tzID = "meta/Japan";
|
||||
UnicodeString tzID = "Asia/Tokyo";
|
||||
|
||||
UnicodeString jdtLong(jdtLongC, 5, 5);
|
||||
|
||||
|
|
457
icu4c/source/test/intltest/tzfmttst.cpp
Normal file
457
icu4c/source/test/intltest/tzfmttst.cpp
Normal file
|
@ -0,0 +1,457 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2007, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
#if !UCONFIG_NO_FORMATTING
|
||||
|
||||
#include "tzfmttst.h"
|
||||
|
||||
#include "unicode/timezone.h"
|
||||
#include "unicode/simpletz.h"
|
||||
#include "unicode/calendar.h"
|
||||
#include "unicode/strenum.h"
|
||||
#include "unicode/smpdtfmt.h"
|
||||
#include "unicode/uchar.h"
|
||||
#include "unicode/basictz.h"
|
||||
#include "cstring.h"
|
||||
#include "zonemeta.h"
|
||||
|
||||
#define DEBUG_ALL 0
|
||||
|
||||
static const char* PATTERNS[] = {"z", "zzzz", "Z", "ZZZZ", "v", "vvvv", "V", "VVVV"};
|
||||
static const int NUM_PATTERNS = sizeof(PATTERNS)/sizeof(const char*);
|
||||
|
||||
void
|
||||
TimeZoneFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
|
||||
{
|
||||
if (exec) {
|
||||
logln("TestSuite TimeZoneFormatTest");
|
||||
}
|
||||
switch (index) {
|
||||
TESTCASE(0, TestTimeZoneRoundTrip);
|
||||
TESTCASE(1, TestTimeRoundTrip);
|
||||
default: name = ""; break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TimeZoneFormatTest::TestTimeZoneRoundTrip(void) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
SimpleTimeZone unknownZone(-31415, (UnicodeString)"Etc/Unknown");
|
||||
int32_t badDstOffset = -1234;
|
||||
int32_t badZoneOffset = -2345;
|
||||
|
||||
int32_t testDateData[][3] = {
|
||||
{2007, 1, 15},
|
||||
{2007, 6, 15},
|
||||
{1990, 1, 15},
|
||||
{1990, 6, 15},
|
||||
{1960, 1, 15},
|
||||
{1960, 6, 15},
|
||||
};
|
||||
|
||||
Calendar *cal = Calendar::createInstance(TimeZone::createTimeZone((UnicodeString)"UTC"), status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln("Calendar::createInstance failed");
|
||||
return;
|
||||
}
|
||||
|
||||
// Set up rule equivalency test range
|
||||
UDate low, high;
|
||||
cal->set(1900, UCAL_JANUARY, 1);
|
||||
low = cal->getTime(status);
|
||||
cal->set(2040, UCAL_JANUARY, 1);
|
||||
high = cal->getTime(status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln("getTime failed");
|
||||
return;
|
||||
}
|
||||
|
||||
// Set up test dates
|
||||
UDate DATES[(sizeof(testDateData)/sizeof(int32_t))/3];
|
||||
const int32_t nDates = (sizeof(testDateData)/sizeof(int32_t))/3;
|
||||
cal->clear();
|
||||
for (int32_t i = 0; i < nDates; i++) {
|
||||
cal->set(testDateData[i][0], testDateData[i][1], testDateData[i][2]);
|
||||
DATES[i] = cal->getTime(status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln("getTime failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Set up test locales
|
||||
const Locale locales1[] = {
|
||||
Locale("en_US")
|
||||
};
|
||||
const Locale locales2[] = {
|
||||
Locale("en_US"),
|
||||
Locale("en"),
|
||||
Locale("en_CA"),
|
||||
Locale("fr"),
|
||||
Locale("zh_Hant")
|
||||
};
|
||||
|
||||
const Locale *LOCALES;
|
||||
int32_t nLocales;
|
||||
if (DEBUG_ALL) {
|
||||
LOCALES = Locale::getAvailableLocales(nLocales);
|
||||
} else if (quick) {
|
||||
LOCALES = locales1;
|
||||
nLocales = sizeof(locales1)/sizeof(Locale);
|
||||
} else {
|
||||
LOCALES = locales2;
|
||||
nLocales = sizeof(locales2)/sizeof(Locale);
|
||||
}
|
||||
|
||||
StringEnumeration *tzids = TimeZone::createEnumeration();
|
||||
if (U_FAILURE(status)) {
|
||||
errln("tzids->count failed");
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t inRaw, inDst;
|
||||
int32_t outRaw, outDst;
|
||||
|
||||
// Run the roundtrip test
|
||||
for (int32_t locidx = 0; locidx < nLocales; locidx++) {
|
||||
for (int32_t patidx = 0; patidx < NUM_PATTERNS; patidx++) {
|
||||
|
||||
//DEBUG static const char* PATTERNS[] = {"z", "zzzz", "Z", "ZZZZ", "v", "vvvv", "V", "VVVV"};
|
||||
//if (patidx != 1) continue;
|
||||
|
||||
SimpleDateFormat *sdf = new SimpleDateFormat((UnicodeString)PATTERNS[patidx], LOCALES[locidx], status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln((UnicodeString)"new SimpleDateFormat failed for pattern " +
|
||||
PATTERNS[patidx] + " for locale " + LOCALES[locidx].getName());
|
||||
status = U_ZERO_ERROR;
|
||||
continue;
|
||||
}
|
||||
|
||||
tzids->reset(status);
|
||||
const UnicodeString *tzid;
|
||||
while ((tzid = tzids->snext(status))) {
|
||||
TimeZone *tz = TimeZone::createTimeZone(*tzid);
|
||||
|
||||
for (int32_t datidx = 0; datidx < nDates; datidx++) {
|
||||
UnicodeString tzstr;
|
||||
FieldPosition fpos(0);
|
||||
// Format
|
||||
sdf->setTimeZone(*tz);
|
||||
sdf->format(DATES[datidx], tzstr, fpos);
|
||||
|
||||
// Before parse, set unknown zone to SimpleDateFormat instance
|
||||
// just for making sure that it does not depends on the time zone
|
||||
// originally set.
|
||||
sdf->setTimeZone(unknownZone);
|
||||
|
||||
// Parse
|
||||
ParsePosition pos(0);
|
||||
Calendar *outcal = Calendar::createInstance(unknownZone, status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln("Failed to create an instance of calendar for receiving parse result.");
|
||||
status = U_ZERO_ERROR;
|
||||
continue;
|
||||
}
|
||||
outcal->set(UCAL_DST_OFFSET, badDstOffset);
|
||||
outcal->set(UCAL_ZONE_OFFSET, badZoneOffset);
|
||||
|
||||
sdf->parse(tzstr, *outcal, pos);
|
||||
|
||||
// Check the result
|
||||
const TimeZone &outtz = outcal->getTimeZone();
|
||||
UnicodeString outtzid;
|
||||
outtz.getID(outtzid);
|
||||
|
||||
tz->getOffset(DATES[datidx], false, inRaw, inDst, status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln((UnicodeString)"Failed to get offsets from time zone" + *tzid);
|
||||
status = U_ZERO_ERROR;
|
||||
}
|
||||
outtz.getOffset(DATES[datidx], false, outRaw, outDst, status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln((UnicodeString)"Failed to get offsets from time zone" + outtzid);
|
||||
status = U_ZERO_ERROR;
|
||||
}
|
||||
|
||||
// Check if localized GMT format or RFC format is used.
|
||||
int32_t numDigits = 0;
|
||||
for (int n = 0; n < tzstr.length(); n++) {
|
||||
if (u_isdigit(tzstr.charAt(n))) {
|
||||
numDigits++;
|
||||
}
|
||||
}
|
||||
if (numDigits >= 4) {
|
||||
// Localized GMT or RFC: total offset (raw + dst) must be preserved.
|
||||
int32_t inOffset = inRaw + inDst;
|
||||
int32_t outOffset = outRaw + outDst;
|
||||
if (inOffset != outOffset) {
|
||||
errln((UnicodeString)"Offset round trip failed; tz=" + *tzid
|
||||
+ ", locale=" + LOCALES[locidx].getName() + ", pattern=" + PATTERNS[patidx]
|
||||
+ ", time=" + DATES[datidx] + ", str=" + tzstr
|
||||
+ ", inOffset=" + inOffset + ", outOffset=" + outOffset);
|
||||
}
|
||||
} else if (uprv_strcmp(PATTERNS[patidx], "z") == 0 || uprv_strcmp(PATTERNS[patidx], "zzzz") == 0
|
||||
|| uprv_strcmp(PATTERNS[patidx], "v") == 0 || uprv_strcmp(PATTERNS[patidx], "vvvv") == 0
|
||||
|| uprv_strcmp(PATTERNS[patidx], "V") == 0) {
|
||||
// Specific or generic: raw offset must be preserved.
|
||||
if (inRaw != outRaw) {
|
||||
errln((UnicodeString)"Raw offset round trip failed; tz=" + *tzid
|
||||
+ ", locale=" + LOCALES[locidx].getName() + ", pattern=" + PATTERNS[patidx]
|
||||
+ ", time=" + DATES[datidx] + ", str=" + tzstr
|
||||
+ ", inRawOffset=" + inRaw + ", outRawOffset=" + outRaw);
|
||||
}
|
||||
} else { // "VVVV"
|
||||
// Location: time zone rule must be preserved.
|
||||
UnicodeString canonical;
|
||||
ZoneMeta::getCanonicalID(*tzid, canonical);
|
||||
if (outtzid != canonical) {
|
||||
// Canonical ID did not match - check the rules
|
||||
if (!((BasicTimeZone*)&outtz)->hasEquivalentTransitions((BasicTimeZone&)*tz, low, high, TRUE, status)) {
|
||||
errln("Canonical round trip failed; tz=" + *tzid
|
||||
+ ", locale=" + LOCALES[locidx].getName() + ", pattern=" + PATTERNS[patidx]
|
||||
+ ", time=" + DATES[datidx] + ", str=" + tzstr
|
||||
+ ", outtz=" + outtzid);
|
||||
}
|
||||
if (U_FAILURE(status)) {
|
||||
errln("hasEquivalentTransitions failed");
|
||||
status = U_ZERO_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
delete tz;
|
||||
}
|
||||
delete sdf;
|
||||
}
|
||||
}
|
||||
delete cal;
|
||||
delete tzids;
|
||||
}
|
||||
|
||||
void
|
||||
TimeZoneFormatTest::TestTimeRoundTrip(void) {
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
Calendar *cal = Calendar::createInstance(TimeZone::createTimeZone((UnicodeString)"UTC"), status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln("Calendar::createInstance failed");
|
||||
return;
|
||||
}
|
||||
|
||||
UDate START_TIME, END_TIME;
|
||||
|
||||
if (DEBUG_ALL) {
|
||||
cal->set(1900, UCAL_JANUARY, 1);
|
||||
} else {
|
||||
cal->set(1965, UCAL_JANUARY, 1);
|
||||
}
|
||||
START_TIME = cal->getTime(status);
|
||||
|
||||
cal->set(2015, UCAL_JANUARY, 1);
|
||||
END_TIME = cal->getTime(status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln("getTime failed");
|
||||
return;
|
||||
}
|
||||
|
||||
// Whether each pattern is ambiguous at DST->STD local time overlap
|
||||
UBool AMBIGUOUS_DST_DECESSION[] = {FALSE, FALSE, FALSE, FALSE, TRUE, TRUE, FALSE, TRUE};
|
||||
// Whether each pattern is ambiguous at STD->STD/DST->DST local time overlap
|
||||
UBool AMBIGUOUS_NEGATIVE_SHIFT[] = {TRUE, TRUE, FALSE, FALSE, TRUE, TRUE, TRUE, TRUE};
|
||||
|
||||
UnicodeString BASEPATTERN("yyyy-MM-dd'T'HH:mm:ss.SSS");
|
||||
|
||||
// timer for performance analysis
|
||||
UDate timer;
|
||||
UDate times[NUM_PATTERNS];
|
||||
for (int32_t i = 0; i < NUM_PATTERNS; i++) {
|
||||
times[i] = 0;
|
||||
}
|
||||
|
||||
UBool REALLY_VERBOSE = FALSE;
|
||||
|
||||
// Set up test locales
|
||||
const Locale locales1[] = {
|
||||
Locale("en_US")
|
||||
};
|
||||
const Locale locales2[] = {
|
||||
Locale("en_US"),
|
||||
Locale("en"),
|
||||
Locale("de_DE"),
|
||||
Locale("es_ES"),
|
||||
Locale("fr_FR"),
|
||||
Locale("it_IT"),
|
||||
Locale("ja_JP"),
|
||||
Locale("ko_KR"),
|
||||
Locale("pt_BR"),
|
||||
Locale("zh_Hans_CN"),
|
||||
Locale("zh_Hant_TW")
|
||||
};
|
||||
|
||||
const Locale *LOCALES;
|
||||
int32_t nLocales;
|
||||
if (DEBUG_ALL) {
|
||||
LOCALES = Locale::getAvailableLocales(nLocales);
|
||||
} else if (quick) {
|
||||
LOCALES = locales1;
|
||||
nLocales = sizeof(locales1)/sizeof(Locale);
|
||||
} else {
|
||||
LOCALES = locales2;
|
||||
nLocales = sizeof(locales2)/sizeof(Locale);
|
||||
}
|
||||
|
||||
StringEnumeration *tzids = TimeZone::createEnumeration();
|
||||
if (U_FAILURE(status)) {
|
||||
errln("tzids->count failed");
|
||||
return;
|
||||
}
|
||||
|
||||
int32_t testCounts = 0;
|
||||
UDate testTimes[4];
|
||||
UBool expectedRoundTrip[4];
|
||||
int32_t testLen = 0;
|
||||
|
||||
for (int32_t locidx = 0; locidx < nLocales; locidx++) {
|
||||
logln((UnicodeString)"Locale: " + LOCALES[locidx].getName());
|
||||
|
||||
for (int32_t patidx = 0; patidx < NUM_PATTERNS; patidx++) {
|
||||
logln((UnicodeString)" pattern: " + PATTERNS[patidx]);
|
||||
|
||||
//DEBUG static const char* PATTERNS[] = {"z", "zzzz", "Z", "ZZZZ", "v", "vvvv", "V", "VVVV"};
|
||||
//if (patidx != 1) continue;
|
||||
|
||||
UnicodeString pattern(BASEPATTERN);
|
||||
pattern.append(" ").append(PATTERNS[patidx]);
|
||||
|
||||
SimpleDateFormat *sdf = new SimpleDateFormat(pattern, LOCALES[locidx], status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln((UnicodeString)"new SimpleDateFormat failed for pattern " +
|
||||
pattern + " for locale " + LOCALES[locidx].getName());
|
||||
status = U_ZERO_ERROR;
|
||||
continue;
|
||||
}
|
||||
|
||||
tzids->reset(status);
|
||||
const UnicodeString *tzid;
|
||||
|
||||
timer = Calendar::getNow();
|
||||
|
||||
while ((tzid = tzids->snext(status))) {
|
||||
UnicodeString canonical;
|
||||
ZoneMeta::getCanonicalID(*tzid, canonical);
|
||||
if (*tzid != canonical) {
|
||||
// Skip aliases
|
||||
continue;
|
||||
}
|
||||
BasicTimeZone *tz = (BasicTimeZone*)TimeZone::createTimeZone(*tzid);
|
||||
sdf->setTimeZone(*tz);
|
||||
|
||||
UDate t = START_TIME;
|
||||
TimeZoneTransition tzt;
|
||||
UBool tztAvail = FALSE;
|
||||
UBool middle = TRUE;
|
||||
|
||||
while (t < END_TIME) {
|
||||
if (!tztAvail) {
|
||||
testTimes[0] = t;
|
||||
expectedRoundTrip[0] = TRUE;
|
||||
testLen = 1;
|
||||
} else {
|
||||
int32_t fromOffset = tzt.getFrom()->getRawOffset() + tzt.getFrom()->getDSTSavings();
|
||||
int32_t toOffset = tzt.getTo()->getRawOffset() + tzt.getTo()->getDSTSavings();
|
||||
int32_t delta = toOffset - fromOffset;
|
||||
if (delta < 0) {
|
||||
UBool isDstDecession = tzt.getFrom()->getDSTSavings() > 0 && tzt.getTo()->getDSTSavings() == 0;
|
||||
testTimes[0] = t + delta - 1;
|
||||
expectedRoundTrip[0] = TRUE;
|
||||
testTimes[1] = t + delta;
|
||||
expectedRoundTrip[1] = isDstDecession ?
|
||||
!AMBIGUOUS_DST_DECESSION[patidx] : !AMBIGUOUS_NEGATIVE_SHIFT[patidx];
|
||||
testTimes[2] = t - 1;
|
||||
expectedRoundTrip[2] = isDstDecession ?
|
||||
!AMBIGUOUS_DST_DECESSION[patidx] : !AMBIGUOUS_NEGATIVE_SHIFT[patidx];
|
||||
testTimes[3] = t;
|
||||
expectedRoundTrip[3] = TRUE;
|
||||
testLen = 4;
|
||||
} else {
|
||||
testTimes[0] = t - 1;
|
||||
expectedRoundTrip[0] = TRUE;
|
||||
testTimes[1] = t;
|
||||
expectedRoundTrip[1] = TRUE;
|
||||
testLen = 2;
|
||||
}
|
||||
}
|
||||
for (int32_t testidx = 0; testidx < testLen; testidx++) {
|
||||
if (quick) {
|
||||
// reduce regular test time
|
||||
if (!expectedRoundTrip[testidx]) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
testCounts++;
|
||||
|
||||
UnicodeString text;
|
||||
FieldPosition fpos(0);
|
||||
sdf->format(testTimes[testidx], text, fpos);
|
||||
|
||||
UDate parsedDate = sdf->parse(text, status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln((UnicodeString)"Failed to parse " + text);
|
||||
status = U_ZERO_ERROR;
|
||||
continue;
|
||||
}
|
||||
if (parsedDate != testTimes[testidx]) {
|
||||
UnicodeString msg = (UnicodeString)"Time round trip failed for "
|
||||
+ "tzid=" + *tzid
|
||||
+ ", locale=" + LOCALES[locidx].getName()
|
||||
+ ", pattern=" + PATTERNS[patidx]
|
||||
+ ", text=" + text
|
||||
+ ", time=" + testTimes[testidx]
|
||||
+ ", restime=" + parsedDate
|
||||
+ ", diff=" + (parsedDate - testTimes[testidx]);
|
||||
if (expectedRoundTrip[testidx]) {
|
||||
errln((UnicodeString)"FAIL: " + msg);
|
||||
} else if (REALLY_VERBOSE) {
|
||||
logln(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
tztAvail = tz->getNextTransition(t, FALSE, tzt);
|
||||
if (!tztAvail) {
|
||||
break;
|
||||
}
|
||||
if (middle) {
|
||||
// Test the date in the middle of two transitions.
|
||||
t += (int64_t)((tzt.getTime() - t)/2);
|
||||
middle = FALSE;
|
||||
tztAvail = FALSE;
|
||||
} else {
|
||||
t = tzt.getTime();
|
||||
}
|
||||
}
|
||||
delete tz;
|
||||
}
|
||||
times[patidx] += (Calendar::getNow() - timer);
|
||||
delete sdf;
|
||||
}
|
||||
}
|
||||
UDate total = 0;
|
||||
logln("### Elapsed time by patterns ###");
|
||||
for (int32_t i = 0; i < NUM_PATTERNS; i++) {
|
||||
logln(UnicodeString("") + times[i] + "ms (" + PATTERNS[i] + ")");
|
||||
total += times[i];
|
||||
}
|
||||
logln((UnicodeString)"Total: " + total + "ms");
|
||||
logln((UnicodeString)"Iteration: " + testCounts);
|
||||
|
||||
delete cal;
|
||||
delete tzids;
|
||||
}
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
27
icu4c/source/test/intltest/tzfmttst.h
Normal file
27
icu4c/source/test/intltest/tzfmttst.h
Normal file
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2007, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _TIMEZONEFORMATTEST_
|
||||
#define _TIMEZONEFORMATTEST_
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
#if !UCONFIG_NO_FORMATTING
|
||||
|
||||
#include "intltest.h"
|
||||
|
||||
class TimeZoneFormatTest : public IntlTest {
|
||||
// IntlTest override
|
||||
void runIndexedTest(int32_t index, UBool exec, const char*& name, char* par);
|
||||
|
||||
void TestTimeZoneRoundTrip(void);
|
||||
void TestTimeRoundTrip(void);
|
||||
};
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
||||
#endif // _TIMEZONEFORMATTEST_
|
329
icu4c/source/test/intltest/tzoffloc.cpp
Normal file
329
icu4c/source/test/intltest/tzoffloc.cpp
Normal file
|
@ -0,0 +1,329 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2007, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
#if !UCONFIG_NO_FORMATTING
|
||||
|
||||
#include "tzoffloc.h"
|
||||
|
||||
#include "unicode/ucal.h"
|
||||
#include "unicode/timezone.h"
|
||||
#include "unicode/calendar.h"
|
||||
#include "unicode/dtrule.h"
|
||||
#include "unicode/tzrule.h"
|
||||
#include "unicode/rbtz.h"
|
||||
#include "unicode/simpletz.h"
|
||||
#include "unicode/tzrule.h"
|
||||
#include "unicode/smpdtfmt.h"
|
||||
#include "unicode/gregocal.h"
|
||||
|
||||
void
|
||||
TimeZoneOffsetLocalTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
|
||||
{
|
||||
if (exec) {
|
||||
logln("TestSuite TimeZoneOffsetLocalTest");
|
||||
}
|
||||
switch (index) {
|
||||
TESTCASE(0, TestGetOffsetAroundTransition);
|
||||
default: name = ""; break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Testing getOffset APIs around rule transition by local standard/wall time.
|
||||
*/
|
||||
void
|
||||
TimeZoneOffsetLocalTest::TestGetOffsetAroundTransition() {
|
||||
const int32_t NUM_DATES = 10;
|
||||
const int32_t NUM_TIMEZONES = 3;
|
||||
|
||||
const int32_t HOUR = 60*60*1000;
|
||||
const int32_t MINUTE = 60*1000;
|
||||
|
||||
const int32_t DATES[NUM_DATES][6] = {
|
||||
{2006, UCAL_APRIL, 2, 1, 30, 1*HOUR+30*MINUTE},
|
||||
{2006, UCAL_APRIL, 2, 2, 00, 2*HOUR},
|
||||
{2006, UCAL_APRIL, 2, 2, 30, 2*HOUR+30*MINUTE},
|
||||
{2006, UCAL_APRIL, 2, 3, 00, 3*HOUR},
|
||||
{2006, UCAL_APRIL, 2, 3, 30, 3*HOUR+30*MINUTE},
|
||||
{2006, UCAL_OCTOBER, 29, 0, 30, 0*HOUR+30*MINUTE},
|
||||
{2006, UCAL_OCTOBER, 29, 1, 00, 1*HOUR},
|
||||
{2006, UCAL_OCTOBER, 29, 1, 30, 1*HOUR+30*MINUTE},
|
||||
{2006, UCAL_OCTOBER, 29, 2, 00, 2*HOUR},
|
||||
{2006, UCAL_OCTOBER, 29, 2, 30, 2*HOUR+30*MINUTE},
|
||||
};
|
||||
|
||||
// Expected offsets by int32_t getOffset(uint8_t era, int32_t year, int32_t month, int32_t day,
|
||||
// uint8_t dayOfWeek, int32_t millis, UErrorCode& status)
|
||||
const int32_t OFFSETS1[NUM_DATES] = {
|
||||
// April 2, 2006
|
||||
-8*HOUR,
|
||||
-7*HOUR,
|
||||
-7*HOUR,
|
||||
-7*HOUR,
|
||||
-7*HOUR,
|
||||
|
||||
// October 29, 2006
|
||||
-7*HOUR,
|
||||
-8*HOUR,
|
||||
-8*HOUR,
|
||||
-8*HOUR,
|
||||
-8*HOUR,
|
||||
};
|
||||
|
||||
// Expected offsets by void getOffset(UDate date, UBool local, int32_t& rawOffset,
|
||||
// int32_t& dstOffset, UErrorCode& ec) with local=TRUE
|
||||
// or void getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt,
|
||||
// int32_t& rawOffset, int32_t& dstOffset, UErrorCode& status) with
|
||||
// nonExistingTimeOpt=kStandard/duplicatedTimeOpt=kStandard
|
||||
const int32_t OFFSETS2[NUM_DATES][2] = {
|
||||
// April 2, 2006
|
||||
{-8*HOUR, 0},
|
||||
{-8*HOUR, 0},
|
||||
{-8*HOUR, 0},
|
||||
{-8*HOUR, 1*HOUR},
|
||||
{-8*HOUR, 1*HOUR},
|
||||
|
||||
// Oct 29, 2006
|
||||
{-8*HOUR, 1*HOUR},
|
||||
{-8*HOUR, 0},
|
||||
{-8*HOUR, 0},
|
||||
{-8*HOUR, 0},
|
||||
{-8*HOUR, 0},
|
||||
};
|
||||
|
||||
// Expected offsets by void getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt,
|
||||
// int32_t duplicatedTimeOpt, int32_t& rawOffset, int32_t& dstOffset, UErrorCode& status) with
|
||||
// nonExistingTimeOpt=kDaylight/duplicatedTimeOpt=kDaylight
|
||||
const int32_t OFFSETS3[][2] = {
|
||||
// April 2, 2006
|
||||
{-8*HOUR, 0},
|
||||
{-8*HOUR, 1*HOUR},
|
||||
{-8*HOUR, 1*HOUR},
|
||||
{-8*HOUR, 1*HOUR},
|
||||
{-8*HOUR, 1*HOUR},
|
||||
|
||||
// October 29, 2006
|
||||
{-8*HOUR, 1*HOUR},
|
||||
{-8*HOUR, 1*HOUR},
|
||||
{-8*HOUR, 1*HOUR},
|
||||
{-8*HOUR, 0},
|
||||
{-8*HOUR, 0},
|
||||
};
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
int32_t rawOffset, dstOffset;
|
||||
TimeZone* utc = TimeZone::createTimeZone("UTC");
|
||||
Calendar* cal = Calendar::createInstance(*utc, status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln("Calendar::createInstance failed");
|
||||
return;
|
||||
}
|
||||
cal->clear();
|
||||
|
||||
// Set up TimeZone objects - OlsonTimeZone, SimpleTimeZone and RuleBasedTimeZone
|
||||
BasicTimeZone *TESTZONES[NUM_TIMEZONES];
|
||||
|
||||
TESTZONES[0] = (BasicTimeZone*)TimeZone::createTimeZone("America/Los_Angeles");
|
||||
TESTZONES[1] = new SimpleTimeZone(-8*HOUR, "Simple Pacific Time",
|
||||
UCAL_APRIL, 1, UCAL_SUNDAY, 2*HOUR,
|
||||
UCAL_OCTOBER, -1, UCAL_SUNDAY, 2*HOUR, status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln("SimpleTimeZone constructor failed");
|
||||
return;
|
||||
}
|
||||
|
||||
InitialTimeZoneRule *ir = new InitialTimeZoneRule(
|
||||
"Pacific Standard Time", // Initial time Name
|
||||
-8*HOUR, // Raw offset
|
||||
0*HOUR); // DST saving amount
|
||||
|
||||
RuleBasedTimeZone *rbPT = new RuleBasedTimeZone("Rule based Pacific Time", ir);
|
||||
|
||||
DateTimeRule *dtr;
|
||||
AnnualTimeZoneRule *atzr;
|
||||
const int32_t STARTYEAR = 2000;
|
||||
|
||||
dtr = new DateTimeRule(UCAL_APRIL, 1, UCAL_SUNDAY,
|
||||
2*HOUR, DateTimeRule::WALL_TIME); // 1st Sunday in April, at 2AM wall time
|
||||
atzr = new AnnualTimeZoneRule("Pacific Daylight Time",
|
||||
-8*HOUR /* rawOffset */, 1*HOUR /* dstSavings */, dtr,
|
||||
STARTYEAR, AnnualTimeZoneRule::MAX_YEAR);
|
||||
rbPT->addTransitionRule(atzr, status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln("Could not add DST start rule to the RuleBasedTimeZone rbPT");
|
||||
return;
|
||||
}
|
||||
|
||||
dtr = new DateTimeRule(UCAL_OCTOBER, -1, UCAL_SUNDAY,
|
||||
2*HOUR, DateTimeRule::WALL_TIME); // last Sunday in October, at 2AM wall time
|
||||
atzr = new AnnualTimeZoneRule("Pacific Standard Time",
|
||||
-8*HOUR /* rawOffset */, 0 /* dstSavings */, dtr,
|
||||
STARTYEAR, AnnualTimeZoneRule::MAX_YEAR);
|
||||
rbPT->addTransitionRule(atzr, status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln("Could not add STD start rule to the RuleBasedTimeZone rbPT");
|
||||
return;
|
||||
}
|
||||
|
||||
rbPT->complete(status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln("complete() failed for RuleBasedTimeZone rbPT");
|
||||
return;
|
||||
}
|
||||
|
||||
TESTZONES[2] = rbPT;
|
||||
|
||||
// Calculate millis
|
||||
UDate MILLIS[NUM_DATES];
|
||||
for (int32_t i = 0; i < NUM_DATES; i++) {
|
||||
cal->clear();
|
||||
cal->set(DATES[i][0], DATES[i][1], DATES[i][2], DATES[i][3], DATES[i][4]);
|
||||
MILLIS[i] = cal->getTime(status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln("cal->getTime failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SimpleDateFormat df(UnicodeString("yyyy-MM-dd HH:mm:ss"), status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln("Failed to initialize a SimpleDateFormat");
|
||||
}
|
||||
df.setTimeZone(*utc);
|
||||
UnicodeString dateStr;
|
||||
|
||||
// Test getOffset(uint8_t era, int32_t year, int32_t month, int32_t day,
|
||||
// uint8_t dayOfWeek, int32_t millis, UErrorCode& status)
|
||||
for (int32_t i = 0; i < NUM_TIMEZONES; i++) {
|
||||
for (int32_t d = 0; d < NUM_DATES; d++) {
|
||||
status = U_ZERO_ERROR;
|
||||
int32_t offset = TESTZONES[i]->getOffset(GregorianCalendar::AD, DATES[d][0], DATES[d][1], DATES[d][2],
|
||||
UCAL_SUNDAY, DATES[d][5], status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln((UnicodeString)"getOffset(era,year,month,day,dayOfWeek,millis,status) failed for TESTZONES[" + i + "]");
|
||||
} else if (offset != OFFSETS1[d]) {
|
||||
dateStr.remove();
|
||||
df.format(MILLIS[d], dateStr);
|
||||
errln((UnicodeString)"Bad offset returned by TESTZONES[" + i + "] at "
|
||||
+ dateStr + "(standard) - Got: " + offset + " Expected: " + OFFSETS1[d]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test getOffset(UDate date, UBool local, int32_t& rawOffset,
|
||||
// int32_t& dstOffset, UErrorCode& ec) with local = TRUE
|
||||
for (int32_t i = 0; i < NUM_TIMEZONES; i++) {
|
||||
for (int32_t m = 0; m < NUM_DATES; m++) {
|
||||
status = U_ZERO_ERROR;
|
||||
TESTZONES[i]->getOffset(MILLIS[m], TRUE, rawOffset, dstOffset, status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln((UnicodeString)"getOffset(date,local,rawOfset,dstOffset,ec) failed for TESTZONES[" + i + "]");
|
||||
} else if (rawOffset != OFFSETS2[m][0] || dstOffset != OFFSETS2[m][1]) {
|
||||
dateStr.remove();
|
||||
df.format(MILLIS[m], dateStr);
|
||||
errln((UnicodeString)"Bad offset returned by TESTZONES[" + i + "] at "
|
||||
+ dateStr + "(wall) - Got: "
|
||||
+ rawOffset + "/" + dstOffset
|
||||
+ " Expected: " + OFFSETS2[m][0] + "/" + OFFSETS2[m][1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt,
|
||||
// int32_t& rawOffset, int32_t& dstOffset, UErroCode& status)
|
||||
// with nonExistingTimeOpt=kStandard/duplicatedTimeOpt=kStandard
|
||||
for (int32_t i = 0; i < NUM_TIMEZONES; i++) {
|
||||
for (int m = 0; m < NUM_DATES; m++) {
|
||||
status = U_ZERO_ERROR;
|
||||
TESTZONES[i]->getOffsetFromLocal(MILLIS[m], BasicTimeZone::kStandard, BasicTimeZone::kStandard,
|
||||
rawOffset, dstOffset, status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln((UnicodeString)"getOffsetFromLocal with kStandard/kStandard failed for TESTZONES[" + i + "]");
|
||||
} else if (rawOffset != OFFSETS2[m][0] || dstOffset != OFFSETS2[m][1]) {
|
||||
dateStr.remove();
|
||||
df.format(MILLIS[m], dateStr);
|
||||
errln((UnicodeString)"Bad offset returned by TESTZONES[" + i + "] at "
|
||||
+ dateStr + "(wall/kStandard/kStandard) - Got: "
|
||||
+ rawOffset + "/" + dstOffset
|
||||
+ " Expected: " + OFFSETS2[m][0] + "/" + OFFSETS2[m][1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt,
|
||||
// int32_t& rawOffset, int32_t& dstOffset, UErroCode& status)
|
||||
// with nonExistingTimeOpt=kDaylight/duplicatedTimeOpt=kDaylight
|
||||
for (int32_t i = 0; i < NUM_TIMEZONES; i++) {
|
||||
for (int m = 0; m < NUM_DATES; m++) {
|
||||
status = U_ZERO_ERROR;
|
||||
TESTZONES[i]->getOffsetFromLocal(MILLIS[m], BasicTimeZone::kDaylight, BasicTimeZone::kDaylight,
|
||||
rawOffset, dstOffset, status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln((UnicodeString)"getOffsetFromLocal with kDaylight/kDaylight failed for TESTZONES[" + i + "]");
|
||||
} else if (rawOffset != OFFSETS3[m][0] || dstOffset != OFFSETS3[m][1]) {
|
||||
dateStr.remove();
|
||||
df.format(MILLIS[m], dateStr);
|
||||
errln((UnicodeString)"Bad offset returned by TESTZONES[" + i + "] at "
|
||||
+ dateStr + "(wall/kDaylight/kDaylight) - Got: "
|
||||
+ rawOffset + "/" + dstOffset
|
||||
+ " Expected: " + OFFSETS3[m][0] + "/" + OFFSETS3[m][1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt,
|
||||
// int32_t& rawOffset, int32_t& dstOffset, UErroCode& status)
|
||||
// with nonExistingTimeOpt=kFormer/duplicatedTimeOpt=kLatter
|
||||
for (int32_t i = 0; i < NUM_TIMEZONES; i++) {
|
||||
for (int m = 0; m < NUM_DATES; m++) {
|
||||
status = U_ZERO_ERROR;
|
||||
TESTZONES[i]->getOffsetFromLocal(MILLIS[m], BasicTimeZone::kFormer, BasicTimeZone::kLatter,
|
||||
rawOffset, dstOffset, status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln((UnicodeString)"getOffsetFromLocal with kFormer/kLatter failed for TESTZONES[" + i + "]");
|
||||
} else if (rawOffset != OFFSETS2[m][0] || dstOffset != OFFSETS2[m][1]) {
|
||||
dateStr.remove();
|
||||
df.format(MILLIS[m], dateStr);
|
||||
errln((UnicodeString)"Bad offset returned by TESTZONES[" + i + "] at "
|
||||
+ dateStr + "(wall/kFormer/kLatter) - Got: "
|
||||
+ rawOffset + "/" + dstOffset
|
||||
+ " Expected: " + OFFSETS2[m][0] + "/" + OFFSETS2[m][1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test getOffsetFromLocal(UDate date, int32_t nonExistingTimeOpt, int32_t duplicatedTimeOpt,
|
||||
// int32_t& rawOffset, int32_t& dstOffset, UErroCode& status)
|
||||
// with nonExistingTimeOpt=kLatter/duplicatedTimeOpt=kFormer
|
||||
for (int32_t i = 0; i < NUM_TIMEZONES; i++) {
|
||||
for (int m = 0; m < NUM_DATES; m++) {
|
||||
status = U_ZERO_ERROR;
|
||||
TESTZONES[i]->getOffsetFromLocal(MILLIS[m], BasicTimeZone::kLatter, BasicTimeZone::kFormer,
|
||||
rawOffset, dstOffset, status);
|
||||
if (U_FAILURE(status)) {
|
||||
errln((UnicodeString)"getOffsetFromLocal with kLatter/kFormer failed for TESTZONES[" + i + "]");
|
||||
} else if (rawOffset != OFFSETS3[m][0] || dstOffset != OFFSETS3[m][1]) {
|
||||
dateStr.remove();
|
||||
df.format(MILLIS[m], dateStr);
|
||||
errln((UnicodeString)"Bad offset returned by TESTZONES[" + i + "] at "
|
||||
+ dateStr + "(wall/kLatter/kFormer) - Got: "
|
||||
+ rawOffset + "/" + dstOffset
|
||||
+ " Expected: " + OFFSETS3[m][0] + "/" + OFFSETS3[m][1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int32_t i = 0; i < NUM_TIMEZONES; i++) {
|
||||
delete TESTZONES[i];
|
||||
}
|
||||
delete utc;
|
||||
delete cal;
|
||||
}
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
26
icu4c/source/test/intltest/tzoffloc.h
Normal file
26
icu4c/source/test/intltest/tzoffloc.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2007, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef _TIMEZONEOFFSETLOCALTEST_
|
||||
#define _TIMEZONEOFFSETLOCALTEST_
|
||||
|
||||
#include "unicode/utypes.h"
|
||||
|
||||
#if !UCONFIG_NO_FORMATTING
|
||||
|
||||
#include "intltest.h"
|
||||
|
||||
class TimeZoneOffsetLocalTest : public IntlTest {
|
||||
// IntlTest override
|
||||
void runIndexedTest(int32_t index, UBool exec, const char*& name, char* par);
|
||||
|
||||
void TestGetOffsetAroundTransition(void);
|
||||
};
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
||||
#endif // _TIMEZONEOFFSETLOCALTEST_
|
|
@ -18,6 +18,7 @@
|
|||
#include "cmemory.h"
|
||||
#include "putilimp.h"
|
||||
#include "cstring.h"
|
||||
#include "olsontz.h"
|
||||
|
||||
#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0]))
|
||||
|
||||
|
@ -755,53 +756,92 @@ void TimeZoneTest::TestShortZoneIDs()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Utility function for TestCustomParse
|
||||
*/
|
||||
UnicodeString& TimeZoneTest::formatMinutes(int32_t min, UnicodeString& rv, UBool insertSep/*=TRUE*/)
|
||||
{
|
||||
rv.remove();
|
||||
UnicodeString& TimeZoneTest::formatOffset(int32_t offset, UnicodeString &rv) {
|
||||
rv.remove();
|
||||
UChar sign = 0x002B;
|
||||
if (offset < 0) {
|
||||
sign = 0x002D;
|
||||
offset = -offset;
|
||||
}
|
||||
|
||||
UChar sign = 0x002B;
|
||||
if (min < 0) {
|
||||
sign = 0x002D;
|
||||
min = -min;
|
||||
int32_t s = offset % 60;
|
||||
offset /= 60;
|
||||
int32_t m = offset % 60;
|
||||
int32_t h = offset / 60;
|
||||
|
||||
rv += (UChar)(sign);
|
||||
if (h >= 10) {
|
||||
rv += (UChar)(0x0030 + (h/10));
|
||||
} else {
|
||||
rv += (UChar)0x0030;
|
||||
}
|
||||
rv += (UChar)(0x0030 + (h%10));
|
||||
|
||||
rv += (UChar)0x003A; /* ':' */
|
||||
if (m >= 10) {
|
||||
rv += (UChar)(0x0030 + (m/10));
|
||||
} else {
|
||||
rv += (UChar)0x0030;
|
||||
}
|
||||
rv += (UChar)(0x0030 + (m%10));
|
||||
|
||||
if (s) {
|
||||
rv += (UChar)0x003A; /* ':' */
|
||||
if (s >= 10) {
|
||||
rv += (UChar)(0x0030 + (s/10));
|
||||
} else {
|
||||
rv += (UChar)0x0030;
|
||||
}
|
||||
int h = min/60;
|
||||
min = min%60;
|
||||
|
||||
rv += (UChar)(sign);
|
||||
if(h >= 10)
|
||||
rv += (UChar)(0x0030 + (h/10));
|
||||
else
|
||||
rv += "0";
|
||||
|
||||
rv += (UChar)(0x0030 + (h%10));
|
||||
|
||||
if (insertSep)
|
||||
rv += ":";
|
||||
|
||||
if(min >= 10)
|
||||
rv += (UChar)(0x0030 + (min/10));
|
||||
else
|
||||
rv += "0";
|
||||
|
||||
rv += (UChar)(0x0030 + (min%10));
|
||||
|
||||
return rv;
|
||||
rv += (UChar)(0x0030 + (s%10));
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Utility function for TestCustomParse, generating RFC822 style
|
||||
* time zone string for the give offset in minutes
|
||||
* Utility function for TestCustomParse, generating time zone ID
|
||||
* string for the give offset.
|
||||
*/
|
||||
UnicodeString& TimeZoneTest::formatRFC822TZ(int32_t min, UnicodeString& rv)
|
||||
{
|
||||
UnicodeString offsetStr;
|
||||
formatMinutes(min, offsetStr, FALSE);
|
||||
UnicodeString& TimeZoneTest::formatTZID(int32_t offset, UnicodeString &rv) {
|
||||
rv.remove();
|
||||
UChar sign = 0x002B;
|
||||
if (offset < 0) {
|
||||
sign = 0x002D;
|
||||
offset = -offset;
|
||||
}
|
||||
|
||||
int32_t s = offset % 60;
|
||||
offset /= 60;
|
||||
int32_t m = offset % 60;
|
||||
int32_t h = offset / 60;
|
||||
|
||||
rv += "GMT";
|
||||
rv += offsetStr;
|
||||
rv += (UChar)(sign);
|
||||
if (h >= 10) {
|
||||
rv += (UChar)(0x0030 + (h/10));
|
||||
} else {
|
||||
rv += (UChar)0x0030;
|
||||
}
|
||||
rv += (UChar)(0x0030 + (h%10));
|
||||
|
||||
if (m >= 10) {
|
||||
rv += (UChar)(0x0030 + (m/10));
|
||||
} else {
|
||||
rv += (UChar)0x0030;
|
||||
}
|
||||
rv += (UChar)(0x0030 + (m%10));
|
||||
|
||||
if (s) {
|
||||
if (s >= 10) {
|
||||
rv += (UChar)(0x0030 + (s/10));
|
||||
} else {
|
||||
rv += (UChar)0x0030;
|
||||
}
|
||||
rv += (UChar)(0x0030 + (s%10));
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -825,92 +865,63 @@ void TimeZoneTest::TestCustomParse()
|
|||
}
|
||||
kData[] =
|
||||
{
|
||||
// ID Expected offset in minutes
|
||||
//{"GMT", kUnparseable}, //Isn't custom. Can't test it here. [returns normal GMT]
|
||||
// ID Expected offset in seconds
|
||||
{"GMT", kUnparseable}, //Isn't custom. [returns normal GMT]
|
||||
{"GMT-YOUR.AD.HERE", kUnparseable},
|
||||
// {"GMT0", kUnparseable}, // ICU 2.8: An Olson zone ID
|
||||
// {"GMT+0", (0)}, // ICU 2.8: An Olson zone ID
|
||||
{"GMT+1", (60)},
|
||||
{"GMT-0030", (-30)},
|
||||
{"GMT0", kUnparseable},
|
||||
{"GMT+0", (0)},
|
||||
{"GMT+1", (1*60*60)},
|
||||
{"GMT-0030", (-30*60)},
|
||||
{"GMT+15:99", kUnparseable},
|
||||
{"GMT+", kUnparseable},
|
||||
{"GMT-", kUnparseable},
|
||||
{"GMT+0:", kUnparseable},
|
||||
{"GMT-:", kUnparseable},
|
||||
{"GMT-YOUR.AD.HERE", kUnparseable},
|
||||
{"GMT+0010", (10)}, // Interpret this as 00:10
|
||||
{"GMT-10", (-10*60)},
|
||||
{"GMT+30", (30)},
|
||||
{"GMT-3:30", (-(3*60+30))},
|
||||
{"GMT-230", (-(2*60+30))},
|
||||
{"GMT-YOUR.AD.HERE", kUnparseable},
|
||||
{"GMT+0010", (10*60)}, // Interpret this as 00:10
|
||||
{"GMT-10", (-10*60*60)},
|
||||
{"GMT+30", kUnparseable},
|
||||
{"GMT-3:30", (-(3*60+30)*60)},
|
||||
{"GMT-230", (-(2*60+30)*60)},
|
||||
{"GMT+05:13:05", ((5*60+13)*60+5)},
|
||||
{"GMT-71023", (-((7*60+10)*60+23))},
|
||||
{"GMT+01:23:45:67", kUnparseable},
|
||||
{"GMT+01:234", kUnparseable},
|
||||
{"GMT-2:31:123", kUnparseable},
|
||||
{"GMT+3:75", kUnparseable},
|
||||
{"GMT-01010101", kUnparseable},
|
||||
{0, 0}
|
||||
};
|
||||
|
||||
for (i=0; kData[i].customId != 0; i++)
|
||||
{
|
||||
for (i=0; kData[i].customId != 0; i++) {
|
||||
UnicodeString id(kData[i].customId);
|
||||
int32_t exp = kData[i].expectedOffset;
|
||||
/*
|
||||
{ // for no data test Jitterbug 4354
|
||||
UErrorCode success = U_ZERO_ERROR;
|
||||
NumberFormat* numberFormat = NumberFormat::createInstance(success);
|
||||
if (U_FAILURE(success)) {
|
||||
dataerrln(" NumberFormat::createInstance() error");
|
||||
return;
|
||||
}
|
||||
delete numberFormat;
|
||||
}
|
||||
*/
|
||||
|
||||
TimeZone *zone = TimeZone::createTimeZone(id);
|
||||
UnicodeString itsID, temp;
|
||||
|
||||
logln();
|
||||
logln("testing # " + formatMinutes(i, temp) + id);
|
||||
|
||||
/*
|
||||
if(zone == NULL)
|
||||
{
|
||||
errln("FAIL: Could not createTimeZone(" + id + "). Returned NULL.");
|
||||
continue;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
if (! zone->getID(itsID).compare("GMT"))
|
||||
//if(zone == NULL)
|
||||
{
|
||||
logln(id + " -> generic GMT");
|
||||
// When TimeZone.getTimeZone() can't parse the id, it
|
||||
// returns GMT -- a dubious practice, but required for
|
||||
// backward compatibility.
|
||||
if (exp != kUnparseable) {
|
||||
errln("FAIL: Expected offset of " + formatMinutes(exp,temp) +
|
||||
" for " + id + ", got parse failure");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (zone->getDynamicClassID() == OlsonTimeZone::getStaticClassID()) {
|
||||
logln(id + " -> Olson time zone");
|
||||
} else {
|
||||
zone->getID(itsID);
|
||||
int32_t ioffset = zone->getRawOffset()/60000;
|
||||
int32_t ioffset = zone->getRawOffset()/1000;
|
||||
UnicodeString offset, expectedID;
|
||||
formatMinutes(ioffset, offset);
|
||||
formatRFC822TZ(ioffset, expectedID);
|
||||
logln(id + " -> " + itsID + " GMT" + offset);
|
||||
if (exp == kUnparseable)
|
||||
{
|
||||
errln("FAIL: Expected parse failure for " + id +
|
||||
", got offset of " + offset +
|
||||
", id " + itsID);
|
||||
formatOffset(ioffset, offset);
|
||||
formatTZID(ioffset, expectedID);
|
||||
logln(id + " -> " + itsID + " " + offset);
|
||||
if (exp == kUnparseable && itsID != "GMT") {
|
||||
errln("Expected parse failure for " + id +
|
||||
", got offset of " + offset +
|
||||
", id " + itsID);
|
||||
}
|
||||
else if (ioffset != exp ||
|
||||
(itsID.compare(expectedID) != 0))
|
||||
{
|
||||
errln("Expected offset of " + formatMinutes(exp,temp) +
|
||||
", id " + expectedID +
|
||||
", for " + id +
|
||||
", got offset of " + offset +
|
||||
", id " + itsID);
|
||||
// JDK 1.3 creates custom zones with the ID "Custom"
|
||||
// JDK 1.4 creates custom zones with IDs of the form "GMT+02:00"
|
||||
// ICU creates custom zones with IDs of the form "GMT+0200"
|
||||
else if (exp != kUnparseable && (ioffset != exp || itsID != expectedID)) {
|
||||
errln("Expected offset of " + formatOffset(exp, temp) +
|
||||
", id " + expectedID +
|
||||
", for " + id +
|
||||
", got offset of " + offset +
|
||||
", id " + itsID);
|
||||
}
|
||||
}
|
||||
delete zone;
|
||||
|
|
|
@ -92,8 +92,8 @@ public:
|
|||
|
||||
private:
|
||||
// internal functions
|
||||
static UnicodeString& formatMinutes(int32_t min, UnicodeString& rv, UBool insertSep = TRUE);
|
||||
static UnicodeString& formatRFC822TZ(int32_t min, UnicodeString& rv);
|
||||
static UnicodeString& formatOffset(int32_t offset, UnicodeString& rv);
|
||||
static UnicodeString& formatTZID(int32_t offset, UnicodeString& rv);
|
||||
};
|
||||
|
||||
#endif /* #if !UCONFIG_NO_FORMATTING */
|
||||
|
|
8
icu4c/source/test/testdata/structLocale.txt
vendored
8
icu4c/source/test/testdata/structLocale.txt
vendored
|
@ -1897,6 +1897,7 @@ structLocale:table(nofallback){
|
|||
ypk{""}
|
||||
za{""}
|
||||
zap{""}
|
||||
zbl{""}
|
||||
zen{""}
|
||||
zh{""}
|
||||
zh_Hans{""}
|
||||
|
@ -1938,6 +1939,7 @@ structLocale:table(nofallback){
|
|||
Scripts{
|
||||
Arab{""}
|
||||
Armn{""}
|
||||
Avst{""}
|
||||
Bali{""}
|
||||
Batk{""}
|
||||
Beng{""}
|
||||
|
@ -2001,6 +2003,7 @@ structLocale:table(nofallback){
|
|||
Lyci{""}
|
||||
Lydi{""}
|
||||
Mand{""}
|
||||
Mani{""}
|
||||
Maya{""}
|
||||
Mero{""}
|
||||
Mlym{""}
|
||||
|
@ -2016,12 +2019,14 @@ structLocale:table(nofallback){
|
|||
Osma{""}
|
||||
Perm{""}
|
||||
Phag{""}
|
||||
Phlv{""}
|
||||
Phnx{""}
|
||||
Plrd{""}
|
||||
Qaai{""}
|
||||
Rjng{""}
|
||||
Roro{""}
|
||||
Runr{""}
|
||||
Samr{""}
|
||||
Sara{""}
|
||||
Saur{""}
|
||||
Sgnw{""}
|
||||
|
@ -2080,6 +2085,7 @@ structLocale:table(nofallback){
|
|||
1606NICT{""}
|
||||
1694ACAD{""}
|
||||
1901{""}
|
||||
1994{""}
|
||||
1996{""}
|
||||
AREVELA{""}
|
||||
AREVMDA{""}
|
||||
|
@ -2091,6 +2097,7 @@ structLocale:table(nofallback){
|
|||
GAULISH{""}
|
||||
GUOYU{""}
|
||||
HAKKA{""}
|
||||
LIPAW{""}
|
||||
LOJBAN{""}
|
||||
MONOTON{""}
|
||||
NEDIS{""}
|
||||
|
@ -2102,6 +2109,7 @@ structLocale:table(nofallback){
|
|||
REVISED{""}
|
||||
ROZAJ{""}
|
||||
SAAHO{""}
|
||||
SCOTLAND{""}
|
||||
SCOUSE{""}
|
||||
SOLBA{""}
|
||||
TARASK{""}
|
||||
|
|
Loading…
Add table
Reference in a new issue