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