]> git.saurik.com Git - apple/icu.git/blame - icuSources/test/intltest/dtptngts.cpp
ICU-66108.tar.gz
[apple/icu.git] / icuSources / test / intltest / dtptngts.cpp
CommitLineData
f3c0d7a5
A
1// © 2016 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html
46f4442e 3/********************************************************************
2ca993e8
A
4 * COPYRIGHT:
5 * Copyright (c) 2008-2016, International Business Machines Corporation and
46f4442e
A
6 * others. All Rights Reserved.
7 ********************************************************************/
8
9#include "unicode/utypes.h"
10
11#if !UCONFIG_NO_FORMATTING
12
13#include <stdio.h>
14#include <stdlib.h>
2ca993e8 15#include "dtptngts.h"
46f4442e
A
16
17#include "unicode/calendar.h"
18#include "unicode/smpdtfmt.h"
19#include "unicode/dtfmtsym.h"
20#include "unicode/dtptngen.h"
0f5d89e8 21#include "unicode/ustring.h"
3d1f044b 22#include "unicode/datefmt.h"
2ca993e8 23#include "cmemory.h"
3d1f044b 24#include "cstring.h"
46f4442e
A
25#include "loctest.h"
26
27
28// This is an API test, not a unit test. It doesn't test very many cases, and doesn't
29// try to test the full functionality. It just calls each function in the class and
30// verifies that it works on a basic level.
31
32void IntlTestDateTimePatternGeneratorAPI::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
33{
34 if (exec) logln("TestSuite DateTimePatternGeneratorAPI");
35 switch (index) {
36 TESTCASE(0, testAPI);
729e4ab9 37 TESTCASE(1, testOptions);
57a6839d 38 TESTCASE(2, testAllFieldPatterns);
2ca993e8
A
39 TESTCASE(3, testStaticGetSkeleton);
40 TESTCASE(4, testC);
0f5d89e8
A
41 TESTCASE(5, testSkeletonsWithDayPeriods);
42 TESTCASE(6, testGetFieldDisplayNames);
3d1f044b 43 TESTCASE(7, testJjMapping);
340931cb
A
44 TESTCASE(8, test20640_HourCyclArsEnNH);
45 TESTCASE(9, testFallbackWithDefaultRootLocale);
46f4442e
A
46 default: name = ""; break;
47 }
48}
49
340931cb 50#define MAX_LOCALE 15
46f4442e
A
51
52/**
53 * Test various generic API methods of DateTimePatternGenerator for API coverage.
54 */
55void IntlTestDateTimePatternGeneratorAPI::testAPI(/*char *par*/)
56{
57 UnicodeString patternData[] = {
729e4ab9
A
58 UnicodeString("yM"), // 00
59 UnicodeString("yMMM"), // 01
60 UnicodeString("yMd"), // 02
61 UnicodeString("yMMMd"), // 03
62 UnicodeString("Md"), // 04
63 UnicodeString("MMMd"), // 05
4388f060
A
64 UnicodeString("MMMMd"), // 06
65 UnicodeString("yQQQ"), // 07
66 UnicodeString("hhmm"), // 08
67 UnicodeString("HHmm"), // 09
68 UnicodeString("jjmm"), // 10
69 UnicodeString("mmss"), // 11
70 UnicodeString("yyyyMMMM"), // 12
71 UnicodeString("MMMEd"), // 13
72 UnicodeString("Ed"), // 14
73 UnicodeString("jmmssSSS"), // 15
57a6839d 74 UnicodeString("JJmm"), // 16
46f4442e
A
75 UnicodeString(),
76 };
2ca993e8 77
46f4442e 78 const char* testLocale[MAX_LOCALE][4] = {
729e4ab9
A
79 {"en", "US", "", ""}, // 0
80 {"en", "US", "", "calendar=japanese"}, // 1
81 {"de", "DE", "", ""}, // 2
82 {"fi", "", "", ""}, // 3
4388f060
A
83 {"es", "", "", ""}, // 4
84 {"ja", "", "", ""}, // 5
85 {"ja", "", "", "calendar=japanese"}, // 6
86 {"zh", "Hans", "CN", ""}, // 7
87 {"zh", "TW", "", "calendar=roc"}, // 8
88 {"ru", "", "", ""}, // 9
340931cb
A
89 {"zh", "", "", "calendar=chinese"}, // 10
90 {"ja", "JP", "TRADITIONAL", ""}, // 11
91 {"zh", "", "", "calendar=chinese;numbers=hanidays"}, // 12 Apple add
92 {"ar", "", "", ""}, // 13 Apple add
93 {"en", "ID", "", "calendar=buddhist"}, // 14 Apple add <rdar://problem/37505940>
46f4442e 94 };
2ca993e8 95
729e4ab9 96 // For Weds, Jan 13, 1999, 23:58:59
340931cb 97 UnicodeString patternResults_en_US[] = {
729e4ab9
A
98 // en_US // 0 en_US
99 UnicodeString("1/1999"), // 00: yM
100 UnicodeString("Jan 1999"), // 01: yMMM
101 UnicodeString("1/13/1999"), // 02: yMd
102 UnicodeString("Jan 13, 1999"), // 03: yMMMd
103 UnicodeString("1/13"), // 04: Md
104 UnicodeString("Jan 13"), // 05: MMMd
4388f060
A
105 UnicodeString("January 13"), // 06: MMMMd
106 UnicodeString("Q1 1999"), // 07: yQQQ
107 UnicodeString("11:58 PM"), // 08: hhmm
108 UnicodeString("23:58"), // 09: HHmm
109 UnicodeString("11:58 PM"), // 10: jjmm
110 UnicodeString("58:59"), // 11: mmss
111 UnicodeString("January 1999"), // 12: yyyyMMMM
112 UnicodeString("Wed, Jan 13"), // 13: MMMEd -> EEE, MMM d
113 UnicodeString("13 Wed"), // 14: Ed -> d EEE
114 UnicodeString("11:58:59.123 PM"), // 15: jmmssSSS -> "h:mm:ss.SSS a"
57a6839d 115 UnicodeString("11:58"), // 16: JJmm
340931cb 116 };
729e4ab9 117
340931cb 118 UnicodeString patternResults_en_US_japanese[] = {
729e4ab9 119 // en_US@calendar=japanese // 1 en_US@calendar=japanese
4388f060 120 UnicodeString("1/11 H"), // 0: yM
729e4ab9 121 UnicodeString("Jan 11 Heisei"), // 1: yMMM
4388f060
A
122 UnicodeString("1/13/11 H"), // 2: yMd
123 UnicodeString("Jan 13, 11 Heisei"), // 3: yMMMd
729e4ab9
A
124 UnicodeString("1/13"), // 4: Md
125 UnicodeString("Jan 13"), // 5: MMMd
4388f060
A
126 UnicodeString("January 13"), // 6: MMMMd
127 UnicodeString("Q1 11 Heisei"), // 7: yQQQ
128 UnicodeString("11:58 PM"), // 8: hhmm
129 UnicodeString("23:58"), // 9: HHmm
130 UnicodeString("11:58 PM"), // 10: jjmm
131 UnicodeString("58:59"), // 11: mmss
132 UnicodeString("January 11 Heisei"), // 12: yyyyMMMM
133 UnicodeString("Wed, Jan 13"), // 13: MMMEd -> EEE, MMM d"
134 UnicodeString("13 Wed"), // 14: Ed -> d EEE
135 UnicodeString("11:58:59.123 PM"), // 15: jmmssSSS -> "h:mm:ss.SSS a"
57a6839d 136 UnicodeString("11:58"), // 16: JJmm
340931cb 137 };
729e4ab9 138
340931cb 139 UnicodeString patternResults_de_DE[] = {
729e4ab9
A
140 // de_DE // 2 de_DE
141 UnicodeString("1.1999"), // 00: yM
51004dcb 142 UnicodeString("Jan. 1999"), // 01: yMMM
729e4ab9 143 UnicodeString("13.1.1999"), // 02: yMd
51004dcb 144 UnicodeString("13. Jan. 1999"), // 03: yMMMd
729e4ab9 145 UnicodeString("13.1."), // 04: Md
51004dcb 146 UnicodeString("13. Jan."), // 05: MMMd
4388f060
A
147 UnicodeString("13. Januar"), // 06: MMMMd
148 UnicodeString("Q1 1999"), // 07: yQQQ
d25163bf 149 UnicodeString("11:58 PM"), // 08: hhmm
4388f060
A
150 UnicodeString("23:58"), // 09: HHmm
151 UnicodeString("23:58"), // 10: jjmm
152 UnicodeString("58:59"), // 11: mmss
153 UnicodeString("Januar 1999"), // 12: yyyyMMMM
2ca993e8 154 UnicodeString("Mi. 13. Jan."), // 13: MMMEd -> E d. MMM
d25163bf 155 UnicodeString("Mi. 13."), // 14: Ed -> E d.
4388f060 156 UnicodeString("23:58:59,123"), // 15: jmmssSSS -> "HH:mm:ss,SSS"
57a6839d 157 UnicodeString("23:58"), // 16: JJmm
340931cb 158 };
729e4ab9 159
340931cb 160 UnicodeString patternResults_fi[] = {
729e4ab9
A
161 // fi // 3 fi
162 UnicodeString("1.1999"), // 00: yM (fixed expected result per ticket:6626:)
163 UnicodeString("tammi 1999"), // 01: yMMM
164 UnicodeString("13.1.1999"), // 02: yMd
f3c0d7a5 165 UnicodeString("13.1.1999"), // 03: yMMMd
729e4ab9 166 UnicodeString("13.1."), // 04: Md
4388f060
A
167 UnicodeString("13.1."), // 05: MMMd
168 UnicodeString("13. tammikuuta"), // 06: MMMMd
169 UnicodeString("1. nelj. 1999"), // 07: yQQQ
170 UnicodeString("11.58 ip."), // 08: hhmm
171 UnicodeString("23.58"), // 09: HHmm
172 UnicodeString("23.58"), // 10: jjmm
173 UnicodeString("58.59"), // 11: mmss
174 UnicodeString("tammikuu 1999"), // 12: yyyyMMMM
f3c0d7a5 175 UnicodeString("ke 13.1."), // 13: MMMEd -> EEE d.M.
4388f060
A
176 UnicodeString("ke 13."), // 14: Ed -> ccc d.
177 UnicodeString("23.58.59,123"), // 15: jmmssSSS -> "H.mm.ss,SSS"
57a6839d 178 UnicodeString("23.58"), // 16: JJmm
340931cb 179 };
4388f060 180
340931cb 181 UnicodeString patternResults_es[] = {
4388f060
A
182 // es // 4 es
183 UnicodeString("1/1999"), // 00: yM -> "M/y"
184 UnicodeString("ene 1999"), // 01: yMMM -> "MMM y"
185 UnicodeString("13/1/1999"), // 02: yMd -> "d/M/y"
186 UnicodeString("13 ene 1999"), // 03: yMMMd -> "d MMM y"
187 UnicodeString("13/1"), // 04: Md -> "d/M"
188 UnicodeString("13 ene"), // 05: MMMd -> "d MMM"
189 UnicodeString("13 de enero"), // 06: MMMMd -> "d 'de' MMMM"
190 UnicodeString("T1 1999"), // 07: yQQQ -> "QQQ y"
3d1f044b 191 CharsToUnicodeString("11:58 p.\\u00A0m."), // 08: hhmm -> "hh:mm a"
4388f060
A
192 UnicodeString("23:58"), // 09: HHmm -> "HH:mm"
193 UnicodeString("23:58"), // 10: jjmm -> "HH:mm"
194 UnicodeString("58:59"), // 11: mmss -> "mm:ss"
195 UnicodeString("enero de 1999"), // 12: yyyyMMMM -> "MMMM 'de' yyyy"
b331163b 196 CharsToUnicodeString("mi\\u00E9, 13 ene"), // 13: MMMEd -> "E d MMM"
4388f060
A
197 CharsToUnicodeString("mi\\u00E9 13"), // 14: Ed -> "EEE d"
198 UnicodeString("23:58:59,123"), // 15: jmmssSSS -> "H:mm:ss,SSS"
57a6839d 199 UnicodeString("23:58"), // 16: JJmm
340931cb 200 };
4388f060 201
340931cb 202 UnicodeString patternResults_ja[] = {
4388f060 203 // ja // 5 ja
729e4ab9
A
204 UnicodeString("1999/1"), // 00: yM -> y/M
205 CharsToUnicodeString("1999\\u5E741\\u6708"), // 01: yMMM -> y\u5E74M\u6708
206 UnicodeString("1999/1/13"), // 02: yMd -> y/M/d
207 CharsToUnicodeString("1999\\u5E741\\u670813\\u65E5"), // 03: yMMMd -> y\u5E74M\u6708d\u65E5
208 UnicodeString("1/13"), // 04: Md -> M/d
209 CharsToUnicodeString("1\\u670813\\u65E5"), // 05: MMMd -> M\u6708d\u65E5
4388f060 210 CharsToUnicodeString("1\\u670813\\u65E5"), // 06: MMMMd -> M\u6708d\u65E5
57a6839d 211 CharsToUnicodeString("1999/Q1"), // 07: yQQQ -> y/QQQ
4388f060
A
212 CharsToUnicodeString("\\u5348\\u5F8C11:58"), // 08: hhmm
213 UnicodeString("23:58"), // 09: HHmm -> HH:mm
214 UnicodeString("23:58"), // 10: jjmm
215 UnicodeString("58:59"), // 11: mmss -> mm:ss
216 CharsToUnicodeString("1999\\u5E741\\u6708"), // 12: yyyyMMMM -> y\u5E74M\u6708
2ca993e8
A
217 CharsToUnicodeString("1\\u670813\\u65E5(\\u6C34)"), // 13: MMMEd -> M\u6708d\u65E5(E)
218 CharsToUnicodeString("13\\u65E5(\\u6C34)"), // 14: Ed -> d\u65E5(E)
4388f060 219 UnicodeString("23:58:59.123"), // 15: jmmssSSS -> "H:mm:ss.SSS"
57a6839d 220 UnicodeString("23:58"), // 16: JJmm
340931cb 221 };
4388f060 222
340931cb 223 UnicodeString patternResults_ja_japanese[] = {
4388f060 224 // ja@calendar=japanese // 6 ja@calendar=japanese
3d1f044b 225 UnicodeString("H11/01"), // 00: yM -> GGGGGy/MM
729e4ab9 226 CharsToUnicodeString("\\u5E73\\u621011\\u5E741\\u6708"), // 01: yMMM -> Gy\u5E74M\u6708
3d1f044b 227 UnicodeString("H11/01/13"), // 02: yMd -> GGGGGy/MM/dd
729e4ab9 228 CharsToUnicodeString("\\u5E73\\u621011\\u5E741\\u670813\\u65E5"), // 03: yMMMd -> Gy\u5E74M\u6708d\u65E5
3d1f044b 229 UnicodeString("1/13"), // 04: Md -> M/dd
729e4ab9 230 CharsToUnicodeString("1\\u670813\\u65E5"), // 05: MMMd -> M\u6708d\u65E5
4388f060 231 CharsToUnicodeString("1\\u670813\\u65E5"), // 06: MMMMd -> M\u6708d\u65E5
b331163b 232 CharsToUnicodeString("\\u5E73\\u621011/Q1"), // 07: yQQQ -> Gy/QQQ
4388f060
A
233 CharsToUnicodeString("\\u5348\\u5F8C11:58"), // 08: hhmm ->
234 UnicodeString("23:58"), // 09: HHmm -> HH:mm (as for ja)
235 UnicodeString("23:58"), // 10: jjmm
236 UnicodeString("58:59"), // 11: mmss -> mm:ss (as for ja)
237 CharsToUnicodeString("\\u5E73\\u621011\\u5E741\\u6708"), // 12: yyyyMMMM -> Gyyyy\u5E74M\u6708
2ca993e8
A
238 CharsToUnicodeString("1\\u670813\\u65E5(\\u6C34)"), // 13: MMMEd -> M\u6708d\u65E5(E)
239 CharsToUnicodeString("13\\u65E5(\\u6C34)"), // 14: Ed -> d\u65E5(E)
4388f060 240 UnicodeString("23:58:59.123"), // 15: jmmssSSS -> "H:mm:ss.SSS"
57a6839d 241 UnicodeString("23:58"), // 16: JJmm
340931cb 242 };
4388f060 243
340931cb 244 UnicodeString patternResults_zh_Hans_CN[] = {
4388f060 245 // zh_Hans_CN // 7 zh_Hans_CN
b331163b 246 CharsToUnicodeString("1999\\u5E741\\u6708"), // 00: yM -> y\u5E74M\u6708
729e4ab9 247 CharsToUnicodeString("1999\\u5E741\\u6708"), // 01: yMMM -> yyyy\u5E74MMM (fixed expected result per ticket:6626:)
51004dcb 248 CharsToUnicodeString("1999/1/13"), // 02: yMd
729e4ab9 249 CharsToUnicodeString("1999\\u5E741\\u670813\\u65E5"), // 03: yMMMd -> yyyy\u5E74MMMd\u65E5 (fixed expected result per ticket:6626:)
51004dcb 250 UnicodeString("1/13"), // 04: Md
4388f060
A
251 CharsToUnicodeString("1\\u670813\\u65E5"), // 05: MMMd -> M\u6708d\u65E5 (fixed expected result per ticket:6626:)
252 CharsToUnicodeString("1\\u670813\\u65E5"), // 06: MMMMd -> M\u6708d\u65E5
51004dcb 253 CharsToUnicodeString("1999\\u5E74\\u7B2C1\\u5B63\\u5EA6"), // 07: yQQQ
4388f060
A
254 CharsToUnicodeString("\\u4E0B\\u534811:58"), // 08: hhmm
255 UnicodeString("23:58"), // 09: HHmm
256 CharsToUnicodeString("\\u4E0B\\u534811:58"), // 10: jjmm
257 UnicodeString("58:59"), // 11: mmss
258 CharsToUnicodeString("1999\\u5E741\\u6708"), // 12: yyyyMMMM -> yyyy\u5E74MMM
57a6839d
A
259 CharsToUnicodeString("1\\u670813\\u65E5 \\u5468\\u4E09"), // 13: MMMEd -> MMMd\u65E5 EEE
260 CharsToUnicodeString("13 \\u5468\\u4E09"), // 14: Ed -> d\u65E5EEE
4388f060 261 CharsToUnicodeString("\\u4E0B\\u534811:58:59.123"), // 15: jmmssSSS -> "ah:mm:ss.SSS"
57a6839d 262 UnicodeString("11:58"), // 16: JJmm
340931cb 263 };
4388f060 264
340931cb 265 UnicodeString patternResults_zh_TW_roc[] = {
2ca993e8 266 // zh_TW@calendar=roc // 8 zh_TW@calendar=roc
3d1f044b
A
267 CharsToUnicodeString("\\u6C11\\u570B 88/1"), // 00: yM -> G y/M
268 CharsToUnicodeString("\\u6C11\\u570B 88\\u5E741\\u6708"), // 01: yMMM -> G y\u5E74M\u6708
269 CharsToUnicodeString("\\u6C11\\u570B 88/1/13"), // 02: yMd -> G y/M/d
270 CharsToUnicodeString("\\u6C11\\u570B 88\\u5E741\\u670813\\u65E5"), // 03: yMMMd -> G y\u5E74M\u6708d\u65E5
729e4ab9
A
271 UnicodeString("1/13"), // 04: Md -> M/d
272 CharsToUnicodeString("1\\u670813\\u65E5"), // 05: MMMd ->M\u6708d\u65E5
4388f060 273 CharsToUnicodeString("1\\u670813\\u65E5"), // 06: MMMMd ->M\u6708d\u65E5
3d1f044b 274 CharsToUnicodeString("\\u6C11\\u570B 88\\u5E741\\u5B63"), // 07: yQQQ -> G yQQQ
4388f060
A
275 CharsToUnicodeString("\\u4E0B\\u534811:58"), // 08: hhmm ->
276 UnicodeString("23:58"), // 09: HHmm ->
277 CharsToUnicodeString("\\u4E0B\\u534811:58"), // 10: jjmm
278 UnicodeString("58:59"), // 11: mmss ->
3d1f044b 279 CharsToUnicodeString("\\u6C11\\u570B 88\\u5E741\\u6708"), // 12: yyyyMMMM -> G y\u5E74M\u670
57a6839d
A
280 CharsToUnicodeString("1\\u670813\\u65E5 \\u9031\\u4E09"), // 13: MMMEd -> M\u6708d\u65E5 E
281 CharsToUnicodeString("13 \\u9031\\u4E09"), // 14: Ed -> d E
4388f060 282 CharsToUnicodeString("\\u4E0B\\u534811:58:59.123"), // 15: jmmssSSS -> "ah:mm:ss.SSS"
57a6839d 283 UnicodeString("11:58"), // 16: JJmm
340931cb 284 };
4388f060 285
340931cb 286 UnicodeString patternResults_ru[] = {
4388f060
A
287 // ru // 9 ru
288 UnicodeString("01.1999"), // 00: yM -> MM.y
340931cb 289 CharsToUnicodeString("\\u044F\\u043D\\u0432. 1999\\u00A0\\u0433."), // 01: yMMM -> LLL y
51004dcb 290 UnicodeString("13.01.1999"), // 02: yMd -> dd.MM.y
340931cb 291 CharsToUnicodeString("13 \\u044F\\u043D\\u0432. 1999\\u00A0\\u0433."), // 03: yMMMd -> d MMM y
51004dcb 292 UnicodeString("13.01"), // 04: Md -> dd.MM
729e4ab9 293 CharsToUnicodeString("13 \\u044F\\u043D\\u0432."), // 05: MMMd -> d MMM
4388f060 294 CharsToUnicodeString("13 \\u044F\\u043D\\u0432\\u0430\\u0440\\u044F"), // 06: MMMMd -> d MMMM
340931cb 295 CharsToUnicodeString("1-\\u0439 \\u043A\\u0432. 1999\\u00A0\\u0433."), // 07: yQQQ -> y QQQ
3d1f044b 296 CharsToUnicodeString("11:58 PM"), // 08: hhmm -> hh:mm a
4388f060
A
297 UnicodeString("23:58"), // 09: HHmm -> HH:mm
298 UnicodeString("23:58"), // 10: jjmm -> HH:mm
299 UnicodeString("58:59"), // 11: mmss -> mm:ss
340931cb
A
300 CharsToUnicodeString("\\u044F\\u043D\\u0432\\u0430\\u0440\\u044C 1999\\u00A0\\u0433."), // 12: yyyyMMMM -> LLLL y
301 CharsToUnicodeString("\\u0421\\u0440, 13 \\u044F\\u043D\\u0432."), // 13: MMMEd -> ccc, d MMM
302 CharsToUnicodeString("\\u0421\\u0440, 13"), // 14: Ed -> EEE, d
4388f060 303 UnicodeString("23:58:59,123"), // 15: jmmssSSS -> "H:mm:ss,SSS"
57a6839d 304 UnicodeString("23:58"), // 16: JJmm
340931cb
A
305 };
306
307 UnicodeString patternResults_zh_chinese[] = {
308 // zh@calendar=chinese // 10 zh@calendar=chinese
309 CharsToUnicodeString("1998\\u620A\\u5BC5\\u5E74\\u51AC\\u6708"), // 00: yMMM
310 CharsToUnicodeString("1998\\u620A\\u5BC5\\u5E74\\u51AC\\u6708"), // 01: yMMM
311 CharsToUnicodeString("1998\\u5E74\\u51AC\\u670826"), // 02: yMMMd
312 CharsToUnicodeString("1998\\u5E74\\u51AC\\u670826"), // 03: yMMMd
313 UnicodeString("11-26"), // 04: Md
314 CharsToUnicodeString("\\u51AC\\u670826"), // 05: MMMd
315 CharsToUnicodeString("\\u51AC\\u670826"), // 06: MMMMd
316 CharsToUnicodeString("1998\\u620A\\u5BC5\\u5E74\\u7b2c\\u56db\\u5B63\\u5EA6"), // 07: yQQQ
317 CharsToUnicodeString("\\u4E0B\\u534811:58"), // 08: hhmm
318 UnicodeString("23:58"), // 09: HHmm
319 CharsToUnicodeString("\\u4E0B\\u534811:58"), // 10: jjmm
320 UnicodeString("58:59"), // 11: mmss
321 CharsToUnicodeString("1998\\u620A\\u5BC5\\u5E74\\u51AC\\u6708"), // 12: yyyyMMMM
322 CharsToUnicodeString("\\u51AC\\u670826\\u5468\\u4E09"), // 13: MMMEd
323 CharsToUnicodeString("26\\u5468\\u4E09"), // 14: Ed -> dEEE
324 CharsToUnicodeString("\\u4E0B\\u534811:58:59.123"), // 15: jmmssSS
325 UnicodeString("11:58"), // 16: JJmm
326 };
4388f060 327
340931cb
A
328 UnicodeString patternResults_ja_jp_traditional[] = { // 11
329 // ja_JP_TRADITIONAL // 11 ja_JP_TRADITIONAL
330 u"AD1999/01", // 00: yM
331 u"西暦1999年1月", // 01: yMMM
332 u"1999年1月13日", // 02: yMd
333 u"西暦1999年1月13日", // 03: yMMMd
334 u"1/13", // 04: Md
335 u"1月13日", // 05: MMMd
336 u"1月13日", // 06: MMMMd
337 u"西暦1999/Q1", // 07: yQQQ
338 u"午後11:58", // 08: hhmm
339 u"23:58", // 09: HHmm
340 u"23:58", // 10: jjmm
341 u"58:59", // 11: mmss
342 u"西暦1999年1月", // 12: yyyyMMMM
343 u"1月13日(水)", // 13: MMMEd
344 u"13日(水)", // 14: Ed
345 u"23:58:59.123", // 15: jmmssSSS
346 u"23:58", // 16: JJmm
347 };
348
349 UnicodeString patternResults_zh_chinese_hanidays[] = { // 12 Apple add
57a6839d
A
350 // zh@calendar=chinese,numbers=hanidays // 10 zh@calendar=chinese,numbers=hanidays
351 CharsToUnicodeString("1998\\u620A\\u5BC5\\u5E74\\u51AC\\u6708"), // 00: yMMM
352 CharsToUnicodeString("1998\\u620A\\u5BC5\\u5E74\\u51AC\\u6708"), // 01: yMMM
353 CharsToUnicodeString("1998\\u5E74\\u51AC\\u6708\\u5EFF\\u516D"), // 02: yMMMd
354 CharsToUnicodeString("1998\\u5E74\\u51AC\\u6708\\u5EFF\\u516D"), // 03: yMMMd
355 CharsToUnicodeString("11-\\u5EFF\\u516D"), // 04: Md // hmm
356 CharsToUnicodeString("\\u51AC\\u6708\\u5EFF\\u516D"), // 05: MMMd
357 CharsToUnicodeString("\\u51AC\\u6708\\u5EFF\\u516D"), // 06: MMMMd
358 CharsToUnicodeString("1998\\u620A\\u5BC5\\u5E74\\u7b2c\\u56db\\u5B63\\u5EA6"), // 07: yQQQ
4388f060
A
359 CharsToUnicodeString("\\u4E0B\\u534811:58"), // 08: hhmm
360 UnicodeString("23:58"), // 09: HHmm
361 CharsToUnicodeString("\\u4E0B\\u534811:58"), // 10: jjmm
362 UnicodeString("58:59"), // 11: mmss
57a6839d
A
363 CharsToUnicodeString("1998\\u620A\\u5BC5\\u5E74\\u51AC\\u6708"), // 12: yyyyMMMM
364 CharsToUnicodeString("\\u51AC\\u6708\\u5EFF\\u516D\\u5468\\u4E09"), // 13: MMMEd
365 CharsToUnicodeString("\\u5EFF\\u516D\\u5468\\u4E09"), // 14: Ed -> dE
4388f060 366 CharsToUnicodeString("\\u4E0B\\u534811:58:59.123"), // 15: jmmssSS
57a6839d 367 UnicodeString("11:58"), // 16: JJmm
340931cb 368 };
46f4442e 369
340931cb 370 UnicodeString patternResults_ar[] = { // 13 Apple add
f3c0d7a5
A
371 // ar // 11 ar, for Weds, Jan 13, 1999, 23:58:59
372 CharsToUnicodeString("\\u0661\\u200F/\\u0661\\u0669\\u0669\\u0669"), // 00: yM
373 CharsToUnicodeString("\\u064A\\u0646\\u0627\\u064A\\u0631 \\u0661\\u0669\\u0669\\u0669"), // 01: yMMM
374 CharsToUnicodeString("\\u0661\\u0663\\u200F/\\u0661\\u200F/\\u0661\\u0669\\u0669\\u0669"), // 02: yMd
375 CharsToUnicodeString("\\u0661\\u0663 \\u064A\\u0646\\u0627\\u064A\\u0631\\u060C \\u0661\\u0669\\u0669\\u0669"), // 03: yMMMd
376 CharsToUnicodeString("\\u0661\\u0663/\\u200F\\u0661"), // 04: Md
377 CharsToUnicodeString("\\u0661\\u0663 \\u064A\\u0646\\u0627\\u064A\\u0631"), // 05: MMMd
378 CharsToUnicodeString("\\u0661\\u0663 \\u064A\\u0646\\u0627\\u064A\\u0631"), // 06: MMMMd
379 CharsToUnicodeString("\\u0627\\u0644\\u0631\\u0628\\u0639 \\u0627\\u0644\\u0623\\u0648\\u0644 \\u0661\\u0669\\u0669\\u0669"), // 07: yQQQ
380 CharsToUnicodeString("\\u0661\\u0661:\\u0665\\u0668\\u00A0\\u0645"), // 08: hhmm
381 CharsToUnicodeString("\\u0662\\u0663:\\u0665\\u0668"), // 09: HHmm
382 CharsToUnicodeString("\\u0661\\u0661:\\u0665\\u0668\\u00A0\\u0645"), // 10: jjmm
383 CharsToUnicodeString("\\u0665\\u0668:\\u0665\\u0669"), // 11: mmss
384 CharsToUnicodeString("\\u064A\\u0646\\u0627\\u064A\\u0631 \\u0661\\u0669\\u0669\\u0669"), // 12: yyyyMMMM
385 CharsToUnicodeString("\\u0623\\u0631\\u0628\\u0639\\u0627\\u0621\\u060C \\u0661\\u0663 \\u064A\\u0646\\u0627\\u064A\\u0631"), // 13: MMMEd
386 CharsToUnicodeString("\\u0623\\u0631\\u0628\\u0639\\u0627\\u0621\\u060C \\u0661\\u0663"), // 14: Ed
387 CharsToUnicodeString("\\u0661\\u0661:\\u0665\\u0668:\\u0665\\u0669\\u066B\\u0661\\u0662\\u0663\\u00A0\\u0645"), // 15: jmmssSSS
388 CharsToUnicodeString("\\u0661\\u0661:\\u0665\\u0668"), // 16: JJmm
340931cb 389 };
f3c0d7a5 390
340931cb
A
391 UnicodeString patternResults_en_ID_buddhist[] = { // 14 Apple add <rdar://problem/37505940>
392 // en_ID@calendar=buddhist // 14 en_ID@calendar=buddhist
393 u"01/2542 BE", // 00: yM
394 u"Jan 2542 BE", // 01: yMMM
395 u"13/01/2542 BE", // 02: yMd
396 u"13 Jan 2542 BE", // 03: yMMMd
397 u"13/01", // 04: Md
398 u"13 Jan", // 05: MMMd
399 u"13 January", // 06: MMMMd
400 u"Q1 2542 BE", // 07: yQQQ
401 u"11.58 PM", // 08: hhmm
402 u"23.58", // 09: HHmm
403 u"23.58", // 10: jjmm
404 u"58.59", // 11: mmss
405 u"January 2542 BE", // 12: yyyyMMMM
406 u"Wed, 13 Jan", // 13: MMMEd
407 u"Wed 13", // 14: Ed
408 u"23.58.59,123", // 15: jmmssSSS
409 u"23.58", // 16: JJmm
410 };
411
412 UnicodeString* patternResults[] = {
413 patternResults_en_US, // 0
414 patternResults_en_US_japanese, // 1
415 patternResults_de_DE, // 2
416 patternResults_fi, // 3
417 patternResults_es, // 4
418 patternResults_ja, // 5
419 patternResults_ja_japanese, // 6
420 patternResults_zh_Hans_CN, // 7
421 patternResults_zh_TW_roc, // 8
422 patternResults_ru, // 9
423 patternResults_zh_chinese, // 10
424 patternResults_ja_jp_traditional, // 11
425 patternResults_zh_chinese_hanidays, // 12 Apple add
426 patternResults_ar, // 13 Apple add
427 patternResults_en_ID_buddhist, // 14 Apple add
46f4442e
A
428 };
429
430 UnicodeString patternTests2[] = {
431 UnicodeString("yyyyMMMdd"),
729e4ab9 432 UnicodeString("yyyyqqqq"),
46f4442e
A
433 UnicodeString("yMMMdd"),
434 UnicodeString("EyyyyMMMdd"),
435 UnicodeString("yyyyMMdd"),
436 UnicodeString("yyyyMMM"),
437 UnicodeString("yyyyMM"),
438 UnicodeString("yyMM"),
439 UnicodeString("yMMMMMd"),
440 UnicodeString("EEEEEMMMMMd"),
441 UnicodeString("MMMd"),
442 UnicodeString("MMMdhmm"),
443 UnicodeString("EMMMdhmms"),
444 UnicodeString("MMdhmm"),
445 UnicodeString("EEEEMMMdhmms"),
446 UnicodeString("yyyyMMMddhhmmss"),
447 UnicodeString("EyyyyMMMddhhmmss"),
448 UnicodeString("hmm"),
449 UnicodeString("hhmm"),
729e4ab9 450 UnicodeString("hhmmVVVV"),
46f4442e
A
451 UnicodeString(""),
452 };
453 UnicodeString patternResults2[] = {
454 UnicodeString("Oct 14, 1999"),
729e4ab9 455 UnicodeString("4th quarter 1999"),
46f4442e
A
456 UnicodeString("Oct 14, 1999"),
457 UnicodeString("Thu, Oct 14, 1999"),
458 UnicodeString("10/14/1999"),
459 UnicodeString("Oct 1999"),
460 UnicodeString("10/1999"),
461 UnicodeString("10/99"),
462 UnicodeString("O 14, 1999"),
463 UnicodeString("T, O 14"),
464 UnicodeString("Oct 14"),
51004dcb
A
465 UnicodeString("Oct 14, 6:58 AM"),
466 UnicodeString("Thu, Oct 14, 6:58:59 AM"),
467 UnicodeString("10/14, 6:58 AM"),
468 UnicodeString("Thursday, Oct 14, 6:58:59 AM"),
469 UnicodeString("Oct 14, 1999, 6:58:59 AM"),
470 UnicodeString("Thu, Oct 14, 1999, 6:58:59 AM"),
46f4442e 471 UnicodeString("6:58 AM"),
729e4ab9 472 UnicodeString("6:58 AM"),
4388f060 473 UnicodeString("6:58 AM GMT"),
46f4442e
A
474 UnicodeString(""),
475 };
2ca993e8 476
46f4442e 477 // results for getSkeletons() and getPatternForSkeleton()
2ca993e8
A
478 const UnicodeString testSkeletonsResults[] = {
479 UnicodeString("HH:mm"),
480 UnicodeString("MMMMd"),
481 UnicodeString("MMMMMdd"),
46f4442e 482 };
2ca993e8
A
483
484 const UnicodeString testBaseSkeletonsResults[] = {
485 UnicodeString("Hm"),
486 UnicodeString("MMMMd"),
4388f060 487 UnicodeString("MMMMMd"),
46f4442e
A
488 };
489
0f5d89e8
A
490 const char* testGetSkeletonAndBase[][3] = {
491 // pattern skeleton baseSkeleton
492 { "dd-MMM", "MMMdd", "MMMd" },
493 { "dd/MMMM/yy", "yyMMMMdd", "yMMMMd" },
494 { "h", "h", "h" },
495 { "ah", "ah", "ah" },
496 { "aaaah", "aaaah", "aaaah" },
497 { "Bh", "Bh", "Bh" }
498 };
499
46f4442e
A
500 UnicodeString newDecimal(" "); // space
501 UnicodeString newAppendItemName("hrs.");
502 UnicodeString newAppendItemFormat("{1} {0}");
503 UnicodeString newDateTimeFormat("{1} {0}");
504 UErrorCode status = U_ZERO_ERROR;
505 UnicodeString conflictingPattern;
51004dcb
A
506 UDateTimePatternConflict conflictingStatus = UDATPG_NO_CONFLICT;
507 (void)conflictingStatus; // Suppress set but not used warning.
46f4442e
A
508
509 // ======= Test CreateInstance with default locale
510 logln("Testing DateTimePatternGenerator createInstance from default locale");
2ca993e8 511
46f4442e
A
512 DateTimePatternGenerator *instFromDefaultLocale=DateTimePatternGenerator::createInstance(status);
513 if (U_FAILURE(status)) {
514 dataerrln("ERROR: Could not create DateTimePatternGenerator (default) - exitting");
515 return;
516 }
517 else {
518 delete instFromDefaultLocale;
519 }
520
2ca993e8 521 // ======= Test CreateInstance with given locale
46f4442e
A
522 logln("Testing DateTimePatternGenerator createInstance from French locale");
523 status = U_ZERO_ERROR;
524 DateTimePatternGenerator *instFromLocale=DateTimePatternGenerator::createInstance(Locale::getFrench(), status);
525 if (U_FAILURE(status)) {
526 dataerrln("ERROR: Could not create DateTimePatternGenerator (Locale::getFrench()) - exitting");
527 return;
528 }
529
2ca993e8 530 // ======= Test clone DateTimePatternGenerator
46f4442e
A
531 logln("Testing DateTimePatternGenerator::clone()");
532 status = U_ZERO_ERROR;
2ca993e8 533
46f4442e
A
534
535 UnicodeString decimalSymbol = instFromLocale->getDecimal();
536 UnicodeString newDecimalSymbol = UnicodeString("*");
537 decimalSymbol = instFromLocale->getDecimal();
538 instFromLocale->setDecimal(newDecimalSymbol);
539 DateTimePatternGenerator *cloneDTPatternGen=instFromLocale->clone();
540 decimalSymbol = cloneDTPatternGen->getDecimal();
541 if (decimalSymbol != newDecimalSymbol) {
542 errln("ERROR: inconsistency is found in cloned object.");
543 }
544 if ( !(*cloneDTPatternGen == *instFromLocale) ) {
545 errln("ERROR: inconsistency is found in cloned object.");
546 }
2ca993e8 547
46f4442e
A
548 if ( *cloneDTPatternGen != *instFromLocale ) {
549 errln("ERROR: inconsistency is found in cloned object.");
550 }
2ca993e8 551
46f4442e
A
552 delete instFromLocale;
553 delete cloneDTPatternGen;
2ca993e8
A
554
555 // ======= Test simple use cases
46f4442e
A
556 logln("Testing simple use cases");
557 status = U_ZERO_ERROR;
558 Locale deLocale=Locale::getGermany();
559 UDate sampleDate=LocaleTest::date(99, 9, 13, 23, 58, 59);
560 DateTimePatternGenerator *gen = DateTimePatternGenerator::createInstance(deLocale, status);
561 if (U_FAILURE(status)) {
562 dataerrln("ERROR: Could not create DateTimePatternGenerator (Locale::getGermany()) - exitting");
563 return;
564 }
565 UnicodeString findPattern = gen->getBestPattern(UnicodeString("MMMddHmm"), status);
566 SimpleDateFormat *format = new SimpleDateFormat(findPattern, deLocale, status);
567 if (U_FAILURE(status)) {
568 dataerrln("ERROR: Could not create SimpleDateFormat (Locale::getGermany())");
569 delete gen;
570 return;
571 }
572 TimeZone *zone = TimeZone::createTimeZone(UnicodeString("ECT"));
573 if (zone==NULL) {
574 dataerrln("ERROR: Could not create TimeZone ECT");
575 delete gen;
576 delete format;
577 return;
578 }
579 format->setTimeZone(*zone);
580 UnicodeString dateReturned, expectedResult;
581 dateReturned.remove();
582 dateReturned = format->format(sampleDate, dateReturned, status);
b331163b 583 expectedResult=UnicodeString("14. Okt., 08:58", -1, US_INV);
46f4442e
A
584 if ( dateReturned != expectedResult ) {
585 errln("ERROR: Simple test in getBestPattern with Locale::getGermany()).");
586 }
587 // add new pattern
588 status = U_ZERO_ERROR;
2ca993e8 589 conflictingStatus = gen->addPattern(UnicodeString("d'. von' MMMM", -1, US_INV), true, conflictingPattern, status);
46f4442e
A
590 if (U_FAILURE(status)) {
591 errln("ERROR: Could not addPattern - d\'. von\' MMMM");
592 }
593 status = U_ZERO_ERROR;
594 UnicodeString testPattern=gen->getBestPattern(UnicodeString("MMMMdd"), status);
595 testPattern=gen->getBestPattern(UnicodeString("MMMddHmm"), status);
729e4ab9 596 format->applyPattern(gen->getBestPattern(UnicodeString("MMMMdHmm"), status));
46f4442e
A
597 dateReturned.remove();
598 dateReturned = format->format(sampleDate, dateReturned, status);
b331163b 599 expectedResult=UnicodeString("14. von Oktober, 08:58", -1, US_INV);
46f4442e 600 if ( dateReturned != expectedResult ) {
729e4ab9 601 errln(UnicodeString("ERROR: Simple test addPattern failed!: d\'. von\' MMMM Got: ") + dateReturned + UnicodeString(" Expected: ") + expectedResult);
46f4442e
A
602 }
603 delete format;
2ca993e8 604
46f4442e 605 // get a pattern and modify it
2ca993e8 606 format = (SimpleDateFormat *)DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull,
46f4442e
A
607 deLocale);
608 format->setTimeZone(*zone);
609 UnicodeString pattern;
610 pattern = format->toPattern(pattern);
611 dateReturned.remove();
612 dateReturned = format->format(sampleDate, dateReturned, status);
b331163b 613 expectedResult=CharsToUnicodeString("Donnerstag, 14. Oktober 1999 um 08:58:59 Mitteleurop\\u00E4ische Sommerzeit");
46f4442e
A
614 if ( dateReturned != expectedResult ) {
615 errln("ERROR: Simple test uses full date format.");
616 errln(UnicodeString(" Got: ") + dateReturned + UnicodeString(" Expected: ") + expectedResult);
617 }
2ca993e8
A
618
619 // modify it to change the zone.
46f4442e
A
620 UnicodeString newPattern = gen->replaceFieldTypes(pattern, UnicodeString("vvvv"), status);
621 format->applyPattern(newPattern);
622 dateReturned.remove();
623 dateReturned = format->format(sampleDate, dateReturned, status);
b331163b 624 expectedResult=CharsToUnicodeString("Donnerstag, 14. Oktober 1999 um 08:58:59 Mitteleurop\\u00E4ische Zeit");
46f4442e
A
625 if ( dateReturned != expectedResult ) {
626 errln("ERROR: Simple test modify the timezone!");
627 errln(UnicodeString(" Got: ")+ dateReturned + UnicodeString(" Expected: ") + expectedResult);
628 }
2ca993e8 629
46f4442e
A
630 // setDeciaml(), getDeciaml()
631 gen->setDecimal(newDecimal);
632 if (newDecimal != gen->getDecimal()) {
633 errln("ERROR: unexpected result from setDecimal() and getDecimal()!.\n");
634 }
2ca993e8 635
46f4442e
A
636 // setAppenItemName() , getAppendItemName()
637 gen->setAppendItemName(UDATPG_HOUR_FIELD, newAppendItemName);
638 if (newAppendItemName != gen->getAppendItemName(UDATPG_HOUR_FIELD)) {
639 errln("ERROR: unexpected result from setAppendItemName() and getAppendItemName()!.\n");
640 }
2ca993e8 641
46f4442e
A
642 // setAppenItemFormat() , getAppendItemFormat()
643 gen->setAppendItemFormat(UDATPG_HOUR_FIELD, newAppendItemFormat);
644 if (newAppendItemFormat != gen->getAppendItemFormat(UDATPG_HOUR_FIELD)) {
645 errln("ERROR: unexpected result from setAppendItemFormat() and getAppendItemFormat()!.\n");
646 }
2ca993e8 647
46f4442e
A
648 // setDateTimeFormat() , getDateTimeFormat()
649 gen->setDateTimeFormat(newDateTimeFormat);
650 if (newDateTimeFormat != gen->getDateTimeFormat()) {
651 errln("ERROR: unexpected result from setDateTimeFormat() and getDateTimeFormat()!.\n");
652 }
2ca993e8 653
46f4442e 654 // ======== Test getSkeleton and getBaseSkeleton
0f5d89e8
A
655
656 int32_t i, count = UPRV_LENGTHOF(testGetSkeletonAndBase);
657 for (i = 0; i < count; i++) {
658 status = U_ZERO_ERROR;
659 pattern = UnicodeString(testGetSkeletonAndBase[i][0]);
660 UnicodeString expectedSkeleton = UnicodeString(testGetSkeletonAndBase[i][1]);
661 UnicodeString expectedBaseSkeleton = UnicodeString(testGetSkeletonAndBase[i][2]);
662 UnicodeString retSkeleton = gen->getSkeleton(pattern, status);
663 if(U_FAILURE(status) || retSkeleton != expectedSkeleton ) {
664 errln("ERROR: Unexpected result from getSkeleton().\n");
665 errln(UnicodeString(" Got: ") + retSkeleton + UnicodeString(" Expected: ") + expectedSkeleton );
666 }
667 retSkeleton = gen->getBaseSkeleton(pattern, status);
668 if(U_FAILURE(status) || retSkeleton != expectedBaseSkeleton) {
669 errln("ERROR: Unexpected result from getBaseSkeleton().\n");
670 errln(UnicodeString(" Got: ") + retSkeleton + UnicodeString(" Expected:")+ expectedBaseSkeleton);
671 }
46f4442e
A
672 }
673
46f4442e
A
674 delete format;
675 delete zone;
676 delete gen;
2ca993e8 677
46f4442e
A
678 {
679 // Trac# 6104
680 status = U_ZERO_ERROR;
681 pattern = UnicodeString("YYYYMMM");
682 UnicodeString expR = CharsToUnicodeString("1999\\u5E741\\u6708"); // fixed expected result per ticket:6626:
683 Locale loc("ja");
684 UDate testDate1= LocaleTest::date(99, 0, 13, 23, 58, 59);
685 DateTimePatternGenerator *patGen=DateTimePatternGenerator::createInstance(loc, status);
686 if(U_FAILURE(status)) {
687 dataerrln("ERROR: Could not create DateTimePatternGenerator");
688 return;
689 }
690 UnicodeString bPattern = patGen->getBestPattern(pattern, status);
691 UnicodeString rDate;
692 SimpleDateFormat sdf(bPattern, loc, status);
693 rDate.remove();
694 rDate = sdf.format(testDate1, rDate);
695
696 logln(UnicodeString(" ja locale with skeleton: YYYYMMM Best Pattern:") + bPattern);
697 logln(UnicodeString(" Formatted date:") + rDate);
698
699 if ( expR!= rDate ) {
2ca993e8 700 errln(UnicodeString("\nERROR: Test Japanese month hack Got: ") + rDate +
46f4442e
A
701 UnicodeString(" Expected: ") + expR );
702 }
2ca993e8 703
46f4442e
A
704 delete patGen;
705 }
706 { // Trac# 6104
707 Locale loc("zh");
708 UnicodeString expR = CharsToUnicodeString("1999\\u5E741\\u6708"); // fixed expected result per ticket:6626:
709 UDate testDate1= LocaleTest::date(99, 0, 13, 23, 58, 59);
710 DateTimePatternGenerator *patGen=DateTimePatternGenerator::createInstance(loc, status);
711 if(U_FAILURE(status)) {
712 dataerrln("ERROR: Could not create DateTimePatternGenerator");
713 return;
714 }
715 UnicodeString bPattern = patGen->getBestPattern(pattern, status);
716 UnicodeString rDate;
717 SimpleDateFormat sdf(bPattern, loc, status);
718 rDate.remove();
719 rDate = sdf.format(testDate1, rDate);
720
721 logln(UnicodeString(" zh locale with skeleton: YYYYMMM Best Pattern:") + bPattern);
722 logln(UnicodeString(" Formatted date:") + rDate);
723 if ( expR!= rDate ) {
2ca993e8 724 errln(UnicodeString("\nERROR: Test Chinese month hack Got: ") + rDate +
46f4442e
A
725 UnicodeString(" Expected: ") + expR );
726 }
2ca993e8 727 delete patGen;
46f4442e
A
728 }
729
730 {
731 // Trac# 6172 duplicate time pattern
732 status = U_ZERO_ERROR;
733 pattern = UnicodeString("hmv");
734 UnicodeString expR = UnicodeString("h:mm a v"); // avail formats has hm -> "h:mm a" (fixed expected result per ticket:6626:)
735 Locale loc("en");
736 DateTimePatternGenerator *patGen=DateTimePatternGenerator::createInstance(loc, status);
737 if(U_FAILURE(status)) {
738 dataerrln("ERROR: Could not create DateTimePatternGenerator");
739 return;
740 }
741 UnicodeString bPattern = patGen->getBestPattern(pattern, status);
742 logln(UnicodeString(" en locale with skeleton: hmv Best Pattern:") + bPattern);
743
744 if ( expR!= bPattern ) {
2ca993e8 745 errln(UnicodeString("\nERROR: Test EN time format Got: ") + bPattern +
46f4442e
A
746 UnicodeString(" Expected: ") + expR );
747 }
2ca993e8 748
46f4442e
A
749 delete patGen;
750 }
2ca993e8
A
751
752
46f4442e
A
753 // ======= Test various skeletons.
754 logln("Testing DateTimePatternGenerator with various skeleton");
2ca993e8 755
46f4442e
A
756 status = U_ZERO_ERROR;
757 int32_t localeIndex=0;
758 int32_t resultIndex=0;
759 UnicodeString resultDate;
729e4ab9 760 UDate testDate= LocaleTest::date(99, 0, 13, 23, 58, 59) + 123.0;
46f4442e 761 while (localeIndex < MAX_LOCALE )
2ca993e8 762 {
340931cb 763 resultIndex=0;
46f4442e
A
764 int32_t dataIndex=0;
765 UnicodeString bestPattern;
2ca993e8 766
46f4442e
A
767 Locale loc(testLocale[localeIndex][0], testLocale[localeIndex][1], testLocale[localeIndex][2], testLocale[localeIndex][3]);
768 logln("\n\n Locale: %s_%s_%s@%s", testLocale[localeIndex][0], testLocale[localeIndex][1], testLocale[localeIndex][2], testLocale[localeIndex][3]);
769 DateTimePatternGenerator *patGen=DateTimePatternGenerator::createInstance(loc, status);
770 if(U_FAILURE(status)) {
771 dataerrln("ERROR: Could not create DateTimePatternGenerator with locale index:%d . - exitting\n", localeIndex);
772 return;
773 }
774 while (patternData[dataIndex].length() > 0) {
775 log(patternData[dataIndex]);
776 bestPattern = patGen->getBestPattern(patternData[dataIndex++], status);
777 logln(UnicodeString(" -> ") + bestPattern);
2ca993e8 778
46f4442e
A
779 SimpleDateFormat sdf(bestPattern, loc, status);
780 resultDate.remove();
781 resultDate = sdf.format(testDate, resultDate);
340931cb
A
782 if ( resultDate != patternResults[localeIndex][resultIndex] ) {
783 auto* calendar = sdf.getCalendar();
46f4442e 784 errln(UnicodeString("\nERROR: Test various skeletons[") + (dataIndex-1) + UnicodeString("], localeIndex ") + localeIndex +
340931cb
A
785 u". Got: \"" + resultDate +
786 u"\" with calendar " + calendar->getType() +
787 u" Expected: \"" + patternResults[localeIndex][resultIndex] + u"\"");
46f4442e 788 }
2ca993e8 789
46f4442e
A
790 resultIndex++;
791 }
792 delete patGen;
793 localeIndex++;
794 }
2ca993e8 795
46f4442e
A
796 // ======= More tests ticket#6110
797 logln("Testing DateTimePatternGenerator with various skeleton");
2ca993e8 798
46f4442e
A
799 status = U_ZERO_ERROR;
800 localeIndex=0;
801 resultIndex=0;
802 testDate= LocaleTest::date(99, 9, 13, 23, 58, 59);
2ca993e8 803 {
46f4442e
A
804 int32_t dataIndex=0;
805 UnicodeString bestPattern;
806 logln("\n\n Test various skeletons for English locale...");
807 DateTimePatternGenerator *patGen=DateTimePatternGenerator::createInstance(Locale::getEnglish(), status);
808 if(U_FAILURE(status)) {
809 dataerrln("ERROR: Could not create DateTimePatternGenerator with locale English . - exitting\n");
810 return;
811 }
812 TimeZone *enZone = TimeZone::createTimeZone(UnicodeString("ECT/GMT"));
813 if (enZone==NULL) {
814 dataerrln("ERROR: Could not create TimeZone ECT");
815 delete patGen;
816 return;
817 }
2ca993e8 818 SimpleDateFormat *enFormat = (SimpleDateFormat *)DateFormat::createDateTimeInstance(DateFormat::kFull,
46f4442e
A
819 DateFormat::kFull, Locale::getEnglish());
820 enFormat->setTimeZone(*enZone);
821 while (patternTests2[dataIndex].length() > 0) {
822 logln(patternTests2[dataIndex]);
823 bestPattern = patGen->getBestPattern(patternTests2[dataIndex], status);
824 logln(UnicodeString(" -> ") + bestPattern);
825 enFormat->applyPattern(bestPattern);
826 resultDate.remove();
827 resultDate = enFormat->format(testDate, resultDate);
828 if ( resultDate != patternResults2[resultIndex] ) {
829 errln(UnicodeString("\nERROR: Test various skeletons[") + dataIndex
2ca993e8 830 + UnicodeString("]. Got: ") + resultDate + UnicodeString(" Expected: ") +
46f4442e
A
831 patternResults2[resultIndex] );
832 }
833 dataIndex++;
834 resultIndex++;
835 }
836 delete patGen;
837 delete enZone;
838 delete enFormat;
839 }
840
841
842
2ca993e8 843 // ======= Test random skeleton
46f4442e
A
844 DateTimePatternGenerator *randDTGen= DateTimePatternGenerator::createInstance(status);
845 if (U_FAILURE(status)) {
846 dataerrln("ERROR: Could not create DateTimePatternGenerator (Locale::getFrench()) - exitting");
847 return;
848 }
849 UChar newChar;
46f4442e
A
850 for (i=0; i<10; ++i) {
851 UnicodeString randomSkeleton;
852 int32_t len = rand() % 20;
853 for (int32_t j=0; j<len; ++j ) {
854 while ((newChar = (UChar)(rand()%0x7f))>=(UChar)0x20) {
855 randomSkeleton += newChar;
856 }
857 }
858 UnicodeString bestPattern = randDTGen->getBestPattern(randomSkeleton, status);
859 }
860 delete randDTGen;
2ca993e8 861
46f4442e
A
862 // UnicodeString randomString=Unicode
863 // ======= Test getStaticClassID()
864
865 logln("Testing getStaticClassID()");
866 status = U_ZERO_ERROR;
867 DateTimePatternGenerator *test= DateTimePatternGenerator::createInstance(status);
2ca993e8 868
46f4442e
A
869 if(test->getDynamicClassID() != DateTimePatternGenerator::getStaticClassID()) {
870 errln("ERROR: getDynamicClassID() didn't return the expected value");
871 }
872 delete test;
2ca993e8 873
46f4442e 874 // ====== Test createEmptyInstance()
2ca993e8 875
46f4442e
A
876 logln("Testing createEmptyInstance()");
877 status = U_ZERO_ERROR;
2ca993e8 878
46f4442e
A
879 test = DateTimePatternGenerator::createEmptyInstance(status);
880 if(U_FAILURE(status)) {
881 errln("ERROR: Fail to create an empty instance ! - exitting.\n");
882 delete test;
883 return;
884 }
2ca993e8
A
885
886 conflictingStatus = test->addPattern(UnicodeString("MMMMd"), true, conflictingPattern, status);
46f4442e
A
887 status = U_ZERO_ERROR;
888 testPattern=test->getBestPattern(UnicodeString("MMMMdd"), status);
2ca993e8 889 conflictingStatus = test->addPattern(UnicodeString("HH:mm"), true, conflictingPattern, status);
4388f060 890 conflictingStatus = test->addPattern(UnicodeString("MMMMMdd"), true, conflictingPattern, status); //duplicate pattern
46f4442e
A
891 StringEnumeration *output=NULL;
892 output = test->getRedundants(status);
893 expectedResult=UnicodeString("MMMMd");
894 if (output != NULL) {
895 output->reset(status);
896 const UnicodeString *dupPattern=output->snext(status);
897 if ( (dupPattern==NULL) || (*dupPattern != expectedResult) ) {
898 errln("ERROR: Fail in getRedundants !\n");
899 }
900 }
2ca993e8 901
46f4442e
A
902 // ======== Test getSkeletons and getBaseSkeletons
903 StringEnumeration* ptrSkeletonEnum = test->getSkeletons(status);
904 if(U_FAILURE(status)) {
905 errln("ERROR: Fail to get skeletons !\n");
906 }
907 UnicodeString returnPattern, *ptrSkeleton;
908 ptrSkeletonEnum->reset(status);
0f5d89e8 909 count=ptrSkeletonEnum->count(status);
46f4442e
A
910 for (i=0; i<count; ++i) {
911 ptrSkeleton = (UnicodeString *)ptrSkeletonEnum->snext(status);
912 returnPattern = test->getPatternForSkeleton(*ptrSkeleton);
913 if ( returnPattern != testSkeletonsResults[i] ) {
914 errln(UnicodeString("ERROR: Unexpected result from getSkeletons and getPatternForSkeleton\nGot: ") + returnPattern
915 + UnicodeString("\nExpected: ") + testSkeletonsResults[i]
916 + UnicodeString("\n"));
917 }
918 }
919 StringEnumeration* ptrBaseSkeletonEnum = test->getBaseSkeletons(status);
920 if(U_FAILURE(status)) {
921 errln("ERROR: Fail to get base skeletons !\n");
2ca993e8 922 }
46f4442e
A
923 count=ptrBaseSkeletonEnum->count(status);
924 for (i=0; i<count; ++i) {
925 ptrSkeleton = (UnicodeString *)ptrBaseSkeletonEnum->snext(status);
926 if ( *ptrSkeleton != testBaseSkeletonsResults[i] ) {
927 errln("ERROR: Unexpected result from getBaseSkeletons() !\n");
928 }
929 }
930
931 // ========= DateTimePatternGenerator sample code in Userguide
932 // set up the generator
933 Locale locale = Locale::getFrench();
934 status = U_ZERO_ERROR;
935 DateTimePatternGenerator *generator = DateTimePatternGenerator::createInstance( locale, status);
2ca993e8 936
46f4442e 937 // get a pattern for an abbreviated month and day
2ca993e8
A
938 pattern = generator->getBestPattern(UnicodeString("MMMd"), status);
939 SimpleDateFormat formatter(pattern, locale, status);
46f4442e
A
940
941 zone = TimeZone::createTimeZone(UnicodeString("GMT"));
942 formatter.setTimeZone(*zone);
943 // use it to format (or parse)
944 UnicodeString formatted;
2ca993e8 945 formatted = formatter.format(Calendar::getNow(), formatted, status);
46f4442e
A
946 // for French, the result is "13 sept."
947 formatted.remove();
948 // cannot use the result from getNow() because the value change evreyday.
949 testDate= LocaleTest::date(99, 0, 13, 23, 58, 59);
950 formatted = formatter.format(testDate, formatted, status);
951 expectedResult=UnicodeString("14 janv.");
952 if ( formatted != expectedResult ) {
953 errln("ERROR: Userguide sample code result!");
954 errln(UnicodeString(" Got: ")+ formatted + UnicodeString(" Expected: ") + expectedResult);
955 }
956
957 delete zone;
958 delete output;
959 delete ptrSkeletonEnum;
960 delete ptrBaseSkeletonEnum;
961 delete test;
962 delete generator;
963}
964
729e4ab9
A
965/**
966 * Test handling of options
967 *
968 * For reference, as of ICU 4.3.3,
969 * root/gregorian has
970 * Hm{"H:mm"}
971 * Hms{"H:mm:ss"}
972 * hm{"h:mm a"}
973 * hms{"h:mm:ss a"}
974 * en/gregorian has
975 * Hm{"H:mm"}
976 * Hms{"H:mm:ss"}
977 * hm{"h:mm a"}
978 * be/gregorian has
979 * HHmmss{"HH.mm.ss"}
980 * Hm{"HH.mm"}
981 * hm{"h.mm a"}
982 * hms{"h.mm.ss a"}
983 */
984typedef struct DTPtnGenOptionsData {
985 const char *locale;
986 const char *skel;
987 const char *expectedPattern;
988 UDateTimePatternMatchOptions options;
989} DTPtnGenOptionsData;
990void IntlTestDateTimePatternGeneratorAPI::testOptions(/*char *par*/)
991{
992 DTPtnGenOptionsData testData[] = {
993 // locale skel expectedPattern options
994 { "en", "Hmm", "HH:mm", UDATPG_MATCH_NO_OPTIONS },
995 { "en", "HHmm", "HH:mm", UDATPG_MATCH_NO_OPTIONS },
996 { "en", "hhmm", "h:mm a", UDATPG_MATCH_NO_OPTIONS },
997 { "en", "Hmm", "HH:mm", UDATPG_MATCH_HOUR_FIELD_LENGTH },
998 { "en", "HHmm", "HH:mm", UDATPG_MATCH_HOUR_FIELD_LENGTH },
999 { "en", "hhmm", "hh:mm a", UDATPG_MATCH_HOUR_FIELD_LENGTH },
2ca993e8
A
1000 { "da", "Hmm", "HH.mm", UDATPG_MATCH_NO_OPTIONS },
1001 { "da", "HHmm", "HH.mm", UDATPG_MATCH_NO_OPTIONS },
1002 { "da", "hhmm", "h.mm a", UDATPG_MATCH_NO_OPTIONS },
1003 { "da", "Hmm", "H.mm", UDATPG_MATCH_HOUR_FIELD_LENGTH },
1004 { "da", "HHmm", "HH.mm", UDATPG_MATCH_HOUR_FIELD_LENGTH },
1005 { "da", "hhmm", "hh.mm a", UDATPG_MATCH_HOUR_FIELD_LENGTH },
51004dcb 1006 //
57a6839d
A
1007 { "en", "yyyy", "yyyy", UDATPG_MATCH_NO_OPTIONS },
1008 { "en", "YYYY", "YYYY", UDATPG_MATCH_NO_OPTIONS },
1009 { "en", "U", "y", UDATPG_MATCH_NO_OPTIONS },
1010 { "en@calendar=japanese", "yyyy", "y G", UDATPG_MATCH_NO_OPTIONS },
1011 { "en@calendar=japanese", "YYYY", "Y G", UDATPG_MATCH_NO_OPTIONS },
1012 { "en@calendar=japanese", "U", "y G", UDATPG_MATCH_NO_OPTIONS },
1013 { "en@calendar=chinese", "yyyy", "r(U)", UDATPG_MATCH_NO_OPTIONS },
b331163b
A
1014 { "en@calendar=chinese", "YYYY", "Y(Y)", UDATPG_MATCH_NO_OPTIONS }, // not a good result, want r(Y) or r(U)
1015 { "en@calendar=chinese", "U", "r(U)", UDATPG_MATCH_NO_OPTIONS },
1016 { "en@calendar=chinese", "Gy", "r(U)", UDATPG_MATCH_NO_OPTIONS },
1017 { "en@calendar=chinese", "GU", "r(U)", UDATPG_MATCH_NO_OPTIONS },
1018 { "en@calendar=chinese", "ULLL", "MMM U", UDATPG_MATCH_NO_OPTIONS },
57a6839d
A
1019 { "en@calendar=chinese", "yMMM", "MMM r(U)", UDATPG_MATCH_NO_OPTIONS },
1020 { "en@calendar=chinese", "GUMMM", "MMM r(U)", UDATPG_MATCH_NO_OPTIONS },
b331163b
A
1021 { "zh@calendar=chinese", "yyyy", "U\\u5E74", UDATPG_MATCH_NO_OPTIONS },
1022 { "zh@calendar=chinese", "YYYY", "Y\\u5E74", UDATPG_MATCH_NO_OPTIONS }, // not a great result, may want r(Y) or r(U)
1023 { "zh@calendar=chinese", "U", "U\\u5E74", UDATPG_MATCH_NO_OPTIONS },
1024 { "zh@calendar=chinese", "Gy", "rU\\u5E74", UDATPG_MATCH_NO_OPTIONS },
1025 { "zh@calendar=chinese", "GU", "rU\\u5E74", UDATPG_MATCH_NO_OPTIONS },
1026 { "zh@calendar=chinese", "ULLL", "U\\u5E74MMM", UDATPG_MATCH_NO_OPTIONS },
57a6839d
A
1027 { "zh@calendar=chinese", "yMMM", "rU\\u5E74MMM", UDATPG_MATCH_NO_OPTIONS },
1028 { "zh@calendar=chinese", "GUMMM", "rU\\u5E74MMM", UDATPG_MATCH_NO_OPTIONS },
729e4ab9 1029 };
2ca993e8
A
1030
1031 int count = UPRV_LENGTHOF(testData);
729e4ab9 1032 const DTPtnGenOptionsData * testDataPtr = testData;
2ca993e8 1033
729e4ab9
A
1034 for (; count-- > 0; ++testDataPtr) {
1035 UErrorCode status = U_ZERO_ERROR;
1036
1037 Locale locale(testDataPtr->locale);
1038 UnicodeString skel(testDataPtr->skel);
57a6839d 1039 UnicodeString expectedPattern(UnicodeString(testDataPtr->expectedPattern).unescape());
729e4ab9
A
1040 UDateTimePatternMatchOptions options = testDataPtr->options;
1041
1042 DateTimePatternGenerator * dtpgen = DateTimePatternGenerator::createInstance(locale, status);
1043 if (U_FAILURE(status)) {
1044 dataerrln("Unable to create DateTimePatternGenerator instance for locale(%s): %s", locale.getName(), u_errorName(status));
1045 delete dtpgen;
1046 continue;
1047 }
1048 UnicodeString pattern = dtpgen->getBestPattern(skel, options, status);
1049 if (pattern.compare(expectedPattern) != 0) {
1050 errln( UnicodeString("ERROR in getBestPattern, locale ") + UnicodeString(testDataPtr->locale) +
1051 UnicodeString(", skeleton ") + skel +
1052 ((options)?UnicodeString(", options!=0"):UnicodeString(", options==0")) +
1053 UnicodeString(", expected pattern ") + expectedPattern +
1054 UnicodeString(", got ") + pattern );
1055 }
1056 delete dtpgen;
1057 }
1058}
1059
57a6839d
A
1060/**
1061 * Test that DTPG can handle all valid pattern character / length combinations
1062 *
1063 */
1064#define FIELD_LENGTHS_COUNT 6
1065#define FIELD_LENGTH_MAX 8
1066#define MUST_INCLUDE_COUNT 5
1067
1068typedef struct AllFieldsTestItem {
1069 char patternChar;
1070 int8_t fieldLengths[FIELD_LENGTHS_COUNT+1]; // up to FIELD_LENGTHS_COUNT lengths to try
1071 // (length <=FIELD_LENGTH_MAX) plus 0 terminator
1072 char mustIncludeOneOf[MUST_INCLUDE_COUNT+1];// resulting pattern must include at least one of
1073 // these as a pattern char (0-terminated list)
1074} AllFieldsTestItem;
1075
1076void IntlTestDateTimePatternGeneratorAPI::testAllFieldPatterns(/*char *par*/)
1077{
1078 const char * localeNames[] = {
1079 "root",
1080 "root@calendar=japanese",
1081 "root@calendar=chinese",
1082 "en",
1083 "en@calendar=japanese",
1084 "en@calendar=chinese",
1085 NULL // terminator
1086 };
1087 AllFieldsTestItem testData[] = {
1088 //pat fieldLengths generated pattern must
1089 //chr to test include one of these
1090 { 'G', {1,2,3,4,5,0}, "G" }, // era
1091 // year
1092 { 'y', {1,2,3,4,0}, "yU" }, // year
1093 { 'Y', {1,2,3,4,0}, "Y" }, // year for week of year
1094 { 'u', {1,2,3,4,5,0}, "yuU" }, // extended year
1095 { 'U', {1,2,3,4,5,0}, "yU" }, // cyclic year name
1096 // quarter
1097 { 'Q', {1,2,3,4,0}, "Qq" }, // x
1098 { 'q', {1,2,3,4,0}, "Qq" }, // standalone
1099 // month
1100 { 'M', {1,2,3,4,5,0}, "ML" }, // x
1101 { 'L', {1,2,3,4,5,0}, "ML" }, // standalone
1102 // week
1103 { 'w', {1,2,0}, "w" }, // week of year
1104 { 'W', {1,0}, "W" }, // week of month
1105 // day
1106 { 'd', {1,2,0}, "d" }, // day of month
1107 { 'D', {1,2,3,0}, "D" }, // day of year
1108 { 'F', {1,0}, "F" }, // day of week in month
1109 { 'g', {7,0}, "g" }, // modified julian day
1110 // weekday
1111 { 'E', {1,2,3,4,5,6}, "Eec" }, // day of week
1112 { 'e', {1,2,3,4,5,6}, "Eec" }, // local day of week
1113 { 'c', {1,2,3,4,5,6}, "Eec" }, // standalone local day of week
1114 // day period
0f5d89e8
A
1115 { 'a', {1,2,3,4,5,0}, "a" }, // am or pm
1116 { 'b', {1,2,3,4,5,0}, "b" }, // dayPeriod AM/PM/noon
1117 { 'B', {1,2,3,4,5,0}, "B" }, // dayPeriod ranges
57a6839d
A
1118 // hour
1119 { 'h', {1,2,0}, "hK" }, // 12 (1-12)
1120 { 'H', {1,2,0}, "Hk" }, // 24 (0-23)
1121 { 'K', {1,2,0}, "hK" }, // 12 (0-11)
1122 { 'k', {1,2,0}, "Hk" }, // 24 (1-24)
1123 { 'j', {1,2,0}, "hHKk" }, // locale default
0f5d89e8
A
1124 { 'J', {1,2,0}, "hHKk" }, // locale default, without any dayPeriod
1125 { 'C', {1,2,0}, "hHKk" }, // locale allowed first entry, possibly with b or B
57a6839d
A
1126 // minute
1127 { 'm', {1,2,0}, "m" }, // x
1128 // second & fractions
1129 { 's', {1,2,0}, "s" }, // x
1130 { 'S', {1,2,3,4,0}, "S" }, // fractional second
1131 { 'A', {8,0}, "A" }, // milliseconds in day
1132 // zone
1133 { 'z', {1,2,3,4,0}, "z" }, // x
1134 { 'Z', {1,2,3,4,5,0}, "Z" }, // x
1135 { 'O', {1,4,0}, "O" }, // x
1136 { 'v', {1,4,0}, "v" }, // x
1137 { 'V', {1,2,3,4,0}, "V" }, // x
1138 { 'X', {1,2,3,4,5,0}, "X" }, // x
1139 { 'x', {1,2,3,4,5,0}, "x" }, // x
1140 };
2ca993e8 1141
57a6839d
A
1142 const char ** localeNamesPtr = localeNames;
1143 const char * localeName;
1144 while ( (localeName = *localeNamesPtr++) != NULL) {
1145 UErrorCode status = U_ZERO_ERROR;
1146 Locale locale = Locale::createFromName(localeName);
1147 DateTimePatternGenerator * dtpg = DateTimePatternGenerator::createInstance(locale, status);
1148 if (U_SUCCESS(status)) {
1149 const AllFieldsTestItem * testDataPtr = testData;
2ca993e8 1150 int itemCount = UPRV_LENGTHOF(testData);
57a6839d
A
1151 for (; itemCount-- > 0; ++testDataPtr) {
1152 char skelBuf[FIELD_LENGTH_MAX];
1153 int32_t chrIndx, lenIndx;
1154 for (chrIndx = 0; chrIndx < FIELD_LENGTH_MAX; chrIndx++) {
1155 skelBuf[chrIndx] = testDataPtr->patternChar;
1156 }
1157 for (lenIndx = 0; lenIndx < FIELD_LENGTHS_COUNT; lenIndx++) {
1158 int32_t skelLen = testDataPtr->fieldLengths[lenIndx];
1159 if (skelLen <= 0) {
1160 break;
1161 }
1162 if (skelLen > FIELD_LENGTH_MAX) {
1163 continue;
1164 }
1165 UnicodeString skeleton(skelBuf, skelLen, US_INV);
1166 UnicodeString pattern = dtpg->getBestPattern(skeleton, status);
1167 if (U_FAILURE(status)) {
1168 errln("DateTimePatternGenerator getBestPattern for locale %s, skelChar %c skelLength %d fails: %s",
1169 locale.getName(), testDataPtr->patternChar, skelLen, u_errorName(status));
1170 } else if (pattern.length() <= 0) {
1171 errln("DateTimePatternGenerator getBestPattern for locale %s, skelChar %c skelLength %d produces 0-length pattern",
1172 locale.getName(), testDataPtr->patternChar, skelLen);
1173 } else {
1174 // test that resulting pattern has at least one char in mustIncludeOneOf
1175 UnicodeString mustIncludeOneOf(testDataPtr->mustIncludeOneOf, -1, US_INV);
1176 int32_t patIndx, patLen = pattern.length();
1177 UBool inQuoted = FALSE;
1178 for (patIndx = 0; patIndx < patLen; patIndx++) {
1179 UChar c = pattern.charAt(patIndx);
1180 if (c == 0x27) {
1181 inQuoted = !inQuoted;
1182 } else if (!inQuoted && c <= 0x007A && c >= 0x0041) {
1183 if (mustIncludeOneOf.indexOf(c) >= 0) {
1184 break;
1185 }
1186 }
1187 }
1188 if (patIndx >= patLen) {
1189 errln(UnicodeString("DateTimePatternGenerator getBestPattern for locale ") +
1190 UnicodeString(locale.getName(),-1,US_INV) +
1191 ", skeleton " + skeleton +
1192 ", produces pattern without required chars: " + pattern);
1193 }
2ca993e8 1194
57a6839d
A
1195 }
1196 }
1197 }
1198 delete dtpg;
1199 } else {
1200 dataerrln("Create DateTimePatternGenerator instance for locale(%s) fails: %s",
1201 locale.getName(), u_errorName(status));
1202 }
1203 }
1204}
2ca993e8
A
1205
1206void IntlTestDateTimePatternGeneratorAPI::testStaticGetSkeleton(/*char *par*/)
1207{
1208 // Verify that staticGetSkeleton() doesn't mangle skeletons. (Ticket #11985)
1209 static const char* const testData[] = {
1210 "jmm",
1211 "jjmm",
1212 "Jmm",
1213 "JJmm"
1214 };
1215
1216 for (size_t i = 0; i < UPRV_LENGTHOF(testData); i++) {
1217 UErrorCode status = U_ZERO_ERROR;
1218 UnicodeString skeleton = DateTimePatternGenerator::staticGetSkeleton(testData[i], status);
1219 if (!assertSuccess("staticGetSkeleton", status)) {
1220 return;
1221 }
1222 assertEquals("Skeleton", testData[i], skeleton);
1223 }
1224}
1225
1226void IntlTestDateTimePatternGeneratorAPI::testC() {
0f5d89e8
A
1227 const char* tests[][3] = {
1228 // These may change with actual data for Bhmm/bhmm skeletons
1229 {"zh", "Cm", "Bh:mm"},
1230 {"zh", "CCm", "Bhh:mm"},
1231 {"zh", "CCCm", "BBBBh:mm"},
1232 {"zh", "CCCCm", "BBBBhh:mm"},
1233 {"zh", "CCCCCm", "BBBBBh:mm"},
1234 {"zh", "CCCCCCm", "BBBBBhh:mm"},
1235 {"de", "Cm", "HH:mm"},
1236 {"de", "CCm", "HH:mm"},
1237 {"de", "CCCm", "HH:mm"},
1238 {"de", "CCCCm", "HH:mm"},
1239 {"en", "Cm", "h:mm a"},
1240 {"en", "CCm", "hh:mm a"},
1241 {"en", "CCCm", "h:mm aaaa"},
1242 {"en", "CCCCm", "hh:mm aaaa"},
1243 {"en", "CCCCCm", "h:mm aaaaa"},
1244 {"en", "CCCCCCm", "hh:mm aaaaa"},
1245 {"en-BN", "Cm", "h:mm b"},
1246 {"gu-IN", "Cm", "h:mm B"},
3d1f044b 1247 {"und-IN", "Cm", "h:mm B"}
2ca993e8
A
1248 };
1249
0f5d89e8
A
1250 UErrorCode status = U_ZERO_ERROR;
1251 int32_t numTests = UPRV_LENGTHOF(tests);
1252 for (int32_t i = 0; i < numTests; ++i) {
3d1f044b
A
1253 DateTimePatternGenerator *gen = DateTimePatternGenerator::createInstance(
1254 Locale::forLanguageTag(tests[i][0], status), status);
f3c0d7a5
A
1255 if (gen == NULL) {
1256 dataerrln("FAIL: DateTimePatternGenerator::createInstance failed for %s", tests[i][0]);
1257 return;
1258 }
0f5d89e8
A
1259 UDateTimePatternMatchOptions options = UDATPG_MATCH_HOUR_FIELD_LENGTH;
1260 UnicodeString pattern = gen->getBestPattern(tests[i][1], options, status);
2ca993e8
A
1261 UnicodeString expectedPattern = tests[i][2];
1262
1263 char message[100] = "\0";
1264 strcat(message, tests[i][0]);
1265 strcat(message, "/");
1266 strcat(message, tests[i][1]);
1267 assertEquals(message, expectedPattern, pattern);
1268 delete gen;
1269 }
1270}
1271
0f5d89e8
A
1272enum { kCharBufMax = 31 };
1273void IntlTestDateTimePatternGeneratorAPI::testSkeletonsWithDayPeriods() {
1274 const char * patterns[] = {
1275 // since icu4c getEmptyInstance does not call addCanonicalItems (unlike J), set these here:
1276 "a", // should get internal skeleton a
1277 "H", // should get internalskeleton H
1278 "m", // should get internalskeleton m
1279 "s", // should get internalskeleton s
1280 // patterns from which to construct sample data for a locale
1281 //"H", // should get internalskeleton H
1282 "h a", // should get internalskeleton ah
1283 "B h", // should get internalskeleton Bh
1284 };
1285 const char* testItems[][2] = {
1286 // sample requested skeletons and results
1287 // skel pattern
1288 { "H", "H"},
1289 { "HH", "HH"},
1290 { "aH", "H"},
1291 { "aHH", "HH"},
1292 { "BH", "H"},
1293 { "BHH", "HH"},
1294 { "BBBBH", "H"},
1295 { "h", "h a"},
1296 { "hh", "hh a"},
1297 { "ah", "h a"},
1298 { "ahh", "hh a"},
1299 { "aaaah", "h aaaa"},
1300 { "aaaahh", "hh aaaa"},
1301 { "bh", "h b"},
1302 { "bhh", "hh b"},
1303 { "bbbbh", "h bbbb"},
1304 { "Bh", "B h"},
1305 { "Bhh", "B hh"},
1306 { "BBBBh", "BBBB h"},
1307 { "BBBBhh", "BBBB hh"},
1308 { "a", "a"},
1309 { "aaaaa", "aaaaa"},
1310 { "b", "b"},
1311 { "bbbb", "bbbb"},
1312 { "B", "B"},
1313 { "BBBB", "BBBB"},
1314 };
1315 UErrorCode status = U_ZERO_ERROR;
1316 DateTimePatternGenerator *gen = DateTimePatternGenerator::createEmptyInstance(status);
1317 if (U_FAILURE(status)) {
1318 errln("ERROR: createEmptyInstance fails, status: %s", u_errorName(status));
1319 } else {
1320 int32_t i, len = UPRV_LENGTHOF(patterns);
1321 for (i = 0; i < len; i++) {
1322 UnicodeString conflictingPattern;
1323 (void)gen->addPattern(UnicodeString(patterns[i]), TRUE, conflictingPattern, status);
1324 if (U_FAILURE(status)) {
1325 errln("ERROR: addPattern %s fail, status: %s", patterns[i], u_errorName(status));
1326 break;
1327 }
1328 }
1329 if (U_SUCCESS(status)) {
1330 len = UPRV_LENGTHOF(testItems);
1331 for (i = 0; i < len; i++) {
1332 status = U_ZERO_ERROR;
1333 UDateTimePatternMatchOptions options = UDATPG_MATCH_HOUR_FIELD_LENGTH;
1334 UnicodeString result = gen->getBestPattern(UnicodeString(testItems[i][0]), options, status);
1335 if (U_FAILURE(status)) {
1336 errln("ERROR: getBestPattern %s fail, status: %s", testItems[i][0], u_errorName(status));
1337 } else if (result != UnicodeString(testItems[i][1])) {
1338 char charResult[kCharBufMax+1];
1339 result.extract(0, result.length(), charResult, kCharBufMax);
1340 charResult[kCharBufMax] = 0; // ensure termination
1341 errln("ERROR: getBestPattern %s, expected %s, got %s", testItems[i][0], testItems[i][1], charResult);
1342 }
1343 }
1344 }
1345 }
1346 delete gen;
1347}
1348
1349typedef struct FieldDisplayNameData {
1350 const char * locale;
1351 UDateTimePatternField field;
1352 UDateTimePGDisplayWidth width;
1353 const char * expected; // can have escapes such as \\u00E0
1354} FieldDisplayNameData;
1355enum { kFieldDisplayNameMax = 32 };
1356
1357void IntlTestDateTimePatternGeneratorAPI::testGetFieldDisplayNames() {
1358 const FieldDisplayNameData testData[] = {
1359 /*loc field width expectedName */
1360 { "de", UDATPG_QUARTER_FIELD, UDATPG_WIDE, "Quartal" },
1361 { "de", UDATPG_QUARTER_FIELD, UDATPG_ABBREVIATED, "Quart." },
1362 { "de", UDATPG_QUARTER_FIELD, UDATPG_NARROW, "Q" },
1363 { "en", UDATPG_DAY_OF_WEEK_IN_MONTH_FIELD, UDATPG_WIDE, "weekday of the month" },
1364 { "en", UDATPG_DAY_OF_WEEK_IN_MONTH_FIELD, UDATPG_ABBREVIATED, "wkday. of mo." },
1365 { "en", UDATPG_DAY_OF_WEEK_IN_MONTH_FIELD, UDATPG_NARROW, "wkday. of mo." }, // fallback
1366 { "en_GB", UDATPG_DAY_OF_WEEK_IN_MONTH_FIELD, UDATPG_WIDE, "weekday of the month" },
1367 { "en_GB", UDATPG_DAY_OF_WEEK_IN_MONTH_FIELD, UDATPG_ABBREVIATED, "wkday of mo" }, // override
1368 { "en_GB", UDATPG_DAY_OF_WEEK_IN_MONTH_FIELD, UDATPG_NARROW, "wkday of mo" },
1369 { "it", UDATPG_SECOND_FIELD, UDATPG_WIDE, "secondo" },
1370 { "it", UDATPG_SECOND_FIELD, UDATPG_ABBREVIATED, "s" },
1371 { "it", UDATPG_SECOND_FIELD, UDATPG_NARROW, "s" },
1372 };
1373
1374 int count = UPRV_LENGTHOF(testData);
1375 const FieldDisplayNameData * testDataPtr = testData;
1376 for (; count-- > 0; ++testDataPtr) {
1377 UErrorCode status = U_ZERO_ERROR;
1378 Locale locale(testDataPtr->locale);
1379 DateTimePatternGenerator * dtpg = DateTimePatternGenerator::createInstance(locale, status);
1380 if (U_FAILURE(status)) {
1381 dataerrln("FAIL: DateTimePatternGenerator::createInstance failed for locale %s", testDataPtr->locale);
1382 } else {
1383 UChar expName[kFieldDisplayNameMax+1];
1384 u_unescape(testDataPtr->expected, expName, kFieldDisplayNameMax);
1385 expName[kFieldDisplayNameMax] = 0; // ensure 0 termination
1386 UnicodeString getName = dtpg->getFieldDisplayName(testDataPtr->field, testDataPtr->width);
1387 if (getName.compare(expName, u_strlen(expName)) != 0) {
1388 errln("ERROR: locale %s field %d width %d, expected %s\n",
1389 testDataPtr->locale, testDataPtr->field, testDataPtr->width, testDataPtr->expected);
1390 }
1391 delete dtpg;
1392 }
1393 }
1394}
1395
3d1f044b
A
1396static const UChar timeCycleChars[] = { (UChar)0x0048, (UChar)0x0068, (UChar)0x004B, (UChar)0x006B, (UChar)0 };
1397
1398void IntlTestDateTimePatternGeneratorAPI::testJjMapping() {
1399 UErrorCode status = U_ZERO_ERROR;
1400 UnicodeString jSkeleton("j");
1401 // First test that j maps correctly by region in a locale for which we do not have data.
1402 {
1403 const char* testLocaleID = "de_US"; // short patterns from fallback locale "de" have "HH"
1404 Locale testLocale(testLocaleID);
1405 LocalPointer<DateTimePatternGenerator> dtpg(DateTimePatternGenerator::createInstance(testLocale, status));
1406 if (U_FAILURE(status)) {
1407 dataerrln("FAIL: DateTimePatternGenerator::createInstance failed for locale %s: %s", testLocaleID, u_errorName(status));
1408 } else {
1409 UnicodeString jPattern = dtpg->getBestPattern(jSkeleton, UDATPG_MATCH_ALL_FIELDS_LENGTH, status); // get pattern with h e.g. "h 'Uhr' a"
1410 if (U_FAILURE(status)) {
1411 errln("FAIL: DateTimePatternGenerator::getBestPattern locale %s, pattern j: %s", testLocaleID, u_errorName(status));
1412 } else {
1413 UnicodeString jPatSkeleton = DateTimePatternGenerator::staticGetSkeleton(jPattern, status); // strip literals, get e.g. "ah"
1414 if (U_FAILURE(status)) {
1415 errln("FAIL: DateTimePatternGenerator::staticGetSkeleton locale %s: %s", testLocaleID, u_errorName(status));
1416 } else if (jPatSkeleton.indexOf(u'h') < 0) { // expect US preferred cycle 'h', not H or other cycle
1417 errln("ERROR: DateTimePatternGenerator::getBestPattern locale %s, pattern j did not use 'h'", testLocaleID);
1418 }
1419 }
1420 }
1421 }
1422
1423 // Next test that in all available Locales, the actual short time pattern uses the same cycle as produced by 'j'
1424 int32_t locCount;
1425 const Locale* localePtr = DateFormat::getAvailableLocales(locCount);
1426 for (; locCount-- > 0; localePtr++) {
1427 const char* localeID = localePtr->getName();
1428 status = U_ZERO_ERROR;
1429 LocalPointer<DateTimePatternGenerator> dtpg(DateTimePatternGenerator::createInstance(*localePtr, status));
1430 if (U_FAILURE(status)) {
1431 dataerrln("FAIL: DateTimePatternGenerator::createInstance failed for locale %s: %s", localeID, u_errorName(status));
1432 continue;
1433 }
1434 LocalPointer<DateFormat> dfmt(DateFormat::createTimeInstance(DateFormat::kShort, *localePtr));
1435 if (U_FAILURE(status)) {
1436 dataerrln("FAIL: DateFormat::createTimeInstance kShort failed for locale %s: %s", localeID, u_errorName(status));
1437 continue;
1438 }
1439 const SimpleDateFormat* sdfmt;
1440 if ((sdfmt = dynamic_cast<const SimpleDateFormat*>(reinterpret_cast<const DateFormat*>(dfmt.getAlias()))) == NULL) {
1441 continue;
1442 }
1443 UnicodeString shortPattern;
1444 shortPattern = sdfmt->toPattern(shortPattern);
1445 UnicodeString jPattern = dtpg->getBestPattern(jSkeleton, status);
1446 if (U_FAILURE(status)) {
1447 errln("FAIL: DateTimePatternGenerator::getBestPattern locale %s, pattern j: %s", localeID, u_errorName(status));
1448 continue;
1449 }
1450 // Now check that shortPattern and jPattern use the same hour cycle
1451 UnicodeString jPatSkeleton = DateTimePatternGenerator::staticGetSkeleton(jPattern, status);
1452 UnicodeString shortPatSkeleton = DateTimePatternGenerator::staticGetSkeleton(shortPattern, status);
1453 if (U_FAILURE(status)) {
1454 errln("FAIL: DateTimePatternGenerator::staticGetSkeleton locale %s: %s", localeID, u_errorName(status));
1455 continue;
1456 }
1457 const UChar* charPtr = timeCycleChars;
1458 for (; *charPtr != (UChar)0; charPtr++) {
1459 if (jPatSkeleton.indexOf(*charPtr) >= 0) {
1460 if (shortPatSkeleton.indexOf(*charPtr) < 0) {
340931cb 1461 char jcBuf[2], spBuf[32], jpBuf[32];
3d1f044b
A
1462 u_austrncpy(jcBuf, charPtr, 1);
1463 jcBuf[1] = 0;
1464 shortPattern.extract(0, shortPattern.length(), spBuf, 32);
340931cb 1465 jPattern.extract(0, jPattern.length(), jpBuf, 32);
3d1f044b 1466 const char* dfmtCalType = (dfmt->getCalendar())->getType();
340931cb 1467 errln("ERROR: locale %s, expected j resolved char %s to occur in short time pattern '%s' for %s (best pattern: '%s')", localeID, jcBuf, spBuf, dfmtCalType, jpBuf);
3d1f044b
A
1468 }
1469 break;
1470 }
1471 }
1472 }
1473}
1474
340931cb
A
1475void IntlTestDateTimePatternGeneratorAPI::test20640_HourCyclArsEnNH() {
1476 IcuTestErrorCode status(*this, "test20640_HourCyclArsEnNH");
1477
1478 const struct TestCase {
1479 const char* localeName;
1480 const char16_t* expectedDtpgPattern;
1481 const char16_t* expectedTimePattern;
1482 } cases[] = {
1483 // ars is interesting because it does not have a region, but it aliases
1484 // to ar_SA, which has a region.
1485 {"ars", u"h\u00A0a", u"h:mm\u00A0a"},
1486 // en_NH is interesting because NH is a deprecated region code;
1487 // formerly New Hebrides, now Vanuatu => VU => h.
1488 {"en_NH", u"h a", u"h:mm a"},
1489 // ch_ZH is a typo (should be zh_CN), but we should fail gracefully.
1490 // {"cn_ZH", u"HH", u"H:mm"}, // TODO(ICU-20653): Desired behavior
1491 {"cn_ZH", u"HH", u"HH:mm"}, // Actual behavior (falls back to root for std formats, 001 for mapping of 'j')
1492 // a non-BCP47 locale without a country code should not fail
1493 {"ja_TRADITIONAL", u"H時", u"H:mm"},
1494 };
1495
1496 for (auto& cas : cases) {
1497 status.setScope(cas.localeName);
1498
1499 Locale loc(cas.localeName);
1500 LocalPointer<DateFormat> dtf(DateFormat::createTimeInstance(DateFormat::kShort, loc), status);
1501 LocalPointer<DateTimePatternGenerator> dtpg(DateTimePatternGenerator::createInstance(loc, status));
1502 if (status.errIfFailureAndReset()) {
1503 return;
1504 }
1505
1506 UnicodeString timePattern;
1507 dynamic_cast<SimpleDateFormat*>(dtf.getAlias())->toPattern(timePattern);
1508 UnicodeString dtpgPattern = dtpg->getBestPattern(u"j", status);
1509 if (status.errIfFailureAndReset()) {
1510 return;
1511 }
1512
1513 assertEquals(UnicodeString("dtpgPattern ") + cas.localeName,
1514 cas.expectedDtpgPattern, dtpgPattern);
1515 assertEquals(UnicodeString("timePattern ") + cas.localeName,
1516 cas.expectedTimePattern, timePattern);
1517 }
1518
1519}
1520
1521void IntlTestDateTimePatternGeneratorAPI::testFallbackWithDefaultRootLocale() {
1522 UErrorCode status = U_ZERO_ERROR;
1523 char original[ULOC_FULLNAME_CAPACITY];
1524
1525 uprv_strcpy(original, uloc_getDefault());
1526 uloc_setDefault("root", &status);
1527 if (U_FAILURE(status)) {
1528 errln("ERROR: Failed to change the default locale to root! Default is: %s\n", uloc_getDefault());
1529 }
1530
1531 DateTimePatternGenerator* dtpg = icu::DateTimePatternGenerator::createInstance("abcdedf", status);
1532
1533 if (U_FAILURE(status)) {
1534 errln("ERROR: expected createInstance with invalid locale to succeed. Status: %s", u_errorName(status));
1535 }
1536 if (status != U_USING_DEFAULT_WARNING) {
1537 errln("ERROR: expected createInstance to return U_USING_DEFAULT_WARNING for invalid locale and default root locale. Status: %s", u_errorName(status));
1538 }
1539
1540 delete dtpg;
1541
1542 uloc_setDefault(original, &status);
1543 if (U_FAILURE(status)) {
1544 errln("ERROR: Failed to change the default locale back to %s\n", original);
1545 }
1546}
1547
46f4442e 1548#endif /* #if !UCONFIG_NO_FORMATTING */