1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
4 * COPYRIGHT:
5 * Copyright (c) 2008-2016, International Business Machines Corporation and
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>
15 #include "dtptngts.h"
16
17 #include "unicode/calendar.h"
18 #include "unicode/smpdtfmt.h"
19 #include "unicode/dtfmtsym.h"
20 #include "unicode/dtptngen.h"
21 #include "cmemory.h"
22 #include "loctest.h"
23
24
25 // This is an API test, not a unit test. It doesn't test very many cases, and doesn't
26 // try to test the full functionality. It just calls each function in the class and
27 // verifies that it works on a basic level.
28
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)29 void IntlTestDateTimePatternGeneratorAPI::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
30 {
31 if (exec) logln("TestSuite DateTimePatternGeneratorAPI");
32 switch (index) {
33 TESTCASE(0, testAPI);
34 TESTCASE(1, testOptions);
35 TESTCASE(2, testAllFieldPatterns);
36 TESTCASE(3, testStaticGetSkeleton);
37 TESTCASE(4, testC);
38 TESTCASE(5, testSkeletonsWithDayPeriods);
39 default: name = ""; break;
40 }
41 }
42
43 #define MAX_LOCALE 11
44
45 /**
46 * Test various generic API methods of DateTimePatternGenerator for API coverage.
47 */
testAPI()48 void IntlTestDateTimePatternGeneratorAPI::testAPI(/*char *par*/)
49 {
50 UnicodeString patternData[] = {
51 UnicodeString("yM"), // 00
52 UnicodeString("yMMM"), // 01
53 UnicodeString("yMd"), // 02
54 UnicodeString("yMMMd"), // 03
55 UnicodeString("Md"), // 04
56 UnicodeString("MMMd"), // 05
57 UnicodeString("MMMMd"), // 06
58 UnicodeString("yQQQ"), // 07
59 UnicodeString("hhmm"), // 08
60 UnicodeString("HHmm"), // 09
61 UnicodeString("jjmm"), // 10
62 UnicodeString("mmss"), // 11
63 UnicodeString("yyyyMMMM"), // 12
64 UnicodeString("MMMEd"), // 13
65 UnicodeString("Ed"), // 14
66 UnicodeString("jmmssSSS"), // 15
67 UnicodeString("JJmm"), // 16
68 UnicodeString(),
69 };
70
71 const char* testLocale[MAX_LOCALE][4] = {
72 {"en", "US", "", ""}, // 0
73 {"en", "US", "", "calendar=japanese"}, // 1
74 {"de", "DE", "", ""}, // 2
75 {"fi", "", "", ""}, // 3
76 {"es", "", "", ""}, // 4
77 {"ja", "", "", ""}, // 5
78 {"ja", "", "", "calendar=japanese"}, // 6
79 {"zh", "Hans", "CN", ""}, // 7
80 {"zh", "TW", "", "calendar=roc"}, // 8
81 {"ru", "", "", ""}, // 9
82 {"zh", "", "", "calendar=chinese"}, // 10
83 };
84
85 // For Weds, Jan 13, 1999, 23:58:59
86 UnicodeString patternResults[] = {
87 // en_US // 0 en_US
88 UnicodeString("1/1999"), // 00: yM
89 UnicodeString("Jan 1999"), // 01: yMMM
90 UnicodeString("1/13/1999"), // 02: yMd
91 UnicodeString("Jan 13, 1999"), // 03: yMMMd
92 UnicodeString("1/13"), // 04: Md
93 UnicodeString("Jan 13"), // 05: MMMd
94 UnicodeString("January 13"), // 06: MMMMd
95 UnicodeString("Q1 1999"), // 07: yQQQ
96 UnicodeString("11:58 PM"), // 08: hhmm
97 UnicodeString("23:58"), // 09: HHmm
98 UnicodeString("11:58 PM"), // 10: jjmm
99 UnicodeString("58:59"), // 11: mmss
100 UnicodeString("January 1999"), // 12: yyyyMMMM
101 UnicodeString("Wed, Jan 13"), // 13: MMMEd -> EEE, MMM d
102 UnicodeString("13 Wed"), // 14: Ed -> d EEE
103 UnicodeString("11:58:59.123 PM"), // 15: jmmssSSS -> "h:mm:ss.SSS a"
104 UnicodeString("11:58"), // 16: JJmm
105
106 // en_US@calendar=japanese // 1 en_US@calendar=japanese
107 UnicodeString("1/11 H"), // 0: yM
108 UnicodeString("Jan 11 Heisei"), // 1: yMMM
109 UnicodeString("1/13/11 H"), // 2: yMd
110 UnicodeString("Jan 13, 11 Heisei"), // 3: yMMMd
111 UnicodeString("1/13"), // 4: Md
112 UnicodeString("Jan 13"), // 5: MMMd
113 UnicodeString("January 13"), // 6: MMMMd
114 UnicodeString("Q1 11 Heisei"), // 7: yQQQ
115 UnicodeString("11:58 PM"), // 8: hhmm
116 UnicodeString("23:58"), // 9: HHmm
117 UnicodeString("11:58 PM"), // 10: jjmm
118 UnicodeString("58:59"), // 11: mmss
119 UnicodeString("January 11 Heisei"), // 12: yyyyMMMM
120 UnicodeString("Wed, Jan 13"), // 13: MMMEd -> EEE, MMM d"
121 UnicodeString("13 Wed"), // 14: Ed -> d EEE
122 UnicodeString("11:58:59.123 PM"), // 15: jmmssSSS -> "h:mm:ss.SSS a"
123 UnicodeString("11:58"), // 16: JJmm
124
125 // de_DE // 2 de_DE
126 UnicodeString("1.1999"), // 00: yM
127 UnicodeString("Jan. 1999"), // 01: yMMM
128 UnicodeString("13.1.1999"), // 02: yMd
129 UnicodeString("13. Jan. 1999"), // 03: yMMMd
130 UnicodeString("13.1."), // 04: Md
131 UnicodeString("13. Jan."), // 05: MMMd
132 UnicodeString("13. Januar"), // 06: MMMMd
133 UnicodeString("Q1 1999"), // 07: yQQQ
134 UnicodeString("11:58 nachm."), // 08: hhmm
135 UnicodeString("23:58"), // 09: HHmm
136 UnicodeString("23:58"), // 10: jjmm
137 UnicodeString("58:59"), // 11: mmss
138 UnicodeString("Januar 1999"), // 12: yyyyMMMM
139 UnicodeString("Mi., 13. Jan."), // 13: MMMEd -> EEE, d. MMM
140 UnicodeString("Mi., 13."), // 14: Ed -> EEE d.
141 UnicodeString("23:58:59,123"), // 15: jmmssSSS -> "HH:mm:ss,SSS"
142 UnicodeString("23:58"), // 16: JJmm
143
144 // fi // 3 fi
145 UnicodeString("1.1999"), // 00: yM (fixed expected result per ticket:6626:)
146 UnicodeString("tammi 1999"), // 01: yMMM
147 UnicodeString("13.1.1999"), // 02: yMd
148 UnicodeString("13. tammik. 1999"), // 03: yMMMd
149 UnicodeString("13.1."), // 04: Md
150 UnicodeString("13. tammik."), // 05: MMMd
151 UnicodeString("13. tammikuuta"), // 06: MMMMd
152 UnicodeString("1. nelj. 1999"), // 07: yQQQ
153 UnicodeString("11.58 ip."), // 08: hhmm
154 UnicodeString("23.58"), // 09: HHmm
155 UnicodeString("23.58"), // 10: jjmm
156 UnicodeString("58.59"), // 11: mmss
157 UnicodeString("tammikuu 1999"), // 12: yyyyMMMM
158 UnicodeString("ke 13. tammik."), // 13: MMMEd -> EEE d. MMM
159 UnicodeString("ke 13."), // 14: Ed -> ccc d.
160 UnicodeString("23.58.59,123"), // 15: jmmssSSS -> "H.mm.ss,SSS"
161 UnicodeString("23.58"), // 16: JJmm
162
163 // es // 4 es
164 UnicodeString("1/1999"), // 00: yM -> "M/y"
165 UnicodeString("ene. 1999"), // 01: yMMM -> "MMM y"
166 UnicodeString("13/1/1999"), // 02: yMd -> "d/M/y"
167 UnicodeString("13 ene. 1999"), // 03: yMMMd -> "d MMM y"
168 UnicodeString("13/1"), // 04: Md -> "d/M"
169 UnicodeString("13 ene."), // 05: MMMd -> "d 'de' MMM"
170 UnicodeString("13 de enero"), // 06: MMMMd -> "d 'de' MMMM"
171 UnicodeString("T1 1999"), // 07: yQQQ -> "QQQ y"
172 UnicodeString("11:58 p. m."), // 08: hhmm -> "hh:mm a"
173 UnicodeString("23:58"), // 09: HHmm -> "HH:mm"
174 UnicodeString("23:58"), // 10: jjmm -> "HH:mm"
175 UnicodeString("58:59"), // 11: mmss -> "mm:ss"
176 UnicodeString("enero de 1999"), // 12: yyyyMMMM -> "MMMM 'de' yyyy"
177 CharsToUnicodeString("mi\\u00E9., 13 ene."), // 13: MMMEd -> "E, d MMM"
178 CharsToUnicodeString("mi\\u00E9. 13"), // 14: Ed -> "EEE d"
179 UnicodeString("23:58:59,123"), // 15: jmmssSSS -> "H:mm:ss,SSS"
180 UnicodeString("23:58"), // 16: JJmm
181
182 // ja // 5 ja
183 UnicodeString("1999/1"), // 00: yM -> y/M
184 CharsToUnicodeString("1999\\u5E741\\u6708"), // 01: yMMM -> y\u5E74M\u6708
185 UnicodeString("1999/1/13"), // 02: yMd -> y/M/d
186 CharsToUnicodeString("1999\\u5E741\\u670813\\u65E5"), // 03: yMMMd -> y\u5E74M\u6708d\u65E5
187 UnicodeString("1/13"), // 04: Md -> M/d
188 CharsToUnicodeString("1\\u670813\\u65E5"), // 05: MMMd -> M\u6708d\u65E5
189 CharsToUnicodeString("1\\u670813\\u65E5"), // 06: MMMMd -> M\u6708d\u65E5
190 CharsToUnicodeString("1999/Q1"), // 07: yQQQ -> y/QQQ
191 CharsToUnicodeString("\\u5348\\u5F8C11:58"), // 08: hhmm
192 UnicodeString("23:58"), // 09: HHmm -> HH:mm
193 UnicodeString("23:58"), // 10: jjmm
194 UnicodeString("58:59"), // 11: mmss -> mm:ss
195 CharsToUnicodeString("1999\\u5E741\\u6708"), // 12: yyyyMMMM -> y\u5E74M\u6708
196 CharsToUnicodeString("1\\u670813\\u65E5(\\u6C34)"), // 13: MMMEd -> M\u6708d\u65E5(EEE)
197 CharsToUnicodeString("13\\u65E5(\\u6C34)"), // 14: Ed -> d\u65E5(EEE)
198 UnicodeString("23:58:59.123"), // 15: jmmssSSS -> "H:mm:ss.SSS"
199 UnicodeString("23:58"), // 16: JJmm
200
201 // ja@calendar=japanese // 6 ja@calendar=japanese
202 CharsToUnicodeString("\\u5E73\\u621011/1"), // 00: yM -> Gy/m
203 CharsToUnicodeString("\\u5E73\\u621011\\u5E741\\u6708"), // 01: yMMM -> Gy\u5E74M\u6708
204 CharsToUnicodeString("\\u5E73\\u621011/1/13"), // 02: yMd -> Gy/m/d
205 CharsToUnicodeString("\\u5E73\\u621011\\u5E741\\u670813\\u65E5"), // 03: yMMMd -> Gy\u5E74M\u6708d\u65E5
206 UnicodeString("1/13"), // 04: Md -> M/d
207 CharsToUnicodeString("1\\u670813\\u65E5"), // 05: MMMd -> M\u6708d\u65E5
208 CharsToUnicodeString("1\\u670813\\u65E5"), // 06: MMMMd -> M\u6708d\u65E5
209 CharsToUnicodeString("\\u5E73\\u621011/Q1"), // 07: yQQQ -> Gy/QQQ
210 CharsToUnicodeString("\\u5348\\u5F8C11:58"), // 08: hhmm ->
211 UnicodeString("23:58"), // 09: HHmm -> HH:mm (as for ja)
212 UnicodeString("23:58"), // 10: jjmm
213 UnicodeString("58:59"), // 11: mmss -> mm:ss (as for ja)
214 CharsToUnicodeString("\\u5E73\\u621011\\u5E741\\u6708"), // 12: yyyyMMMM -> Gyyyy\u5E74M\u6708
215 CharsToUnicodeString("1\\u670813\\u65E5(\\u6C34)"), // 13: MMMEd -> M\u6708d\u65E5(EEE)
216 CharsToUnicodeString("13\\u65E5(\\u6C34)"), // 14: Ed -> d\u65E5(EEE)
217 UnicodeString("23:58:59.123"), // 15: jmmssSSS -> "H:mm:ss.SSS"
218 UnicodeString("23:58"), // 16: JJmm
219
220 // zh_Hans_CN // 7 zh_Hans_CN
221 CharsToUnicodeString("1999\\u5E741\\u6708"), // 00: yM -> y\u5E74M\u6708
222 CharsToUnicodeString("1999\\u5E741\\u6708"), // 01: yMMM -> yyyy\u5E74MMM (fixed expected result per ticket:6626:)
223 CharsToUnicodeString("1999/1/13"), // 02: yMd
224 CharsToUnicodeString("1999\\u5E741\\u670813\\u65E5"), // 03: yMMMd -> yyyy\u5E74MMMd\u65E5 (fixed expected result per ticket:6626:)
225 UnicodeString("1/13"), // 04: Md
226 CharsToUnicodeString("1\\u670813\\u65E5"), // 05: MMMd -> M\u6708d\u65E5 (fixed expected result per ticket:6626:)
227 CharsToUnicodeString("1\\u670813\\u65E5"), // 06: MMMMd -> M\u6708d\u65E5
228 CharsToUnicodeString("1999\\u5E74\\u7B2C1\\u5B63\\u5EA6"), // 07: yQQQ
229 CharsToUnicodeString("\\u4E0B\\u534811:58"), // 08: hhmm
230 UnicodeString("23:58"), // 09: HHmm
231 CharsToUnicodeString("\\u4E0B\\u534811:58"), // 10: jjmm
232 UnicodeString("58:59"), // 11: mmss
233 CharsToUnicodeString("1999\\u5E741\\u6708"), // 12: yyyyMMMM -> yyyy\u5E74MMM
234 CharsToUnicodeString("1\\u670813\\u65E5\\u5468\\u4E09"), // 13: MMMEd -> MMMd\u65E5EEE
235 CharsToUnicodeString("13\\u65E5\\u5468\\u4E09"), // 14: Ed -> d\u65E5EEE
236 CharsToUnicodeString("\\u4E0B\\u534811:58:59.123"), // 15: jmmssSSS -> "ah:mm:ss.SSS"
237 UnicodeString("11:58"), // 16: JJmm
238
239 // zh_TW@calendar=roc // 8 zh_TW@calendar=roc
240 CharsToUnicodeString("\\u6C11\\u570B88/1"), // 00: yM -> Gy/M
241 CharsToUnicodeString("\\u6C11\\u570B88\\u5E741\\u6708"), // 01: yMMM -> Gy\u5E74M\u6708
242 CharsToUnicodeString("\\u6C11\\u570B88/1/13"), // 02: yMd -> Gy/M/d
243 CharsToUnicodeString("\\u6C11\\u570B88\\u5E741\\u670813\\u65E5"), // 03: yMMMd -> Gy\u5E74M\u6708d\u65E5
244 UnicodeString("1/13"), // 04: Md -> M/d
245 CharsToUnicodeString("1\\u670813\\u65E5"), // 05: MMMd ->M\u6708d\u65E5
246 CharsToUnicodeString("1\\u670813\\u65E5"), // 06: MMMMd ->M\u6708d\u65E5
247 CharsToUnicodeString("\\u6C11\\u570B88\\u5E74\\u7B2C1\\u5B63"), // 07: yQQQ -> Gy QQQ
248 CharsToUnicodeString("\\u4E0B\\u534811:58"), // 08: hhmm ->
249 UnicodeString("23:58"), // 09: HHmm ->
250 CharsToUnicodeString("\\u4E0B\\u534811:58"), // 10: jjmm
251 UnicodeString("58:59"), // 11: mmss ->
252 CharsToUnicodeString("\\u6C11\\u570B88\\u5E741\\u6708"), // 12: yyyyMMMM -> Gy\u5E74M\u670
253 CharsToUnicodeString("1\\u670813\\u65E5\\u9031\\u4E09"), // 13: MMMEd -> M\u6708d\u65E5EEE
254 CharsToUnicodeString("13 \\u9031\\u4E09"), // 14: Ed -> d E
255 CharsToUnicodeString("\\u4E0B\\u534811:58:59.123"), // 15: jmmssSSS -> "ah:mm:ss.SSS"
256 UnicodeString("11:58"), // 16: JJmm
257
258 // ru // 9 ru
259 UnicodeString("01.1999"), // 00: yM -> MM.y
260 CharsToUnicodeString("\\u044F\\u043D\\u0432. 1999 \\u0433."), // 01: yMMM -> LLL y
261 UnicodeString("13.01.1999"), // 02: yMd -> dd.MM.y
262 CharsToUnicodeString("13 \\u044F\\u043D\\u0432. 1999 \\u0433."), // 03: yMMMd -> d MMM y
263 UnicodeString("13.01"), // 04: Md -> dd.MM
264 CharsToUnicodeString("13 \\u044F\\u043D\\u0432."), // 05: MMMd -> d MMM
265 CharsToUnicodeString("13 \\u044F\\u043D\\u0432\\u0430\\u0440\\u044F"), // 06: MMMMd -> d MMMM
266 CharsToUnicodeString("1-\\u0439 \\u043A\\u0432. 1999 \\u0433."), // 07: yQQQ -> y QQQ
267 CharsToUnicodeString("11:58 PM"), // 08: hhmm -> hh:mm a
268 UnicodeString("23:58"), // 09: HHmm -> HH:mm
269 UnicodeString("23:58"), // 10: jjmm -> HH:mm
270 UnicodeString("58:59"), // 11: mmss -> mm:ss
271 CharsToUnicodeString("\\u044F\\u043D\\u0432\\u0430\\u0440\\u044C 1999 \\u0433."), // 12: yyyyMMMM -> LLLL y
272 CharsToUnicodeString("\\u0441\\u0440, 13 \\u044F\\u043D\\u0432."), // 13: MMMEd -> ccc, d MMM
273 CharsToUnicodeString("\\u0441\\u0440, 13"), // 14: Ed -> EEE, d
274 UnicodeString("23:58:59,123"), // 15: jmmssSSS -> "H:mm:ss,SSS"
275 UnicodeString("23:58"), // 16: JJmm
276
277 // zh@calendar=chinese // 10 zh@calendar=chinese
278 CharsToUnicodeString("1998\\u620A\\u5BC5\\u5E74\\u5341\\u4E00\\u6708"), // 00: yMMM
279 CharsToUnicodeString("1998\\u620A\\u5BC5\\u5E74\\u5341\\u4E00\\u6708"), // 01: yMMM
280 CharsToUnicodeString("1998\\u5E74\\u5341\\u4E00\\u670826"), // 02: yMMMd
281 CharsToUnicodeString("1998\\u5E74\\u5341\\u4E00\\u670826"), // 03: yMMMd
282 UnicodeString("11-26"), // 04: Md
283 CharsToUnicodeString("\\u5341\\u4E00\\u670826\\u65E5"), // 05: MMMd
284 CharsToUnicodeString("\\u5341\\u4E00\\u670826\\u65E5"), // 06: MMMMd
285 CharsToUnicodeString("1998\\u620A\\u5BC5\\u5E74\\u7b2c\\u56db\\u5B63\\u5EA6"), // 07: yQQQ
286 CharsToUnicodeString("\\u4E0B\\u534811:58"), // 08: hhmm
287 UnicodeString("23:58"), // 09: HHmm
288 CharsToUnicodeString("\\u4E0B\\u534811:58"), // 10: jjmm
289 UnicodeString("58:59"), // 11: mmss
290 CharsToUnicodeString("1998\\u620A\\u5BC5\\u5E74\\u5341\\u4E00\\u6708"), // 12: yyyyMMMM
291 CharsToUnicodeString("\\u5341\\u4E00\\u670826\\u65E5\\u5468\\u4E09"), // 13: MMMEd
292 CharsToUnicodeString("26\\u65E5\\u5468\\u4E09"), // 14: Ed -> d\u65E5EEE
293 CharsToUnicodeString("\\u4E0B\\u534811:58:59.123"), // 15: jmmssSS
294 UnicodeString("11:58"), // 16: JJmm
295
296 UnicodeString(),
297 };
298
299 UnicodeString patternTests2[] = {
300 UnicodeString("yyyyMMMdd"),
301 UnicodeString("yyyyqqqq"),
302 UnicodeString("yMMMdd"),
303 UnicodeString("EyyyyMMMdd"),
304 UnicodeString("yyyyMMdd"),
305 UnicodeString("yyyyMMM"),
306 UnicodeString("yyyyMM"),
307 UnicodeString("yyMM"),
308 UnicodeString("yMMMMMd"),
309 UnicodeString("EEEEEMMMMMd"),
310 UnicodeString("MMMd"),
311 UnicodeString("MMMdhmm"),
312 UnicodeString("EMMMdhmms"),
313 UnicodeString("MMdhmm"),
314 UnicodeString("EEEEMMMdhmms"),
315 UnicodeString("yyyyMMMddhhmmss"),
316 UnicodeString("EyyyyMMMddhhmmss"),
317 UnicodeString("hmm"),
318 UnicodeString("hhmm"),
319 UnicodeString("hhmmVVVV"),
320 UnicodeString(""),
321 };
322 UnicodeString patternResults2[] = {
323 UnicodeString("Oct 14, 1999"),
324 UnicodeString("4th quarter 1999"),
325 UnicodeString("Oct 14, 1999"),
326 UnicodeString("Thu, Oct 14, 1999"),
327 UnicodeString("10/14/1999"),
328 UnicodeString("Oct 1999"),
329 UnicodeString("10/1999"),
330 UnicodeString("10/99"),
331 UnicodeString("O 14, 1999"),
332 UnicodeString("T, O 14"),
333 UnicodeString("Oct 14"),
334 UnicodeString("Oct 14, 6:58 AM"),
335 UnicodeString("Thu, Oct 14, 6:58:59 AM"),
336 UnicodeString("10/14, 6:58 AM"),
337 UnicodeString("Thursday, Oct 14, 6:58:59 AM"),
338 UnicodeString("Oct 14, 1999, 6:58:59 AM"),
339 UnicodeString("Thu, Oct 14, 1999, 6:58:59 AM"),
340 UnicodeString("6:58 AM"),
341 UnicodeString("6:58 AM"),
342 UnicodeString("6:58 AM GMT"),
343 UnicodeString(""),
344 };
345
346 // results for getSkeletons() and getPatternForSkeleton()
347 const UnicodeString testSkeletonsResults[] = {
348 UnicodeString("HH:mm"),
349 UnicodeString("MMMMd"),
350 UnicodeString("MMMMMdd"),
351 };
352
353 const UnicodeString testBaseSkeletonsResults[] = {
354 UnicodeString("Hm"),
355 UnicodeString("MMMMd"),
356 UnicodeString("MMMMMd"),
357 };
358
359 const char* testGetSkeletonAndBase[][3] = {
360 // pattern skeleton baseSkeleton
361 { "dd-MMM", "MMMdd", "MMMd" },
362 { "dd/MMMM/yy", "yyMMMMdd", "yMMMMd" },
363 { "h", "h", "h" },
364 { "ah", "ah", "ah" },
365 { "aaaah", "aaaah", "aaaah" },
366 { "Bh", "Bh", "Bh" }
367 };
368
369 UnicodeString newDecimal(" "); // space
370 UnicodeString newAppendItemName("hrs.");
371 UnicodeString newAppendItemFormat("{1} {0}");
372 UnicodeString newDateTimeFormat("{1} {0}");
373 UErrorCode status = U_ZERO_ERROR;
374 UnicodeString conflictingPattern;
375 UDateTimePatternConflict conflictingStatus = UDATPG_NO_CONFLICT;
376 (void)conflictingStatus; // Suppress set but not used warning.
377
378 // ======= Test CreateInstance with default locale
379 logln("Testing DateTimePatternGenerator createInstance from default locale");
380
381 DateTimePatternGenerator *instFromDefaultLocale=DateTimePatternGenerator::createInstance(status);
382 if (U_FAILURE(status)) {
383 dataerrln("ERROR: Could not create DateTimePatternGenerator (default) - exitting");
384 return;
385 }
386 else {
387 delete instFromDefaultLocale;
388 }
389
390 // ======= Test CreateInstance with given locale
391 logln("Testing DateTimePatternGenerator createInstance from French locale");
392 status = U_ZERO_ERROR;
393 DateTimePatternGenerator *instFromLocale=DateTimePatternGenerator::createInstance(Locale::getFrench(), status);
394 if (U_FAILURE(status)) {
395 dataerrln("ERROR: Could not create DateTimePatternGenerator (Locale::getFrench()) - exitting");
396 return;
397 }
398
399 // ======= Test clone DateTimePatternGenerator
400 logln("Testing DateTimePatternGenerator::clone()");
401 status = U_ZERO_ERROR;
402
403
404 UnicodeString decimalSymbol = instFromLocale->getDecimal();
405 UnicodeString newDecimalSymbol = UnicodeString("*");
406 decimalSymbol = instFromLocale->getDecimal();
407 instFromLocale->setDecimal(newDecimalSymbol);
408 DateTimePatternGenerator *cloneDTPatternGen=instFromLocale->clone();
409 decimalSymbol = cloneDTPatternGen->getDecimal();
410 if (decimalSymbol != newDecimalSymbol) {
411 errln("ERROR: inconsistency is found in cloned object.");
412 }
413 if ( !(*cloneDTPatternGen == *instFromLocale) ) {
414 errln("ERROR: inconsistency is found in cloned object.");
415 }
416
417 if ( *cloneDTPatternGen != *instFromLocale ) {
418 errln("ERROR: inconsistency is found in cloned object.");
419 }
420
421 delete instFromLocale;
422 delete cloneDTPatternGen;
423
424 // ======= Test simple use cases
425 logln("Testing simple use cases");
426 status = U_ZERO_ERROR;
427 Locale deLocale=Locale::getGermany();
428 UDate sampleDate=LocaleTest::date(99, 9, 13, 23, 58, 59);
429 DateTimePatternGenerator *gen = DateTimePatternGenerator::createInstance(deLocale, status);
430 if (U_FAILURE(status)) {
431 dataerrln("ERROR: Could not create DateTimePatternGenerator (Locale::getGermany()) - exitting");
432 return;
433 }
434 UnicodeString findPattern = gen->getBestPattern(UnicodeString("MMMddHmm"), status);
435 SimpleDateFormat *format = new SimpleDateFormat(findPattern, deLocale, status);
436 if (U_FAILURE(status)) {
437 dataerrln("ERROR: Could not create SimpleDateFormat (Locale::getGermany())");
438 delete gen;
439 return;
440 }
441 TimeZone *zone = TimeZone::createTimeZone(UnicodeString("ECT"));
442 if (zone==NULL) {
443 dataerrln("ERROR: Could not create TimeZone ECT");
444 delete gen;
445 delete format;
446 return;
447 }
448 format->setTimeZone(*zone);
449 UnicodeString dateReturned, expectedResult;
450 dateReturned.remove();
451 dateReturned = format->format(sampleDate, dateReturned, status);
452 expectedResult=UnicodeString("14. Okt., 08:58", -1, US_INV);
453 if ( dateReturned != expectedResult ) {
454 errln("ERROR: Simple test in getBestPattern with Locale::getGermany()).");
455 }
456 // add new pattern
457 status = U_ZERO_ERROR;
458 conflictingStatus = gen->addPattern(UnicodeString("d'. von' MMMM", -1, US_INV), true, conflictingPattern, status);
459 if (U_FAILURE(status)) {
460 errln("ERROR: Could not addPattern - d\'. von\' MMMM");
461 }
462 status = U_ZERO_ERROR;
463 UnicodeString testPattern=gen->getBestPattern(UnicodeString("MMMMdd"), status);
464 testPattern=gen->getBestPattern(UnicodeString("MMMddHmm"), status);
465 format->applyPattern(gen->getBestPattern(UnicodeString("MMMMdHmm"), status));
466 dateReturned.remove();
467 dateReturned = format->format(sampleDate, dateReturned, status);
468 expectedResult=UnicodeString("14. von Oktober, 08:58", -1, US_INV);
469 if ( dateReturned != expectedResult ) {
470 errln(UnicodeString("ERROR: Simple test addPattern failed!: d\'. von\' MMMM Got: ") + dateReturned + UnicodeString(" Expected: ") + expectedResult);
471 }
472 delete format;
473
474 // get a pattern and modify it
475 format = (SimpleDateFormat *)DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull,
476 deLocale);
477 format->setTimeZone(*zone);
478 UnicodeString pattern;
479 pattern = format->toPattern(pattern);
480 dateReturned.remove();
481 dateReturned = format->format(sampleDate, dateReturned, status);
482 expectedResult=CharsToUnicodeString("Donnerstag, 14. Oktober 1999 um 08:58:59 Mitteleurop\\u00E4ische Sommerzeit");
483 if ( dateReturned != expectedResult ) {
484 errln("ERROR: Simple test uses full date format.");
485 errln(UnicodeString(" Got: ") + dateReturned + UnicodeString(" Expected: ") + expectedResult);
486 }
487
488 // modify it to change the zone.
489 UnicodeString newPattern = gen->replaceFieldTypes(pattern, UnicodeString("vvvv"), status);
490 format->applyPattern(newPattern);
491 dateReturned.remove();
492 dateReturned = format->format(sampleDate, dateReturned, status);
493 expectedResult=CharsToUnicodeString("Donnerstag, 14. Oktober 1999 um 08:58:59 Mitteleurop\\u00E4ische Zeit");
494 if ( dateReturned != expectedResult ) {
495 errln("ERROR: Simple test modify the timezone!");
496 errln(UnicodeString(" Got: ")+ dateReturned + UnicodeString(" Expected: ") + expectedResult);
497 }
498
499 // setDeciaml(), getDeciaml()
500 gen->setDecimal(newDecimal);
501 if (newDecimal != gen->getDecimal()) {
502 errln("ERROR: unexpected result from setDecimal() and getDecimal()!.\n");
503 }
504
505 // setAppenItemName() , getAppendItemName()
506 gen->setAppendItemName(UDATPG_HOUR_FIELD, newAppendItemName);
507 if (newAppendItemName != gen->getAppendItemName(UDATPG_HOUR_FIELD)) {
508 errln("ERROR: unexpected result from setAppendItemName() and getAppendItemName()!.\n");
509 }
510
511 // setAppenItemFormat() , getAppendItemFormat()
512 gen->setAppendItemFormat(UDATPG_HOUR_FIELD, newAppendItemFormat);
513 if (newAppendItemFormat != gen->getAppendItemFormat(UDATPG_HOUR_FIELD)) {
514 errln("ERROR: unexpected result from setAppendItemFormat() and getAppendItemFormat()!.\n");
515 }
516
517 // setDateTimeFormat() , getDateTimeFormat()
518 gen->setDateTimeFormat(newDateTimeFormat);
519 if (newDateTimeFormat != gen->getDateTimeFormat()) {
520 errln("ERROR: unexpected result from setDateTimeFormat() and getDateTimeFormat()!.\n");
521 }
522
523 // ======== Test getSkeleton and getBaseSkeleton
524
525 int32_t i, count = UPRV_LENGTHOF(testGetSkeletonAndBase);
526 for (i = 0; i < count; i++) {
527 status = U_ZERO_ERROR;
528 pattern = UnicodeString(testGetSkeletonAndBase[i][0]);
529 UnicodeString expectedSkeleton = UnicodeString(testGetSkeletonAndBase[i][1]);
530 UnicodeString expectedBaseSkeleton = UnicodeString(testGetSkeletonAndBase[i][2]);
531 UnicodeString retSkeleton = gen->getSkeleton(pattern, status);
532 if(U_FAILURE(status) || retSkeleton != expectedSkeleton ) {
533 errln("ERROR: Unexpected result from getSkeleton().\n");
534 errln(UnicodeString(" Got: ") + retSkeleton + UnicodeString(" Expected: ") + expectedSkeleton );
535 }
536 retSkeleton = gen->getBaseSkeleton(pattern, status);
537 if(U_FAILURE(status) || retSkeleton != expectedBaseSkeleton) {
538 errln("ERROR: Unexpected result from getBaseSkeleton().\n");
539 errln(UnicodeString(" Got: ") + retSkeleton + UnicodeString(" Expected:")+ expectedBaseSkeleton);
540 }
541 }
542
543 delete format;
544 delete zone;
545 delete gen;
546
547 {
548 // Trac# 6104
549 status = U_ZERO_ERROR;
550 pattern = UnicodeString("YYYYMMM");
551 UnicodeString expR = CharsToUnicodeString("1999\\u5E741\\u6708"); // fixed expected result per ticket:6626:
552 Locale loc("ja");
553 UDate testDate1= LocaleTest::date(99, 0, 13, 23, 58, 59);
554 DateTimePatternGenerator *patGen=DateTimePatternGenerator::createInstance(loc, status);
555 if(U_FAILURE(status)) {
556 dataerrln("ERROR: Could not create DateTimePatternGenerator");
557 return;
558 }
559 UnicodeString bPattern = patGen->getBestPattern(pattern, status);
560 UnicodeString rDate;
561 SimpleDateFormat sdf(bPattern, loc, status);
562 rDate.remove();
563 rDate = sdf.format(testDate1, rDate);
564
565 logln(UnicodeString(" ja locale with skeleton: YYYYMMM Best Pattern:") + bPattern);
566 logln(UnicodeString(" Formatted date:") + rDate);
567
568 if ( expR!= rDate ) {
569 errln(UnicodeString("\nERROR: Test Japanese month hack Got: ") + rDate +
570 UnicodeString(" Expected: ") + expR );
571 }
572
573 delete patGen;
574 }
575 { // Trac# 6104
576 Locale loc("zh");
577 UnicodeString expR = CharsToUnicodeString("1999\\u5E741\\u6708"); // fixed expected result per ticket:6626:
578 UDate testDate1= LocaleTest::date(99, 0, 13, 23, 58, 59);
579 DateTimePatternGenerator *patGen=DateTimePatternGenerator::createInstance(loc, status);
580 if(U_FAILURE(status)) {
581 dataerrln("ERROR: Could not create DateTimePatternGenerator");
582 return;
583 }
584 UnicodeString bPattern = patGen->getBestPattern(pattern, status);
585 UnicodeString rDate;
586 SimpleDateFormat sdf(bPattern, loc, status);
587 rDate.remove();
588 rDate = sdf.format(testDate1, rDate);
589
590 logln(UnicodeString(" zh locale with skeleton: YYYYMMM Best Pattern:") + bPattern);
591 logln(UnicodeString(" Formatted date:") + rDate);
592 if ( expR!= rDate ) {
593 errln(UnicodeString("\nERROR: Test Chinese month hack Got: ") + rDate +
594 UnicodeString(" Expected: ") + expR );
595 }
596 delete patGen;
597 }
598
599 {
600 // Trac# 6172 duplicate time pattern
601 status = U_ZERO_ERROR;
602 pattern = UnicodeString("hmv");
603 UnicodeString expR = UnicodeString("h:mm a v"); // avail formats has hm -> "h:mm a" (fixed expected result per ticket:6626:)
604 Locale loc("en");
605 DateTimePatternGenerator *patGen=DateTimePatternGenerator::createInstance(loc, status);
606 if(U_FAILURE(status)) {
607 dataerrln("ERROR: Could not create DateTimePatternGenerator");
608 return;
609 }
610 UnicodeString bPattern = patGen->getBestPattern(pattern, status);
611 logln(UnicodeString(" en locale with skeleton: hmv Best Pattern:") + bPattern);
612
613 if ( expR!= bPattern ) {
614 errln(UnicodeString("\nERROR: Test EN time format Got: ") + bPattern +
615 UnicodeString(" Expected: ") + expR );
616 }
617
618 delete patGen;
619 }
620
621
622 // ======= Test various skeletons.
623 logln("Testing DateTimePatternGenerator with various skeleton");
624
625 status = U_ZERO_ERROR;
626 int32_t localeIndex=0;
627 int32_t resultIndex=0;
628 UnicodeString resultDate;
629 UDate testDate= LocaleTest::date(99, 0, 13, 23, 58, 59) + 123.0;
630 while (localeIndex < MAX_LOCALE )
631 {
632 int32_t dataIndex=0;
633 UnicodeString bestPattern;
634
635 Locale loc(testLocale[localeIndex][0], testLocale[localeIndex][1], testLocale[localeIndex][2], testLocale[localeIndex][3]);
636 logln("\n\n Locale: %s_%s_%s@%s", testLocale[localeIndex][0], testLocale[localeIndex][1], testLocale[localeIndex][2], testLocale[localeIndex][3]);
637 DateTimePatternGenerator *patGen=DateTimePatternGenerator::createInstance(loc, status);
638 if(U_FAILURE(status)) {
639 dataerrln("ERROR: Could not create DateTimePatternGenerator with locale index:%d . - exitting\n", localeIndex);
640 return;
641 }
642 while (patternData[dataIndex].length() > 0) {
643 log(patternData[dataIndex]);
644 bestPattern = patGen->getBestPattern(patternData[dataIndex++], status);
645 logln(UnicodeString(" -> ") + bestPattern);
646
647 SimpleDateFormat sdf(bestPattern, loc, status);
648 resultDate.remove();
649 resultDate = sdf.format(testDate, resultDate);
650 if ( resultDate != patternResults[resultIndex] ) {
651 errln(UnicodeString("\nERROR: Test various skeletons[") + (dataIndex-1) + UnicodeString("], localeIndex ") + localeIndex +
652 UnicodeString(". Got: \"") + resultDate + UnicodeString("\" Expected: \"") + patternResults[resultIndex] + "\"" );
653 }
654
655 resultIndex++;
656 }
657 delete patGen;
658 localeIndex++;
659 }
660
661 // ======= More tests ticket#6110
662 logln("Testing DateTimePatternGenerator with various skeleton");
663
664 status = U_ZERO_ERROR;
665 localeIndex=0;
666 resultIndex=0;
667 testDate= LocaleTest::date(99, 9, 13, 23, 58, 59);
668 {
669 int32_t dataIndex=0;
670 UnicodeString bestPattern;
671 logln("\n\n Test various skeletons for English locale...");
672 DateTimePatternGenerator *patGen=DateTimePatternGenerator::createInstance(Locale::getEnglish(), status);
673 if(U_FAILURE(status)) {
674 dataerrln("ERROR: Could not create DateTimePatternGenerator with locale English . - exitting\n");
675 return;
676 }
677 TimeZone *enZone = TimeZone::createTimeZone(UnicodeString("ECT/GMT"));
678 if (enZone==NULL) {
679 dataerrln("ERROR: Could not create TimeZone ECT");
680 delete patGen;
681 return;
682 }
683 SimpleDateFormat *enFormat = (SimpleDateFormat *)DateFormat::createDateTimeInstance(DateFormat::kFull,
684 DateFormat::kFull, Locale::getEnglish());
685 enFormat->setTimeZone(*enZone);
686 while (patternTests2[dataIndex].length() > 0) {
687 logln(patternTests2[dataIndex]);
688 bestPattern = patGen->getBestPattern(patternTests2[dataIndex], status);
689 logln(UnicodeString(" -> ") + bestPattern);
690 enFormat->applyPattern(bestPattern);
691 resultDate.remove();
692 resultDate = enFormat->format(testDate, resultDate);
693 if ( resultDate != patternResults2[resultIndex] ) {
694 errln(UnicodeString("\nERROR: Test various skeletons[") + dataIndex
695 + UnicodeString("]. Got: ") + resultDate + UnicodeString(" Expected: ") +
696 patternResults2[resultIndex] );
697 }
698 dataIndex++;
699 resultIndex++;
700 }
701 delete patGen;
702 delete enZone;
703 delete enFormat;
704 }
705
706
707
708 // ======= Test random skeleton
709 DateTimePatternGenerator *randDTGen= DateTimePatternGenerator::createInstance(status);
710 if (U_FAILURE(status)) {
711 dataerrln("ERROR: Could not create DateTimePatternGenerator (Locale::getFrench()) - exitting");
712 return;
713 }
714 UChar newChar;
715 for (i=0; i<10; ++i) {
716 UnicodeString randomSkeleton;
717 int32_t len = rand() % 20;
718 for (int32_t j=0; j<len; ++j ) {
719 while ((newChar = (UChar)(rand()%0x7f))>=(UChar)0x20) {
720 randomSkeleton += newChar;
721 }
722 }
723 UnicodeString bestPattern = randDTGen->getBestPattern(randomSkeleton, status);
724 }
725 delete randDTGen;
726
727 // UnicodeString randomString=Unicode
728 // ======= Test getStaticClassID()
729
730 logln("Testing getStaticClassID()");
731 status = U_ZERO_ERROR;
732 DateTimePatternGenerator *test= DateTimePatternGenerator::createInstance(status);
733
734 if(test->getDynamicClassID() != DateTimePatternGenerator::getStaticClassID()) {
735 errln("ERROR: getDynamicClassID() didn't return the expected value");
736 }
737 delete test;
738
739 // ====== Test createEmptyInstance()
740
741 logln("Testing createEmptyInstance()");
742 status = U_ZERO_ERROR;
743
744 test = DateTimePatternGenerator::createEmptyInstance(status);
745 if(U_FAILURE(status)) {
746 errln("ERROR: Fail to create an empty instance ! - exitting.\n");
747 delete test;
748 return;
749 }
750
751 conflictingStatus = test->addPattern(UnicodeString("MMMMd"), true, conflictingPattern, status);
752 status = U_ZERO_ERROR;
753 testPattern=test->getBestPattern(UnicodeString("MMMMdd"), status);
754 conflictingStatus = test->addPattern(UnicodeString("HH:mm"), true, conflictingPattern, status);
755 conflictingStatus = test->addPattern(UnicodeString("MMMMMdd"), true, conflictingPattern, status); //duplicate pattern
756 StringEnumeration *output=NULL;
757 output = test->getRedundants(status);
758 expectedResult=UnicodeString("MMMMd");
759 if (output != NULL) {
760 output->reset(status);
761 const UnicodeString *dupPattern=output->snext(status);
762 if ( (dupPattern==NULL) || (*dupPattern != expectedResult) ) {
763 errln("ERROR: Fail in getRedundants !\n");
764 }
765 }
766
767 // ======== Test getSkeletons and getBaseSkeletons
768 StringEnumeration* ptrSkeletonEnum = test->getSkeletons(status);
769 if(U_FAILURE(status)) {
770 errln("ERROR: Fail to get skeletons !\n");
771 }
772 UnicodeString returnPattern, *ptrSkeleton;
773 ptrSkeletonEnum->reset(status);
774 count=ptrSkeletonEnum->count(status);
775 for (i=0; i<count; ++i) {
776 ptrSkeleton = (UnicodeString *)ptrSkeletonEnum->snext(status);
777 returnPattern = test->getPatternForSkeleton(*ptrSkeleton);
778 if ( returnPattern != testSkeletonsResults[i] ) {
779 errln(UnicodeString("ERROR: Unexpected result from getSkeletons and getPatternForSkeleton\nGot: ") + returnPattern
780 + UnicodeString("\nExpected: ") + testSkeletonsResults[i]
781 + UnicodeString("\n"));
782 }
783 }
784 StringEnumeration* ptrBaseSkeletonEnum = test->getBaseSkeletons(status);
785 if(U_FAILURE(status)) {
786 errln("ERROR: Fail to get base skeletons !\n");
787 }
788 count=ptrBaseSkeletonEnum->count(status);
789 for (i=0; i<count; ++i) {
790 ptrSkeleton = (UnicodeString *)ptrBaseSkeletonEnum->snext(status);
791 if ( *ptrSkeleton != testBaseSkeletonsResults[i] ) {
792 errln("ERROR: Unexpected result from getBaseSkeletons() !\n");
793 }
794 }
795
796 // ========= DateTimePatternGenerator sample code in Userguide
797 // set up the generator
798 Locale locale = Locale::getFrench();
799 status = U_ZERO_ERROR;
800 DateTimePatternGenerator *generator = DateTimePatternGenerator::createInstance( locale, status);
801
802 // get a pattern for an abbreviated month and day
803 pattern = generator->getBestPattern(UnicodeString("MMMd"), status);
804 SimpleDateFormat formatter(pattern, locale, status);
805
806 zone = TimeZone::createTimeZone(UnicodeString("GMT"));
807 formatter.setTimeZone(*zone);
808 // use it to format (or parse)
809 UnicodeString formatted;
810 formatted = formatter.format(Calendar::getNow(), formatted, status);
811 // for French, the result is "13 sept."
812 formatted.remove();
813 // cannot use the result from getNow() because the value change evreyday.
814 testDate= LocaleTest::date(99, 0, 13, 23, 58, 59);
815 formatted = formatter.format(testDate, formatted, status);
816 expectedResult=UnicodeString("14 janv.");
817 if ( formatted != expectedResult ) {
818 errln("ERROR: Userguide sample code result!");
819 errln(UnicodeString(" Got: ")+ formatted + UnicodeString(" Expected: ") + expectedResult);
820 }
821
822 delete zone;
823 delete output;
824 delete ptrSkeletonEnum;
825 delete ptrBaseSkeletonEnum;
826 delete test;
827 delete generator;
828 }
829
830 /**
831 * Test handling of options
832 *
833 * For reference, as of ICU 4.3.3,
834 * root/gregorian has
835 * Hm{"H:mm"}
836 * Hms{"H:mm:ss"}
837 * hm{"h:mm a"}
838 * hms{"h:mm:ss a"}
839 * en/gregorian has
840 * Hm{"H:mm"}
841 * Hms{"H:mm:ss"}
842 * hm{"h:mm a"}
843 * be/gregorian has
844 * HHmmss{"HH.mm.ss"}
845 * Hm{"HH.mm"}
846 * hm{"h.mm a"}
847 * hms{"h.mm.ss a"}
848 */
849 typedef struct DTPtnGenOptionsData {
850 const char *locale;
851 const char *skel;
852 const char *expectedPattern;
853 UDateTimePatternMatchOptions options;
854 } DTPtnGenOptionsData;
testOptions()855 void IntlTestDateTimePatternGeneratorAPI::testOptions(/*char *par*/)
856 {
857 DTPtnGenOptionsData testData[] = {
858 // locale skel expectedPattern options
859 { "en", "Hmm", "HH:mm", UDATPG_MATCH_NO_OPTIONS },
860 { "en", "HHmm", "HH:mm", UDATPG_MATCH_NO_OPTIONS },
861 { "en", "hhmm", "h:mm a", UDATPG_MATCH_NO_OPTIONS },
862 { "en", "Hmm", "HH:mm", UDATPG_MATCH_HOUR_FIELD_LENGTH },
863 { "en", "HHmm", "HH:mm", UDATPG_MATCH_HOUR_FIELD_LENGTH },
864 { "en", "hhmm", "hh:mm a", UDATPG_MATCH_HOUR_FIELD_LENGTH },
865 { "da", "Hmm", "HH.mm", UDATPG_MATCH_NO_OPTIONS },
866 { "da", "HHmm", "HH.mm", UDATPG_MATCH_NO_OPTIONS },
867 { "da", "hhmm", "h.mm a", UDATPG_MATCH_NO_OPTIONS },
868 { "da", "Hmm", "H.mm", UDATPG_MATCH_HOUR_FIELD_LENGTH },
869 { "da", "HHmm", "HH.mm", UDATPG_MATCH_HOUR_FIELD_LENGTH },
870 { "da", "hhmm", "hh.mm a", UDATPG_MATCH_HOUR_FIELD_LENGTH },
871 //
872 { "en", "yyyy", "yyyy", UDATPG_MATCH_NO_OPTIONS },
873 { "en", "YYYY", "YYYY", UDATPG_MATCH_NO_OPTIONS },
874 { "en", "U", "y", UDATPG_MATCH_NO_OPTIONS },
875 { "en@calendar=japanese", "yyyy", "y G", UDATPG_MATCH_NO_OPTIONS },
876 { "en@calendar=japanese", "YYYY", "Y G", UDATPG_MATCH_NO_OPTIONS },
877 { "en@calendar=japanese", "U", "y G", UDATPG_MATCH_NO_OPTIONS },
878 { "en@calendar=chinese", "yyyy", "r(U)", UDATPG_MATCH_NO_OPTIONS },
879 { "en@calendar=chinese", "YYYY", "Y(Y)", UDATPG_MATCH_NO_OPTIONS }, // not a good result, want r(Y) or r(U)
880 { "en@calendar=chinese", "U", "r(U)", UDATPG_MATCH_NO_OPTIONS },
881 { "en@calendar=chinese", "Gy", "r(U)", UDATPG_MATCH_NO_OPTIONS },
882 { "en@calendar=chinese", "GU", "r(U)", UDATPG_MATCH_NO_OPTIONS },
883 { "en@calendar=chinese", "ULLL", "MMM U", UDATPG_MATCH_NO_OPTIONS },
884 { "en@calendar=chinese", "yMMM", "MMM r(U)", UDATPG_MATCH_NO_OPTIONS },
885 { "en@calendar=chinese", "GUMMM", "MMM r(U)", UDATPG_MATCH_NO_OPTIONS },
886 { "zh@calendar=chinese", "yyyy", "rU\\u5E74", UDATPG_MATCH_NO_OPTIONS },
887 { "zh@calendar=chinese", "YYYY", "YY\\u5E74", UDATPG_MATCH_NO_OPTIONS }, // not a good result, may want r(Y) or r(U)
888 { "zh@calendar=chinese", "U", "rU\\u5E74", UDATPG_MATCH_NO_OPTIONS },
889 { "zh@calendar=chinese", "Gy", "rU\\u5E74", UDATPG_MATCH_NO_OPTIONS },
890 { "zh@calendar=chinese", "GU", "rU\\u5E74", UDATPG_MATCH_NO_OPTIONS },
891 { "zh@calendar=chinese", "ULLL", "U\\u5E74MMM", UDATPG_MATCH_NO_OPTIONS },
892 { "zh@calendar=chinese", "yMMM", "rU\\u5E74MMM", UDATPG_MATCH_NO_OPTIONS },
893 { "zh@calendar=chinese", "GUMMM", "rU\\u5E74MMM", UDATPG_MATCH_NO_OPTIONS },
894 };
895
896 int count = UPRV_LENGTHOF(testData);
897 const DTPtnGenOptionsData * testDataPtr = testData;
898
899 for (; count-- > 0; ++testDataPtr) {
900 UErrorCode status = U_ZERO_ERROR;
901
902 Locale locale(testDataPtr->locale);
903 UnicodeString skel(testDataPtr->skel);
904 UnicodeString expectedPattern(UnicodeString(testDataPtr->expectedPattern).unescape());
905 UDateTimePatternMatchOptions options = testDataPtr->options;
906
907 DateTimePatternGenerator * dtpgen = DateTimePatternGenerator::createInstance(locale, status);
908 if (U_FAILURE(status)) {
909 dataerrln("Unable to create DateTimePatternGenerator instance for locale(%s): %s", locale.getName(), u_errorName(status));
910 delete dtpgen;
911 continue;
912 }
913 UnicodeString pattern = dtpgen->getBestPattern(skel, options, status);
914 if (pattern.compare(expectedPattern) != 0) {
915 errln( UnicodeString("ERROR in getBestPattern, locale ") + UnicodeString(testDataPtr->locale) +
916 UnicodeString(", skeleton ") + skel +
917 ((options)?UnicodeString(", options!=0"):UnicodeString(", options==0")) +
918 UnicodeString(", expected pattern ") + expectedPattern +
919 UnicodeString(", got ") + pattern );
920 }
921 delete dtpgen;
922 }
923 }
924
925 /**
926 * Test that DTPG can handle all valid pattern character / length combinations
927 *
928 */
929 #define FIELD_LENGTHS_COUNT 6
930 #define FIELD_LENGTH_MAX 8
931 #define MUST_INCLUDE_COUNT 5
932
933 typedef struct AllFieldsTestItem {
934 char patternChar;
935 int8_t fieldLengths[FIELD_LENGTHS_COUNT+1]; // up to FIELD_LENGTHS_COUNT lengths to try
936 // (length <=FIELD_LENGTH_MAX) plus 0 terminator
937 char mustIncludeOneOf[MUST_INCLUDE_COUNT+1];// resulting pattern must include at least one of
938 // these as a pattern char (0-terminated list)
939 } AllFieldsTestItem;
940
testAllFieldPatterns()941 void IntlTestDateTimePatternGeneratorAPI::testAllFieldPatterns(/*char *par*/)
942 {
943 const char * localeNames[] = {
944 "root",
945 "root@calendar=japanese",
946 "root@calendar=chinese",
947 "en",
948 "en@calendar=japanese",
949 "en@calendar=chinese",
950 NULL // terminator
951 };
952 AllFieldsTestItem testData[] = {
953 //pat fieldLengths generated pattern must
954 //chr to test include one of these
955 { 'G', {1,2,3,4,5,0}, "G" }, // era
956 // year
957 { 'y', {1,2,3,4,0}, "yU" }, // year
958 { 'Y', {1,2,3,4,0}, "Y" }, // year for week of year
959 { 'u', {1,2,3,4,5,0}, "yuU" }, // extended year
960 { 'U', {1,2,3,4,5,0}, "yU" }, // cyclic year name
961 // quarter
962 { 'Q', {1,2,3,4,0}, "Qq" }, // x
963 { 'q', {1,2,3,4,0}, "Qq" }, // standalone
964 // month
965 { 'M', {1,2,3,4,5,0}, "ML" }, // x
966 { 'L', {1,2,3,4,5,0}, "ML" }, // standalone
967 // week
968 { 'w', {1,2,0}, "w" }, // week of year
969 { 'W', {1,0}, "W" }, // week of month
970 // day
971 { 'd', {1,2,0}, "d" }, // day of month
972 { 'D', {1,2,3,0}, "D" }, // day of year
973 { 'F', {1,0}, "F" }, // day of week in month
974 { 'g', {7,0}, "g" }, // modified julian day
975 // weekday
976 { 'E', {1,2,3,4,5,6}, "Eec" }, // day of week
977 { 'e', {1,2,3,4,5,6}, "Eec" }, // local day of week
978 { 'c', {1,2,3,4,5,6}, "Eec" }, // standalone local day of week
979 // day period
980 { 'a', {1,2,3,4,5,0}, "a" }, // am or pm
981 { 'b', {1,2,3,4,5,0}, "b" }, // dayPeriod AM/PM/noon
982 { 'B', {1,2,3,4,5,0}, "B" }, // dayPeriod ranges
983 // hour
984 { 'h', {1,2,0}, "hK" }, // 12 (1-12)
985 { 'H', {1,2,0}, "Hk" }, // 24 (0-23)
986 { 'K', {1,2,0}, "hK" }, // 12 (0-11)
987 { 'k', {1,2,0}, "Hk" }, // 24 (1-24)
988 { 'j', {1,2,0}, "hHKk" }, // locale default
989 { 'J', {1,2,0}, "hHKk" }, // locale default, without any dayPeriod
990 { 'C', {1,2,0}, "hHKk" }, // locale allowed first entry, possibly with b or B
991 // minute
992 { 'm', {1,2,0}, "m" }, // x
993 // second & fractions
994 { 's', {1,2,0}, "s" }, // x
995 { 'S', {1,2,3,4,0}, "S" }, // fractional second
996 { 'A', {8,0}, "A" }, // milliseconds in day
997 // zone
998 { 'z', {1,2,3,4,0}, "z" }, // x
999 { 'Z', {1,2,3,4,5,0}, "Z" }, // x
1000 { 'O', {1,4,0}, "O" }, // x
1001 { 'v', {1,4,0}, "v" }, // x
1002 { 'V', {1,2,3,4,0}, "V" }, // x
1003 { 'X', {1,2,3,4,5,0}, "X" }, // x
1004 { 'x', {1,2,3,4,5,0}, "x" }, // x
1005 };
1006
1007 const char ** localeNamesPtr = localeNames;
1008 const char * localeName;
1009 while ( (localeName = *localeNamesPtr++) != NULL) {
1010 UErrorCode status = U_ZERO_ERROR;
1011 Locale locale = Locale::createFromName(localeName);
1012 DateTimePatternGenerator * dtpg = DateTimePatternGenerator::createInstance(locale, status);
1013 if (U_SUCCESS(status)) {
1014 const AllFieldsTestItem * testDataPtr = testData;
1015 int itemCount = UPRV_LENGTHOF(testData);
1016 for (; itemCount-- > 0; ++testDataPtr) {
1017 char skelBuf[FIELD_LENGTH_MAX];
1018 int32_t chrIndx, lenIndx;
1019 for (chrIndx = 0; chrIndx < FIELD_LENGTH_MAX; chrIndx++) {
1020 skelBuf[chrIndx] = testDataPtr->patternChar;
1021 }
1022 for (lenIndx = 0; lenIndx < FIELD_LENGTHS_COUNT; lenIndx++) {
1023 int32_t skelLen = testDataPtr->fieldLengths[lenIndx];
1024 if (skelLen <= 0) {
1025 break;
1026 }
1027 if (skelLen > FIELD_LENGTH_MAX) {
1028 continue;
1029 }
1030 UnicodeString skeleton(skelBuf, skelLen, US_INV);
1031 UnicodeString pattern = dtpg->getBestPattern(skeleton, status);
1032 if (U_FAILURE(status)) {
1033 errln("DateTimePatternGenerator getBestPattern for locale %s, skelChar %c skelLength %d fails: %s",
1034 locale.getName(), testDataPtr->patternChar, skelLen, u_errorName(status));
1035 } else if (pattern.length() <= 0) {
1036 errln("DateTimePatternGenerator getBestPattern for locale %s, skelChar %c skelLength %d produces 0-length pattern",
1037 locale.getName(), testDataPtr->patternChar, skelLen);
1038 } else {
1039 // test that resulting pattern has at least one char in mustIncludeOneOf
1040 UnicodeString mustIncludeOneOf(testDataPtr->mustIncludeOneOf, -1, US_INV);
1041 int32_t patIndx, patLen = pattern.length();
1042 UBool inQuoted = FALSE;
1043 for (patIndx = 0; patIndx < patLen; patIndx++) {
1044 UChar c = pattern.charAt(patIndx);
1045 if (c == 0x27) {
1046 inQuoted = !inQuoted;
1047 } else if (!inQuoted && c <= 0x007A && c >= 0x0041) {
1048 if (mustIncludeOneOf.indexOf(c) >= 0) {
1049 break;
1050 }
1051 }
1052 }
1053 if (patIndx >= patLen) {
1054 errln(UnicodeString("DateTimePatternGenerator getBestPattern for locale ") +
1055 UnicodeString(locale.getName(),-1,US_INV) +
1056 ", skeleton " + skeleton +
1057 ", produces pattern without required chars: " + pattern);
1058 }
1059
1060 }
1061 }
1062 }
1063 delete dtpg;
1064 } else {
1065 dataerrln("Create DateTimePatternGenerator instance for locale(%s) fails: %s",
1066 locale.getName(), u_errorName(status));
1067 }
1068 }
1069 }
1070
testStaticGetSkeleton()1071 void IntlTestDateTimePatternGeneratorAPI::testStaticGetSkeleton(/*char *par*/)
1072 {
1073 // Verify that staticGetSkeleton() doesn't mangle skeletons. (Ticket #11985)
1074 static const char* const testData[] = {
1075 "jmm",
1076 "jjmm",
1077 "Jmm",
1078 "JJmm"
1079 };
1080
1081 for (size_t i = 0; i < UPRV_LENGTHOF(testData); i++) {
1082 UErrorCode status = U_ZERO_ERROR;
1083 UnicodeString skeleton = DateTimePatternGenerator::staticGetSkeleton(testData[i], status);
1084 if (!assertSuccess("staticGetSkeleton", status)) {
1085 return;
1086 }
1087 assertEquals("Skeleton", testData[i], skeleton);
1088 }
1089 }
1090
testC()1091 void IntlTestDateTimePatternGeneratorAPI::testC() {
1092 const char* tests[][3] = {
1093 // These may change with actual data for Bhmm/bhmm skeletons
1094 {"zh", "Cm", "Bh:mm"},
1095 {"zh", "CCm", "Bhh:mm"},
1096 {"zh", "CCCm", "BBBBh:mm"},
1097 {"zh", "CCCCm", "BBBBhh:mm"},
1098 {"zh", "CCCCCm", "BBBBBh:mm"},
1099 {"zh", "CCCCCCm", "BBBBBhh:mm"},
1100 {"de", "Cm", "HH:mm"},
1101 {"de", "CCm", "HH:mm"},
1102 {"de", "CCCm", "HH:mm"},
1103 {"de", "CCCCm", "HH:mm"},
1104 {"en", "Cm", "h:mm a"},
1105 {"en", "CCm", "hh:mm a"},
1106 {"en", "CCCm", "h:mm aaaa"},
1107 {"en", "CCCCm", "hh:mm aaaa"},
1108 {"en", "CCCCCm", "h:mm aaaaa"},
1109 {"en", "CCCCCCm", "hh:mm aaaaa"},
1110 {"en-BN", "Cm", "h:mm b"},
1111 {"gu-IN", "Cm", "h:mm B"},
1112 {"und-IN", "Cm", "h:mm a"}
1113 };
1114
1115 UErrorCode status = U_ZERO_ERROR;
1116 int32_t numTests = UPRV_LENGTHOF(tests);
1117 for (int32_t i = 0; i < numTests; ++i) {
1118 DateTimePatternGenerator *gen = DateTimePatternGenerator::createInstance(Locale(tests[i][0]), status);
1119 if (gen == NULL) {
1120 dataerrln("FAIL: DateTimePatternGenerator::createInstance failed for %s", tests[i][0]);
1121 return;
1122 }
1123 UDateTimePatternMatchOptions options = UDATPG_MATCH_HOUR_FIELD_LENGTH;
1124 UnicodeString pattern = gen->getBestPattern(tests[i][1], options, status);
1125 UnicodeString expectedPattern = tests[i][2];
1126
1127 char message[100] = "\0";
1128 strcat(message, tests[i][0]);
1129 strcat(message, "/");
1130 strcat(message, tests[i][1]);
1131 assertEquals(message, expectedPattern, pattern);
1132 delete gen;
1133 }
1134 }
1135
1136 enum { kCharBufMax = 31 };
testSkeletonsWithDayPeriods()1137 void IntlTestDateTimePatternGeneratorAPI::testSkeletonsWithDayPeriods() {
1138 const char * patterns[] = {
1139 // since icu4c getEmptyInstance does not call addCanonicalItems (unlike J), set these here:
1140 "a", // should get internal skeleton a
1141 "H", // should get internalskeleton H
1142 "m", // should get internalskeleton m
1143 "s", // should get internalskeleton s
1144 // patterns from which to construct sample data for a locale
1145 //"H", // should get internalskeleton H
1146 "h a", // should get internalskeleton ah
1147 "B h", // should get internalskeleton Bh
1148 };
1149 const char* testItems[][2] = {
1150 // sample requested skeletons and results
1151 // skel pattern
1152 { "H", "H"},
1153 { "HH", "HH"},
1154 { "aH", "H"},
1155 { "aHH", "HH"},
1156 { "BH", "H"},
1157 { "BHH", "HH"},
1158 { "BBBBH", "H"},
1159 { "h", "h a"},
1160 { "hh", "hh a"},
1161 { "ah", "h a"},
1162 { "ahh", "hh a"},
1163 { "aaaah", "h aaaa"},
1164 { "aaaahh", "hh aaaa"},
1165 { "bh", "h b"},
1166 { "bhh", "hh b"},
1167 { "bbbbh", "h bbbb"},
1168 { "Bh", "B h"},
1169 { "Bhh", "B hh"},
1170 { "BBBBh", "BBBB h"},
1171 { "BBBBhh", "BBBB hh"},
1172 { "a", "a"},
1173 { "aaaaa", "aaaaa"},
1174 { "b", "b"},
1175 { "bbbb", "bbbb"},
1176 { "B", "B"},
1177 { "BBBB", "BBBB"},
1178 };
1179 UErrorCode status = U_ZERO_ERROR;
1180 DateTimePatternGenerator *gen = DateTimePatternGenerator::createEmptyInstance(status);
1181 if (U_FAILURE(status)) {
1182 errln("ERROR: createEmptyInstance fails, status: %s", u_errorName(status));
1183 } else {
1184 int32_t i, len = UPRV_LENGTHOF(patterns);
1185 for (i = 0; i < len; i++) {
1186 UnicodeString conflictingPattern;
1187 (void)gen->addPattern(UnicodeString(patterns[i]), TRUE, conflictingPattern, status);
1188 if (U_FAILURE(status)) {
1189 errln("ERROR: addPattern %s fail, status: %s", patterns[i], u_errorName(status));
1190 break;
1191 }
1192 }
1193 if (U_SUCCESS(status)) {
1194 len = UPRV_LENGTHOF(testItems);
1195 for (i = 0; i < len; i++) {
1196 status = U_ZERO_ERROR;
1197 UDateTimePatternMatchOptions options = UDATPG_MATCH_HOUR_FIELD_LENGTH;
1198 UnicodeString result = gen->getBestPattern(UnicodeString(testItems[i][0]), options, status);
1199 if (U_FAILURE(status)) {
1200 errln("ERROR: getBestPattern %s fail, status: %s", testItems[i][0], u_errorName(status));
1201 } else if (result != UnicodeString(testItems[i][1])) {
1202 char charResult[kCharBufMax+1];
1203 result.extract(0, result.length(), charResult, kCharBufMax);
1204 charResult[kCharBufMax] = 0; // ensure termination
1205 errln("ERROR: getBestPattern %s, expected %s, got %s", testItems[i][0], testItems[i][1], charResult);
1206 }
1207 }
1208 }
1209 }
1210 delete gen;
1211 }
1212
1213 #endif /* #if !UCONFIG_NO_FORMATTING */
1214