1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
5 * Copyright (c) 2008-2016, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 ********************************************************************/
9 #include "unicode/utypes.h"
11 #if !UCONFIG_NO_FORMATTING
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 "unicode/datefmt.h"
28 // This is an API test, not a unit test. It doesn't test very many cases, and doesn't
29 // try to test the full functionality. It just calls each function in the class and
30 // verifies that it works on a basic level.
32 void IntlTestDateTimePatternGeneratorAPI::runIndexedTest( int32_t index
, UBool exec
, const char* &name
, char* /*par*/ )
34 if (exec
) logln("TestSuite DateTimePatternGeneratorAPI");
37 TESTCASE(1, testOptions
);
38 TESTCASE(2, testAllFieldPatterns
);
39 TESTCASE(3, testStaticGetSkeleton
);
41 TESTCASE(5, testSkeletonsWithDayPeriods
);
42 TESTCASE(6, testGetFieldDisplayNames
);
43 TESTCASE(7, testJjMapping
);
44 default: name
= ""; break;
51 * Test various generic API methods of DateTimePatternGenerator for API coverage.
53 void IntlTestDateTimePatternGeneratorAPI::testAPI(/*char *par*/)
55 UnicodeString patternData
[] = {
56 UnicodeString("yM"), // 00
57 UnicodeString("yMMM"), // 01
58 UnicodeString("yMd"), // 02
59 UnicodeString("yMMMd"), // 03
60 UnicodeString("Md"), // 04
61 UnicodeString("MMMd"), // 05
62 UnicodeString("MMMMd"), // 06
63 UnicodeString("yQQQ"), // 07
64 UnicodeString("hhmm"), // 08
65 UnicodeString("HHmm"), // 09
66 UnicodeString("jjmm"), // 10
67 UnicodeString("mmss"), // 11
68 UnicodeString("yyyyMMMM"), // 12
69 UnicodeString("MMMEd"), // 13
70 UnicodeString("Ed"), // 14
71 UnicodeString("jmmssSSS"), // 15
72 UnicodeString("JJmm"), // 16
76 const char* testLocale
[MAX_LOCALE
][4] = {
77 {"en", "US", "", ""}, // 0
78 {"en", "US", "", "calendar=japanese"}, // 1
79 {"de", "DE", "", ""}, // 2
80 {"fi", "", "", ""}, // 3
81 {"es", "", "", ""}, // 4
82 {"ja", "", "", ""}, // 5
83 {"ja", "", "", "calendar=japanese"}, // 6
84 {"zh", "Hans", "CN", ""}, // 7
85 {"zh", "TW", "", "calendar=roc"}, // 8
86 {"ru", "", "", ""}, // 9
87 {"zh", "", "", "calendar=chinese;numbers=hanidays"}, // 10
88 {"ar", "", "", ""}, // 11
91 // For Weds, Jan 13, 1999, 23:58:59
92 UnicodeString patternResults
[] = {
94 UnicodeString("1/1999"), // 00: yM
95 UnicodeString("Jan 1999"), // 01: yMMM
96 UnicodeString("1/13/1999"), // 02: yMd
97 UnicodeString("Jan 13, 1999"), // 03: yMMMd
98 UnicodeString("1/13"), // 04: Md
99 UnicodeString("Jan 13"), // 05: MMMd
100 UnicodeString("January 13"), // 06: MMMMd
101 UnicodeString("Q1 1999"), // 07: yQQQ
102 UnicodeString("11:58 PM"), // 08: hhmm
103 UnicodeString("23:58"), // 09: HHmm
104 UnicodeString("11:58 PM"), // 10: jjmm
105 UnicodeString("58:59"), // 11: mmss
106 UnicodeString("January 1999"), // 12: yyyyMMMM
107 UnicodeString("Wed, Jan 13"), // 13: MMMEd -> EEE, MMM d
108 UnicodeString("13 Wed"), // 14: Ed -> d EEE
109 UnicodeString("11:58:59.123 PM"), // 15: jmmssSSS -> "h:mm:ss.SSS a"
110 UnicodeString("11:58"), // 16: JJmm
112 // en_US@calendar=japanese // 1 en_US@calendar=japanese
113 UnicodeString("1/11 H"), // 0: yM
114 UnicodeString("Jan 11 Heisei"), // 1: yMMM
115 UnicodeString("1/13/11 H"), // 2: yMd
116 UnicodeString("Jan 13, 11 Heisei"), // 3: yMMMd
117 UnicodeString("1/13"), // 4: Md
118 UnicodeString("Jan 13"), // 5: MMMd
119 UnicodeString("January 13"), // 6: MMMMd
120 UnicodeString("Q1 11 Heisei"), // 7: yQQQ
121 UnicodeString("11:58 PM"), // 8: hhmm
122 UnicodeString("23:58"), // 9: HHmm
123 UnicodeString("11:58 PM"), // 10: jjmm
124 UnicodeString("58:59"), // 11: mmss
125 UnicodeString("January 11 Heisei"), // 12: yyyyMMMM
126 UnicodeString("Wed, Jan 13"), // 13: MMMEd -> EEE, MMM d"
127 UnicodeString("13 Wed"), // 14: Ed -> d EEE
128 UnicodeString("11:58:59.123 PM"), // 15: jmmssSSS -> "h:mm:ss.SSS a"
129 UnicodeString("11:58"), // 16: JJmm
132 UnicodeString("1.1999"), // 00: yM
133 UnicodeString("Jan. 1999"), // 01: yMMM
134 UnicodeString("13.1.1999"), // 02: yMd
135 UnicodeString("13. Jan. 1999"), // 03: yMMMd
136 UnicodeString("13.1."), // 04: Md
137 UnicodeString("13. Jan."), // 05: MMMd
138 UnicodeString("13. Januar"), // 06: MMMMd
139 UnicodeString("Q1 1999"), // 07: yQQQ
140 UnicodeString("11:58 PM"), // 08: hhmm
141 UnicodeString("23:58"), // 09: HHmm
142 UnicodeString("23:58"), // 10: jjmm
143 UnicodeString("58:59"), // 11: mmss
144 UnicodeString("Januar 1999"), // 12: yyyyMMMM
145 UnicodeString("Mi. 13. Jan."), // 13: MMMEd -> E d. MMM
146 UnicodeString("Mi. 13."), // 14: Ed -> E d.
147 UnicodeString("23:58:59,123"), // 15: jmmssSSS -> "HH:mm:ss,SSS"
148 UnicodeString("23:58"), // 16: JJmm
151 UnicodeString("1.1999"), // 00: yM (fixed expected result per ticket:6626:)
152 UnicodeString("tammi 1999"), // 01: yMMM
153 UnicodeString("13.1.1999"), // 02: yMd
154 UnicodeString("13.1.1999"), // 03: yMMMd
155 UnicodeString("13.1."), // 04: Md
156 UnicodeString("13.1."), // 05: MMMd
157 UnicodeString("13. tammikuuta"), // 06: MMMMd
158 UnicodeString("1. nelj. 1999"), // 07: yQQQ
159 UnicodeString("11.58 ip."), // 08: hhmm
160 UnicodeString("23.58"), // 09: HHmm
161 UnicodeString("23.58"), // 10: jjmm
162 UnicodeString("58.59"), // 11: mmss
163 UnicodeString("tammikuu 1999"), // 12: yyyyMMMM
164 UnicodeString("ke 13.1."), // 13: MMMEd -> EEE d.M.
165 UnicodeString("ke 13."), // 14: Ed -> ccc d.
166 UnicodeString("23.58.59,123"), // 15: jmmssSSS -> "H.mm.ss,SSS"
167 UnicodeString("23.58"), // 16: JJmm
170 UnicodeString("1/1999"), // 00: yM -> "M/y"
171 UnicodeString("ene 1999"), // 01: yMMM -> "MMM y"
172 UnicodeString("13/1/1999"), // 02: yMd -> "d/M/y"
173 UnicodeString("13 ene 1999"), // 03: yMMMd -> "d MMM y"
174 UnicodeString("13/1"), // 04: Md -> "d/M"
175 UnicodeString("13 ene"), // 05: MMMd -> "d MMM"
176 UnicodeString("13 de enero"), // 06: MMMMd -> "d 'de' MMMM"
177 UnicodeString("T1 1999"), // 07: yQQQ -> "QQQ y"
178 CharsToUnicodeString("11:58 p.\\u00A0m."), // 08: hhmm -> "hh:mm a"
179 UnicodeString("23:58"), // 09: HHmm -> "HH:mm"
180 UnicodeString("23:58"), // 10: jjmm -> "HH:mm"
181 UnicodeString("58:59"), // 11: mmss -> "mm:ss"
182 UnicodeString("enero de 1999"), // 12: yyyyMMMM -> "MMMM 'de' yyyy"
183 CharsToUnicodeString("mi\\u00E9, 13 ene"), // 13: MMMEd -> "E d MMM"
184 CharsToUnicodeString("mi\\u00E9 13"), // 14: Ed -> "EEE d"
185 UnicodeString("23:58:59,123"), // 15: jmmssSSS -> "H:mm:ss,SSS"
186 UnicodeString("23:58"), // 16: JJmm
189 UnicodeString("1999/1"), // 00: yM -> y/M
190 CharsToUnicodeString("1999\\u5E741\\u6708"), // 01: yMMM -> y\u5E74M\u6708
191 UnicodeString("1999/1/13"), // 02: yMd -> y/M/d
192 CharsToUnicodeString("1999\\u5E741\\u670813\\u65E5"), // 03: yMMMd -> y\u5E74M\u6708d\u65E5
193 UnicodeString("1/13"), // 04: Md -> M/d
194 CharsToUnicodeString("1\\u670813\\u65E5"), // 05: MMMd -> M\u6708d\u65E5
195 CharsToUnicodeString("1\\u670813\\u65E5"), // 06: MMMMd -> M\u6708d\u65E5
196 CharsToUnicodeString("1999/Q1"), // 07: yQQQ -> y/QQQ
197 CharsToUnicodeString("\\u5348\\u5F8C11:58"), // 08: hhmm
198 UnicodeString("23:58"), // 09: HHmm -> HH:mm
199 UnicodeString("23:58"), // 10: jjmm
200 UnicodeString("58:59"), // 11: mmss -> mm:ss
201 CharsToUnicodeString("1999\\u5E741\\u6708"), // 12: yyyyMMMM -> y\u5E74M\u6708
202 CharsToUnicodeString("1\\u670813\\u65E5(\\u6C34)"), // 13: MMMEd -> M\u6708d\u65E5(E)
203 CharsToUnicodeString("13\\u65E5(\\u6C34)"), // 14: Ed -> d\u65E5(E)
204 UnicodeString("23:58:59.123"), // 15: jmmssSSS -> "H:mm:ss.SSS"
205 UnicodeString("23:58"), // 16: JJmm
207 // ja@calendar=japanese // 6 ja@calendar=japanese
208 UnicodeString("H11/01"), // 00: yM -> GGGGGy/MM
209 CharsToUnicodeString("\\u5E73\\u621011\\u5E741\\u6708"), // 01: yMMM -> Gy\u5E74M\u6708
210 UnicodeString("H11/01/13"), // 02: yMd -> GGGGGy/MM/dd
211 CharsToUnicodeString("\\u5E73\\u621011\\u5E741\\u670813\\u65E5"), // 03: yMMMd -> Gy\u5E74M\u6708d\u65E5
212 UnicodeString("1/13"), // 04: Md -> M/dd
213 CharsToUnicodeString("1\\u670813\\u65E5"), // 05: MMMd -> M\u6708d\u65E5
214 CharsToUnicodeString("1\\u670813\\u65E5"), // 06: MMMMd -> M\u6708d\u65E5
215 CharsToUnicodeString("\\u5E73\\u621011/Q1"), // 07: yQQQ -> Gy/QQQ
216 CharsToUnicodeString("\\u5348\\u5F8C11:58"), // 08: hhmm ->
217 UnicodeString("23:58"), // 09: HHmm -> HH:mm (as for ja)
218 UnicodeString("23:58"), // 10: jjmm
219 UnicodeString("58:59"), // 11: mmss -> mm:ss (as for ja)
220 CharsToUnicodeString("\\u5E73\\u621011\\u5E741\\u6708"), // 12: yyyyMMMM -> Gyyyy\u5E74M\u6708
221 CharsToUnicodeString("1\\u670813\\u65E5(\\u6C34)"), // 13: MMMEd -> M\u6708d\u65E5(E)
222 CharsToUnicodeString("13\\u65E5(\\u6C34)"), // 14: Ed -> d\u65E5(E)
223 UnicodeString("23:58:59.123"), // 15: jmmssSSS -> "H:mm:ss.SSS"
224 UnicodeString("23:58"), // 16: JJmm
226 // zh_Hans_CN // 7 zh_Hans_CN
227 CharsToUnicodeString("1999\\u5E741\\u6708"), // 00: yM -> y\u5E74M\u6708
228 CharsToUnicodeString("1999\\u5E741\\u6708"), // 01: yMMM -> yyyy\u5E74MMM (fixed expected result per ticket:6626:)
229 CharsToUnicodeString("1999/1/13"), // 02: yMd
230 CharsToUnicodeString("1999\\u5E741\\u670813\\u65E5"), // 03: yMMMd -> yyyy\u5E74MMMd\u65E5 (fixed expected result per ticket:6626:)
231 UnicodeString("1/13"), // 04: Md
232 CharsToUnicodeString("1\\u670813\\u65E5"), // 05: MMMd -> M\u6708d\u65E5 (fixed expected result per ticket:6626:)
233 CharsToUnicodeString("1\\u670813\\u65E5"), // 06: MMMMd -> M\u6708d\u65E5
234 CharsToUnicodeString("1999\\u5E74\\u7B2C1\\u5B63\\u5EA6"), // 07: yQQQ
235 CharsToUnicodeString("\\u4E0B\\u534811:58"), // 08: hhmm
236 UnicodeString("23:58"), // 09: HHmm
237 CharsToUnicodeString("\\u4E0B\\u534811:58"), // 10: jjmm
238 UnicodeString("58:59"), // 11: mmss
239 CharsToUnicodeString("1999\\u5E741\\u6708"), // 12: yyyyMMMM -> yyyy\u5E74MMM
240 CharsToUnicodeString("1\\u670813\\u65E5 \\u5468\\u4E09"), // 13: MMMEd -> MMMd\u65E5 EEE
241 CharsToUnicodeString("13 \\u5468\\u4E09"), // 14: Ed -> d\u65E5EEE
242 CharsToUnicodeString("\\u4E0B\\u534811:58:59.123"), // 15: jmmssSSS -> "ah:mm:ss.SSS"
243 UnicodeString("11:58"), // 16: JJmm
245 // zh_TW@calendar=roc // 8 zh_TW@calendar=roc
246 CharsToUnicodeString("\\u6C11\\u570B 88/1"), // 00: yM -> G y/M
247 CharsToUnicodeString("\\u6C11\\u570B 88\\u5E741\\u6708"), // 01: yMMM -> G y\u5E74M\u6708
248 CharsToUnicodeString("\\u6C11\\u570B 88/1/13"), // 02: yMd -> G y/M/d
249 CharsToUnicodeString("\\u6C11\\u570B 88\\u5E741\\u670813\\u65E5"), // 03: yMMMd -> G y\u5E74M\u6708d\u65E5
250 UnicodeString("1/13"), // 04: Md -> M/d
251 CharsToUnicodeString("1\\u670813\\u65E5"), // 05: MMMd ->M\u6708d\u65E5
252 CharsToUnicodeString("1\\u670813\\u65E5"), // 06: MMMMd ->M\u6708d\u65E5
253 CharsToUnicodeString("\\u6C11\\u570B 88\\u5E741\\u5B63"), // 07: yQQQ -> G yQQQ
254 CharsToUnicodeString("\\u4E0B\\u534811:58"), // 08: hhmm ->
255 UnicodeString("23:58"), // 09: HHmm ->
256 CharsToUnicodeString("\\u4E0B\\u534811:58"), // 10: jjmm
257 UnicodeString("58:59"), // 11: mmss ->
258 CharsToUnicodeString("\\u6C11\\u570B 88\\u5E741\\u6708"), // 12: yyyyMMMM -> G y\u5E74M\u670
259 CharsToUnicodeString("1\\u670813\\u65E5 \\u9031\\u4E09"), // 13: MMMEd -> M\u6708d\u65E5 E
260 CharsToUnicodeString("13 \\u9031\\u4E09"), // 14: Ed -> d E
261 CharsToUnicodeString("\\u4E0B\\u534811:58:59.123"), // 15: jmmssSSS -> "ah:mm:ss.SSS"
262 UnicodeString("11:58"), // 16: JJmm
265 UnicodeString("01.1999"), // 00: yM -> MM.y
266 CharsToUnicodeString("\\u044F\\u043D\\u0432. 1999 \\u0433."), // 01: yMMM -> LLL y
267 UnicodeString("13.01.1999"), // 02: yMd -> dd.MM.y
268 CharsToUnicodeString("13 \\u044F\\u043D\\u0432. 1999 \\u0433."), // 03: yMMMd -> d MMM y
269 UnicodeString("13.01"), // 04: Md -> dd.MM
270 CharsToUnicodeString("13 \\u044F\\u043D\\u0432."), // 05: MMMd -> d MMM
271 CharsToUnicodeString("13 \\u044F\\u043D\\u0432\\u0430\\u0440\\u044F"), // 06: MMMMd -> d MMMM
272 CharsToUnicodeString("1-\\u0439 \\u043A\\u0432. 1999 \\u0433."), // 07: yQQQ -> y QQQ
273 CharsToUnicodeString("11:58 PM"), // 08: hhmm -> hh:mm a
274 UnicodeString("23:58"), // 09: HHmm -> HH:mm
275 UnicodeString("23:58"), // 10: jjmm -> HH:mm
276 UnicodeString("58:59"), // 11: mmss -> mm:ss
277 CharsToUnicodeString("\\u044F\\u043D\\u0432\\u0430\\u0440\\u044C 1999 \\u0433."), // 12: yyyyMMMM -> LLLL y
278 CharsToUnicodeString("\\u0441\\u0440, 13 \\u044F\\u043D\\u0432."), // 13: MMMEd -> ccc, d MMM
279 CharsToUnicodeString("\\u0441\\u0440, 13"), // 14: Ed -> EEE, d
280 UnicodeString("23:58:59,123"), // 15: jmmssSSS -> "H:mm:ss,SSS"
281 UnicodeString("23:58"), // 16: JJmm
283 // zh@calendar=chinese,numbers=hanidays // 10 zh@calendar=chinese,numbers=hanidays
284 CharsToUnicodeString("1998\\u620A\\u5BC5\\u5E74\\u51AC\\u6708"), // 00: yMMM
285 CharsToUnicodeString("1998\\u620A\\u5BC5\\u5E74\\u51AC\\u6708"), // 01: yMMM
286 CharsToUnicodeString("1998\\u5E74\\u51AC\\u6708\\u5EFF\\u516D"), // 02: yMMMd
287 CharsToUnicodeString("1998\\u5E74\\u51AC\\u6708\\u5EFF\\u516D"), // 03: yMMMd
288 CharsToUnicodeString("11-\\u5EFF\\u516D"), // 04: Md // hmm
289 CharsToUnicodeString("\\u51AC\\u6708\\u5EFF\\u516D"), // 05: MMMd
290 CharsToUnicodeString("\\u51AC\\u6708\\u5EFF\\u516D"), // 06: MMMMd
291 CharsToUnicodeString("1998\\u620A\\u5BC5\\u5E74\\u7b2c\\u56db\\u5B63\\u5EA6"), // 07: yQQQ
292 CharsToUnicodeString("\\u4E0B\\u534811:58"), // 08: hhmm
293 UnicodeString("23:58"), // 09: HHmm
294 CharsToUnicodeString("\\u4E0B\\u534811:58"), // 10: jjmm
295 UnicodeString("58:59"), // 11: mmss
296 CharsToUnicodeString("1998\\u620A\\u5BC5\\u5E74\\u51AC\\u6708"), // 12: yyyyMMMM
297 CharsToUnicodeString("\\u51AC\\u6708\\u5EFF\\u516D\\u5468\\u4E09"), // 13: MMMEd
298 CharsToUnicodeString("\\u5EFF\\u516D\\u5468\\u4E09"), // 14: Ed -> dE
299 CharsToUnicodeString("\\u4E0B\\u534811:58:59.123"), // 15: jmmssSS
300 UnicodeString("11:58"), // 16: JJmm
302 // ar // 11 ar, for Weds, Jan 13, 1999, 23:58:59
303 CharsToUnicodeString("\\u0661\\u200F/\\u0661\\u0669\\u0669\\u0669"), // 00: yM
304 CharsToUnicodeString("\\u064A\\u0646\\u0627\\u064A\\u0631 \\u0661\\u0669\\u0669\\u0669"), // 01: yMMM
305 CharsToUnicodeString("\\u0661\\u0663\\u200F/\\u0661\\u200F/\\u0661\\u0669\\u0669\\u0669"), // 02: yMd
306 CharsToUnicodeString("\\u0661\\u0663 \\u064A\\u0646\\u0627\\u064A\\u0631\\u060C \\u0661\\u0669\\u0669\\u0669"), // 03: yMMMd
307 CharsToUnicodeString("\\u0661\\u0663/\\u200F\\u0661"), // 04: Md
308 CharsToUnicodeString("\\u0661\\u0663 \\u064A\\u0646\\u0627\\u064A\\u0631"), // 05: MMMd
309 CharsToUnicodeString("\\u0661\\u0663 \\u064A\\u0646\\u0627\\u064A\\u0631"), // 06: MMMMd
310 CharsToUnicodeString("\\u0627\\u0644\\u0631\\u0628\\u0639 \\u0627\\u0644\\u0623\\u0648\\u0644 \\u0661\\u0669\\u0669\\u0669"), // 07: yQQQ
311 CharsToUnicodeString("\\u0661\\u0661:\\u0665\\u0668\\u00A0\\u0645"), // 08: hhmm
312 CharsToUnicodeString("\\u0662\\u0663:\\u0665\\u0668"), // 09: HHmm
313 CharsToUnicodeString("\\u0661\\u0661:\\u0665\\u0668\\u00A0\\u0645"), // 10: jjmm
314 CharsToUnicodeString("\\u0665\\u0668:\\u0665\\u0669"), // 11: mmss
315 CharsToUnicodeString("\\u064A\\u0646\\u0627\\u064A\\u0631 \\u0661\\u0669\\u0669\\u0669"), // 12: yyyyMMMM
316 CharsToUnicodeString("\\u0623\\u0631\\u0628\\u0639\\u0627\\u0621\\u060C \\u0661\\u0663 \\u064A\\u0646\\u0627\\u064A\\u0631"), // 13: MMMEd
317 CharsToUnicodeString("\\u0623\\u0631\\u0628\\u0639\\u0627\\u0621\\u060C \\u0661\\u0663"), // 14: Ed
318 CharsToUnicodeString("\\u0661\\u0661:\\u0665\\u0668:\\u0665\\u0669\\u066B\\u0661\\u0662\\u0663\\u00A0\\u0645"), // 15: jmmssSSS
319 CharsToUnicodeString("\\u0661\\u0661:\\u0665\\u0668"), // 16: JJmm
324 UnicodeString patternTests2
[] = {
325 UnicodeString("yyyyMMMdd"),
326 UnicodeString("yyyyqqqq"),
327 UnicodeString("yMMMdd"),
328 UnicodeString("EyyyyMMMdd"),
329 UnicodeString("yyyyMMdd"),
330 UnicodeString("yyyyMMM"),
331 UnicodeString("yyyyMM"),
332 UnicodeString("yyMM"),
333 UnicodeString("yMMMMMd"),
334 UnicodeString("EEEEEMMMMMd"),
335 UnicodeString("MMMd"),
336 UnicodeString("MMMdhmm"),
337 UnicodeString("EMMMdhmms"),
338 UnicodeString("MMdhmm"),
339 UnicodeString("EEEEMMMdhmms"),
340 UnicodeString("yyyyMMMddhhmmss"),
341 UnicodeString("EyyyyMMMddhhmmss"),
342 UnicodeString("hmm"),
343 UnicodeString("hhmm"),
344 UnicodeString("hhmmVVVV"),
347 UnicodeString patternResults2
[] = {
348 UnicodeString("Oct 14, 1999"),
349 UnicodeString("4th quarter 1999"),
350 UnicodeString("Oct 14, 1999"),
351 UnicodeString("Thu, Oct 14, 1999"),
352 UnicodeString("10/14/1999"),
353 UnicodeString("Oct 1999"),
354 UnicodeString("10/1999"),
355 UnicodeString("10/99"),
356 UnicodeString("O 14, 1999"),
357 UnicodeString("T, O 14"),
358 UnicodeString("Oct 14"),
359 UnicodeString("Oct 14, 6:58 AM"),
360 UnicodeString("Thu, Oct 14, 6:58:59 AM"),
361 UnicodeString("10/14, 6:58 AM"),
362 UnicodeString("Thursday, Oct 14, 6:58:59 AM"),
363 UnicodeString("Oct 14, 1999, 6:58:59 AM"),
364 UnicodeString("Thu, Oct 14, 1999, 6:58:59 AM"),
365 UnicodeString("6:58 AM"),
366 UnicodeString("6:58 AM"),
367 UnicodeString("6:58 AM GMT"),
371 // results for getSkeletons() and getPatternForSkeleton()
372 const UnicodeString testSkeletonsResults
[] = {
373 UnicodeString("HH:mm"),
374 UnicodeString("MMMMd"),
375 UnicodeString("MMMMMdd"),
378 const UnicodeString testBaseSkeletonsResults
[] = {
380 UnicodeString("MMMMd"),
381 UnicodeString("MMMMMd"),
384 const char* testGetSkeletonAndBase
[][3] = {
385 // pattern skeleton baseSkeleton
386 { "dd-MMM", "MMMdd", "MMMd" },
387 { "dd/MMMM/yy", "yyMMMMdd", "yMMMMd" },
389 { "ah", "ah", "ah" },
390 { "aaaah", "aaaah", "aaaah" },
394 UnicodeString
newDecimal(" "); // space
395 UnicodeString
newAppendItemName("hrs.");
396 UnicodeString
newAppendItemFormat("{1} {0}");
397 UnicodeString
newDateTimeFormat("{1} {0}");
398 UErrorCode status
= U_ZERO_ERROR
;
399 UnicodeString conflictingPattern
;
400 UDateTimePatternConflict conflictingStatus
= UDATPG_NO_CONFLICT
;
401 (void)conflictingStatus
; // Suppress set but not used warning.
403 // ======= Test CreateInstance with default locale
404 logln("Testing DateTimePatternGenerator createInstance from default locale");
406 DateTimePatternGenerator
*instFromDefaultLocale
=DateTimePatternGenerator::createInstance(status
);
407 if (U_FAILURE(status
)) {
408 dataerrln("ERROR: Could not create DateTimePatternGenerator (default) - exitting");
412 delete instFromDefaultLocale
;
415 // ======= Test CreateInstance with given locale
416 logln("Testing DateTimePatternGenerator createInstance from French locale");
417 status
= U_ZERO_ERROR
;
418 DateTimePatternGenerator
*instFromLocale
=DateTimePatternGenerator::createInstance(Locale::getFrench(), status
);
419 if (U_FAILURE(status
)) {
420 dataerrln("ERROR: Could not create DateTimePatternGenerator (Locale::getFrench()) - exitting");
424 // ======= Test clone DateTimePatternGenerator
425 logln("Testing DateTimePatternGenerator::clone()");
426 status
= U_ZERO_ERROR
;
429 UnicodeString decimalSymbol
= instFromLocale
->getDecimal();
430 UnicodeString newDecimalSymbol
= UnicodeString("*");
431 decimalSymbol
= instFromLocale
->getDecimal();
432 instFromLocale
->setDecimal(newDecimalSymbol
);
433 DateTimePatternGenerator
*cloneDTPatternGen
=instFromLocale
->clone();
434 decimalSymbol
= cloneDTPatternGen
->getDecimal();
435 if (decimalSymbol
!= newDecimalSymbol
) {
436 errln("ERROR: inconsistency is found in cloned object.");
438 if ( !(*cloneDTPatternGen
== *instFromLocale
) ) {
439 errln("ERROR: inconsistency is found in cloned object.");
442 if ( *cloneDTPatternGen
!= *instFromLocale
) {
443 errln("ERROR: inconsistency is found in cloned object.");
446 delete instFromLocale
;
447 delete cloneDTPatternGen
;
449 // ======= Test simple use cases
450 logln("Testing simple use cases");
451 status
= U_ZERO_ERROR
;
452 Locale deLocale
=Locale::getGermany();
453 UDate sampleDate
=LocaleTest::date(99, 9, 13, 23, 58, 59);
454 DateTimePatternGenerator
*gen
= DateTimePatternGenerator::createInstance(deLocale
, status
);
455 if (U_FAILURE(status
)) {
456 dataerrln("ERROR: Could not create DateTimePatternGenerator (Locale::getGermany()) - exitting");
459 UnicodeString findPattern
= gen
->getBestPattern(UnicodeString("MMMddHmm"), status
);
460 SimpleDateFormat
*format
= new SimpleDateFormat(findPattern
, deLocale
, status
);
461 if (U_FAILURE(status
)) {
462 dataerrln("ERROR: Could not create SimpleDateFormat (Locale::getGermany())");
466 TimeZone
*zone
= TimeZone::createTimeZone(UnicodeString("ECT"));
468 dataerrln("ERROR: Could not create TimeZone ECT");
473 format
->setTimeZone(*zone
);
474 UnicodeString dateReturned
, expectedResult
;
475 dateReturned
.remove();
476 dateReturned
= format
->format(sampleDate
, dateReturned
, status
);
477 expectedResult
=UnicodeString("14. Okt., 08:58", -1, US_INV
);
478 if ( dateReturned
!= expectedResult
) {
479 errln("ERROR: Simple test in getBestPattern with Locale::getGermany()).");
482 status
= U_ZERO_ERROR
;
483 conflictingStatus
= gen
->addPattern(UnicodeString("d'. von' MMMM", -1, US_INV
), true, conflictingPattern
, status
);
484 if (U_FAILURE(status
)) {
485 errln("ERROR: Could not addPattern - d\'. von\' MMMM");
487 status
= U_ZERO_ERROR
;
488 UnicodeString testPattern
=gen
->getBestPattern(UnicodeString("MMMMdd"), status
);
489 testPattern
=gen
->getBestPattern(UnicodeString("MMMddHmm"), status
);
490 format
->applyPattern(gen
->getBestPattern(UnicodeString("MMMMdHmm"), status
));
491 dateReturned
.remove();
492 dateReturned
= format
->format(sampleDate
, dateReturned
, status
);
493 expectedResult
=UnicodeString("14. von Oktober, 08:58", -1, US_INV
);
494 if ( dateReturned
!= expectedResult
) {
495 errln(UnicodeString("ERROR: Simple test addPattern failed!: d\'. von\' MMMM Got: ") + dateReturned
+ UnicodeString(" Expected: ") + expectedResult
);
499 // get a pattern and modify it
500 format
= (SimpleDateFormat
*)DateFormat::createDateTimeInstance(DateFormat::kFull
, DateFormat::kFull
,
502 format
->setTimeZone(*zone
);
503 UnicodeString pattern
;
504 pattern
= format
->toPattern(pattern
);
505 dateReturned
.remove();
506 dateReturned
= format
->format(sampleDate
, dateReturned
, status
);
507 expectedResult
=CharsToUnicodeString("Donnerstag, 14. Oktober 1999 um 08:58:59 Mitteleurop\\u00E4ische Sommerzeit");
508 if ( dateReturned
!= expectedResult
) {
509 errln("ERROR: Simple test uses full date format.");
510 errln(UnicodeString(" Got: ") + dateReturned
+ UnicodeString(" Expected: ") + expectedResult
);
513 // modify it to change the zone.
514 UnicodeString newPattern
= gen
->replaceFieldTypes(pattern
, UnicodeString("vvvv"), status
);
515 format
->applyPattern(newPattern
);
516 dateReturned
.remove();
517 dateReturned
= format
->format(sampleDate
, dateReturned
, status
);
518 expectedResult
=CharsToUnicodeString("Donnerstag, 14. Oktober 1999 um 08:58:59 Mitteleurop\\u00E4ische Zeit");
519 if ( dateReturned
!= expectedResult
) {
520 errln("ERROR: Simple test modify the timezone!");
521 errln(UnicodeString(" Got: ")+ dateReturned
+ UnicodeString(" Expected: ") + expectedResult
);
524 // setDeciaml(), getDeciaml()
525 gen
->setDecimal(newDecimal
);
526 if (newDecimal
!= gen
->getDecimal()) {
527 errln("ERROR: unexpected result from setDecimal() and getDecimal()!.\n");
530 // setAppenItemName() , getAppendItemName()
531 gen
->setAppendItemName(UDATPG_HOUR_FIELD
, newAppendItemName
);
532 if (newAppendItemName
!= gen
->getAppendItemName(UDATPG_HOUR_FIELD
)) {
533 errln("ERROR: unexpected result from setAppendItemName() and getAppendItemName()!.\n");
536 // setAppenItemFormat() , getAppendItemFormat()
537 gen
->setAppendItemFormat(UDATPG_HOUR_FIELD
, newAppendItemFormat
);
538 if (newAppendItemFormat
!= gen
->getAppendItemFormat(UDATPG_HOUR_FIELD
)) {
539 errln("ERROR: unexpected result from setAppendItemFormat() and getAppendItemFormat()!.\n");
542 // setDateTimeFormat() , getDateTimeFormat()
543 gen
->setDateTimeFormat(newDateTimeFormat
);
544 if (newDateTimeFormat
!= gen
->getDateTimeFormat()) {
545 errln("ERROR: unexpected result from setDateTimeFormat() and getDateTimeFormat()!.\n");
548 // ======== Test getSkeleton and getBaseSkeleton
550 int32_t i
, count
= UPRV_LENGTHOF(testGetSkeletonAndBase
);
551 for (i
= 0; i
< count
; i
++) {
552 status
= U_ZERO_ERROR
;
553 pattern
= UnicodeString(testGetSkeletonAndBase
[i
][0]);
554 UnicodeString expectedSkeleton
= UnicodeString(testGetSkeletonAndBase
[i
][1]);
555 UnicodeString expectedBaseSkeleton
= UnicodeString(testGetSkeletonAndBase
[i
][2]);
556 UnicodeString retSkeleton
= gen
->getSkeleton(pattern
, status
);
557 if(U_FAILURE(status
) || retSkeleton
!= expectedSkeleton
) {
558 errln("ERROR: Unexpected result from getSkeleton().\n");
559 errln(UnicodeString(" Got: ") + retSkeleton
+ UnicodeString(" Expected: ") + expectedSkeleton
);
561 retSkeleton
= gen
->getBaseSkeleton(pattern
, status
);
562 if(U_FAILURE(status
) || retSkeleton
!= expectedBaseSkeleton
) {
563 errln("ERROR: Unexpected result from getBaseSkeleton().\n");
564 errln(UnicodeString(" Got: ") + retSkeleton
+ UnicodeString(" Expected:")+ expectedBaseSkeleton
);
574 status
= U_ZERO_ERROR
;
575 pattern
= UnicodeString("YYYYMMM");
576 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");
584 UnicodeString bPattern
= patGen
->getBestPattern(pattern
, status
);
586 SimpleDateFormat
sdf(bPattern
, loc
, status
);
588 rDate
= sdf
.format(testDate1
, rDate
);
590 logln(UnicodeString(" ja locale with skeleton: YYYYMMM Best Pattern:") + bPattern
);
591 logln(UnicodeString(" Formatted date:") + rDate
);
593 if ( expR
!= rDate
) {
594 errln(UnicodeString("\nERROR: Test Japanese month hack Got: ") + rDate
+
595 UnicodeString(" Expected: ") + expR
);
602 UnicodeString expR
= CharsToUnicodeString("1999\\u5E741\\u6708"); // fixed expected result per ticket:6626:
603 UDate testDate1
= LocaleTest::date(99, 0, 13, 23, 58, 59);
604 DateTimePatternGenerator
*patGen
=DateTimePatternGenerator::createInstance(loc
, status
);
605 if(U_FAILURE(status
)) {
606 dataerrln("ERROR: Could not create DateTimePatternGenerator");
609 UnicodeString bPattern
= patGen
->getBestPattern(pattern
, status
);
611 SimpleDateFormat
sdf(bPattern
, loc
, status
);
613 rDate
= sdf
.format(testDate1
, rDate
);
615 logln(UnicodeString(" zh locale with skeleton: YYYYMMM Best Pattern:") + bPattern
);
616 logln(UnicodeString(" Formatted date:") + rDate
);
617 if ( expR
!= rDate
) {
618 errln(UnicodeString("\nERROR: Test Chinese month hack Got: ") + rDate
+
619 UnicodeString(" Expected: ") + expR
);
625 // Trac# 6172 duplicate time pattern
626 status
= U_ZERO_ERROR
;
627 pattern
= UnicodeString("hmv");
628 UnicodeString expR
= UnicodeString("h:mm a v"); // avail formats has hm -> "h:mm a" (fixed expected result per ticket:6626:)
630 DateTimePatternGenerator
*patGen
=DateTimePatternGenerator::createInstance(loc
, status
);
631 if(U_FAILURE(status
)) {
632 dataerrln("ERROR: Could not create DateTimePatternGenerator");
635 UnicodeString bPattern
= patGen
->getBestPattern(pattern
, status
);
636 logln(UnicodeString(" en locale with skeleton: hmv Best Pattern:") + bPattern
);
638 if ( expR
!= bPattern
) {
639 errln(UnicodeString("\nERROR: Test EN time format Got: ") + bPattern
+
640 UnicodeString(" Expected: ") + expR
);
647 // ======= Test various skeletons.
648 logln("Testing DateTimePatternGenerator with various skeleton");
650 status
= U_ZERO_ERROR
;
651 int32_t localeIndex
=0;
652 int32_t resultIndex
=0;
653 UnicodeString resultDate
;
654 UDate testDate
= LocaleTest::date(99, 0, 13, 23, 58, 59) + 123.0;
655 while (localeIndex
< MAX_LOCALE
)
658 UnicodeString bestPattern
;
660 Locale
loc(testLocale
[localeIndex
][0], testLocale
[localeIndex
][1], testLocale
[localeIndex
][2], testLocale
[localeIndex
][3]);
661 logln("\n\n Locale: %s_%s_%s@%s", testLocale
[localeIndex
][0], testLocale
[localeIndex
][1], testLocale
[localeIndex
][2], testLocale
[localeIndex
][3]);
662 DateTimePatternGenerator
*patGen
=DateTimePatternGenerator::createInstance(loc
, status
);
663 if(U_FAILURE(status
)) {
664 dataerrln("ERROR: Could not create DateTimePatternGenerator with locale index:%d . - exitting\n", localeIndex
);
667 while (patternData
[dataIndex
].length() > 0) {
668 log(patternData
[dataIndex
]);
669 bestPattern
= patGen
->getBestPattern(patternData
[dataIndex
++], status
);
670 logln(UnicodeString(" -> ") + bestPattern
);
672 SimpleDateFormat
sdf(bestPattern
, loc
, status
);
674 resultDate
= sdf
.format(testDate
, resultDate
);
675 if ( resultDate
!= patternResults
[resultIndex
] ) {
676 errln(UnicodeString("\nERROR: Test various skeletons[") + (dataIndex
-1) + UnicodeString("], localeIndex ") + localeIndex
+
677 UnicodeString(". Got: \"") + resultDate
+ UnicodeString("\" Expected: \"") + patternResults
[resultIndex
] + "\"" );
686 // ======= More tests ticket#6110
687 logln("Testing DateTimePatternGenerator with various skeleton");
689 status
= U_ZERO_ERROR
;
692 testDate
= LocaleTest::date(99, 9, 13, 23, 58, 59);
695 UnicodeString bestPattern
;
696 logln("\n\n Test various skeletons for English locale...");
697 DateTimePatternGenerator
*patGen
=DateTimePatternGenerator::createInstance(Locale::getEnglish(), status
);
698 if(U_FAILURE(status
)) {
699 dataerrln("ERROR: Could not create DateTimePatternGenerator with locale English . - exitting\n");
702 TimeZone
*enZone
= TimeZone::createTimeZone(UnicodeString("ECT/GMT"));
704 dataerrln("ERROR: Could not create TimeZone ECT");
708 SimpleDateFormat
*enFormat
= (SimpleDateFormat
*)DateFormat::createDateTimeInstance(DateFormat::kFull
,
709 DateFormat::kFull
, Locale::getEnglish());
710 enFormat
->setTimeZone(*enZone
);
711 while (patternTests2
[dataIndex
].length() > 0) {
712 logln(patternTests2
[dataIndex
]);
713 bestPattern
= patGen
->getBestPattern(patternTests2
[dataIndex
], status
);
714 logln(UnicodeString(" -> ") + bestPattern
);
715 enFormat
->applyPattern(bestPattern
);
717 resultDate
= enFormat
->format(testDate
, resultDate
);
718 if ( resultDate
!= patternResults2
[resultIndex
] ) {
719 errln(UnicodeString("\nERROR: Test various skeletons[") + dataIndex
720 + UnicodeString("]. Got: ") + resultDate
+ UnicodeString(" Expected: ") +
721 patternResults2
[resultIndex
] );
733 // ======= Test random skeleton
734 DateTimePatternGenerator
*randDTGen
= DateTimePatternGenerator::createInstance(status
);
735 if (U_FAILURE(status
)) {
736 dataerrln("ERROR: Could not create DateTimePatternGenerator (Locale::getFrench()) - exitting");
740 for (i
=0; i
<10; ++i
) {
741 UnicodeString randomSkeleton
;
742 int32_t len
= rand() % 20;
743 for (int32_t j
=0; j
<len
; ++j
) {
744 while ((newChar
= (UChar
)(rand()%0x7f
))>=(UChar
)0x20) {
745 randomSkeleton
+= newChar
;
748 UnicodeString bestPattern
= randDTGen
->getBestPattern(randomSkeleton
, status
);
752 // UnicodeString randomString=Unicode
753 // ======= Test getStaticClassID()
755 logln("Testing getStaticClassID()");
756 status
= U_ZERO_ERROR
;
757 DateTimePatternGenerator
*test
= DateTimePatternGenerator::createInstance(status
);
759 if(test
->getDynamicClassID() != DateTimePatternGenerator::getStaticClassID()) {
760 errln("ERROR: getDynamicClassID() didn't return the expected value");
764 // ====== Test createEmptyInstance()
766 logln("Testing createEmptyInstance()");
767 status
= U_ZERO_ERROR
;
769 test
= DateTimePatternGenerator::createEmptyInstance(status
);
770 if(U_FAILURE(status
)) {
771 errln("ERROR: Fail to create an empty instance ! - exitting.\n");
776 conflictingStatus
= test
->addPattern(UnicodeString("MMMMd"), true, conflictingPattern
, status
);
777 status
= U_ZERO_ERROR
;
778 testPattern
=test
->getBestPattern(UnicodeString("MMMMdd"), status
);
779 conflictingStatus
= test
->addPattern(UnicodeString("HH:mm"), true, conflictingPattern
, status
);
780 conflictingStatus
= test
->addPattern(UnicodeString("MMMMMdd"), true, conflictingPattern
, status
); //duplicate pattern
781 StringEnumeration
*output
=NULL
;
782 output
= test
->getRedundants(status
);
783 expectedResult
=UnicodeString("MMMMd");
784 if (output
!= NULL
) {
785 output
->reset(status
);
786 const UnicodeString
*dupPattern
=output
->snext(status
);
787 if ( (dupPattern
==NULL
) || (*dupPattern
!= expectedResult
) ) {
788 errln("ERROR: Fail in getRedundants !\n");
792 // ======== Test getSkeletons and getBaseSkeletons
793 StringEnumeration
* ptrSkeletonEnum
= test
->getSkeletons(status
);
794 if(U_FAILURE(status
)) {
795 errln("ERROR: Fail to get skeletons !\n");
797 UnicodeString returnPattern
, *ptrSkeleton
;
798 ptrSkeletonEnum
->reset(status
);
799 count
=ptrSkeletonEnum
->count(status
);
800 for (i
=0; i
<count
; ++i
) {
801 ptrSkeleton
= (UnicodeString
*)ptrSkeletonEnum
->snext(status
);
802 returnPattern
= test
->getPatternForSkeleton(*ptrSkeleton
);
803 if ( returnPattern
!= testSkeletonsResults
[i
] ) {
804 errln(UnicodeString("ERROR: Unexpected result from getSkeletons and getPatternForSkeleton\nGot: ") + returnPattern
805 + UnicodeString("\nExpected: ") + testSkeletonsResults
[i
]
806 + UnicodeString("\n"));
809 StringEnumeration
* ptrBaseSkeletonEnum
= test
->getBaseSkeletons(status
);
810 if(U_FAILURE(status
)) {
811 errln("ERROR: Fail to get base skeletons !\n");
813 count
=ptrBaseSkeletonEnum
->count(status
);
814 for (i
=0; i
<count
; ++i
) {
815 ptrSkeleton
= (UnicodeString
*)ptrBaseSkeletonEnum
->snext(status
);
816 if ( *ptrSkeleton
!= testBaseSkeletonsResults
[i
] ) {
817 errln("ERROR: Unexpected result from getBaseSkeletons() !\n");
821 // ========= DateTimePatternGenerator sample code in Userguide
822 // set up the generator
823 Locale locale
= Locale::getFrench();
824 status
= U_ZERO_ERROR
;
825 DateTimePatternGenerator
*generator
= DateTimePatternGenerator::createInstance( locale
, status
);
827 // get a pattern for an abbreviated month and day
828 pattern
= generator
->getBestPattern(UnicodeString("MMMd"), status
);
829 SimpleDateFormat
formatter(pattern
, locale
, status
);
831 zone
= TimeZone::createTimeZone(UnicodeString("GMT"));
832 formatter
.setTimeZone(*zone
);
833 // use it to format (or parse)
834 UnicodeString formatted
;
835 formatted
= formatter
.format(Calendar::getNow(), formatted
, status
);
836 // for French, the result is "13 sept."
838 // cannot use the result from getNow() because the value change evreyday.
839 testDate
= LocaleTest::date(99, 0, 13, 23, 58, 59);
840 formatted
= formatter
.format(testDate
, formatted
, status
);
841 expectedResult
=UnicodeString("14 janv.");
842 if ( formatted
!= expectedResult
) {
843 errln("ERROR: Userguide sample code result!");
844 errln(UnicodeString(" Got: ")+ formatted
+ UnicodeString(" Expected: ") + expectedResult
);
849 delete ptrSkeletonEnum
;
850 delete ptrBaseSkeletonEnum
;
856 * Test handling of options
858 * For reference, as of ICU 4.3.3,
874 typedef struct DTPtnGenOptionsData
{
877 const char *expectedPattern
;
878 UDateTimePatternMatchOptions options
;
879 } DTPtnGenOptionsData
;
880 void IntlTestDateTimePatternGeneratorAPI::testOptions(/*char *par*/)
882 DTPtnGenOptionsData testData
[] = {
883 // locale skel expectedPattern options
884 { "en", "Hmm", "HH:mm", UDATPG_MATCH_NO_OPTIONS
},
885 { "en", "HHmm", "HH:mm", UDATPG_MATCH_NO_OPTIONS
},
886 { "en", "hhmm", "h:mm a", UDATPG_MATCH_NO_OPTIONS
},
887 { "en", "Hmm", "HH:mm", UDATPG_MATCH_HOUR_FIELD_LENGTH
},
888 { "en", "HHmm", "HH:mm", UDATPG_MATCH_HOUR_FIELD_LENGTH
},
889 { "en", "hhmm", "hh:mm a", UDATPG_MATCH_HOUR_FIELD_LENGTH
},
890 { "da", "Hmm", "HH.mm", UDATPG_MATCH_NO_OPTIONS
},
891 { "da", "HHmm", "HH.mm", UDATPG_MATCH_NO_OPTIONS
},
892 { "da", "hhmm", "h.mm a", UDATPG_MATCH_NO_OPTIONS
},
893 { "da", "Hmm", "H.mm", UDATPG_MATCH_HOUR_FIELD_LENGTH
},
894 { "da", "HHmm", "HH.mm", UDATPG_MATCH_HOUR_FIELD_LENGTH
},
895 { "da", "hhmm", "hh.mm a", UDATPG_MATCH_HOUR_FIELD_LENGTH
},
897 { "en", "yyyy", "yyyy", UDATPG_MATCH_NO_OPTIONS
},
898 { "en", "YYYY", "YYYY", UDATPG_MATCH_NO_OPTIONS
},
899 { "en", "U", "y", UDATPG_MATCH_NO_OPTIONS
},
900 { "en@calendar=japanese", "yyyy", "y G", UDATPG_MATCH_NO_OPTIONS
},
901 { "en@calendar=japanese", "YYYY", "Y G", UDATPG_MATCH_NO_OPTIONS
},
902 { "en@calendar=japanese", "U", "y G", UDATPG_MATCH_NO_OPTIONS
},
903 { "en@calendar=chinese", "yyyy", "r(U)", UDATPG_MATCH_NO_OPTIONS
},
904 { "en@calendar=chinese", "YYYY", "Y(Y)", UDATPG_MATCH_NO_OPTIONS
}, // not a good result, want r(Y) or r(U)
905 { "en@calendar=chinese", "U", "r(U)", UDATPG_MATCH_NO_OPTIONS
},
906 { "en@calendar=chinese", "Gy", "r(U)", UDATPG_MATCH_NO_OPTIONS
},
907 { "en@calendar=chinese", "GU", "r(U)", UDATPG_MATCH_NO_OPTIONS
},
908 { "en@calendar=chinese", "ULLL", "MMM U", UDATPG_MATCH_NO_OPTIONS
},
909 { "en@calendar=chinese", "yMMM", "MMM r(U)", UDATPG_MATCH_NO_OPTIONS
},
910 { "en@calendar=chinese", "GUMMM", "MMM r(U)", UDATPG_MATCH_NO_OPTIONS
},
911 { "zh@calendar=chinese", "yyyy", "U\\u5E74", UDATPG_MATCH_NO_OPTIONS
},
912 { "zh@calendar=chinese", "YYYY", "Y\\u5E74", UDATPG_MATCH_NO_OPTIONS
}, // not a great result, may want r(Y) or r(U)
913 { "zh@calendar=chinese", "U", "U\\u5E74", UDATPG_MATCH_NO_OPTIONS
},
914 { "zh@calendar=chinese", "Gy", "rU\\u5E74", UDATPG_MATCH_NO_OPTIONS
},
915 { "zh@calendar=chinese", "GU", "rU\\u5E74", UDATPG_MATCH_NO_OPTIONS
},
916 { "zh@calendar=chinese", "ULLL", "U\\u5E74MMM", UDATPG_MATCH_NO_OPTIONS
},
917 { "zh@calendar=chinese", "yMMM", "rU\\u5E74MMM", UDATPG_MATCH_NO_OPTIONS
},
918 { "zh@calendar=chinese", "GUMMM", "rU\\u5E74MMM", UDATPG_MATCH_NO_OPTIONS
},
921 int count
= UPRV_LENGTHOF(testData
);
922 const DTPtnGenOptionsData
* testDataPtr
= testData
;
924 for (; count
-- > 0; ++testDataPtr
) {
925 UErrorCode status
= U_ZERO_ERROR
;
927 Locale
locale(testDataPtr
->locale
);
928 UnicodeString
skel(testDataPtr
->skel
);
929 UnicodeString
expectedPattern(UnicodeString(testDataPtr
->expectedPattern
).unescape());
930 UDateTimePatternMatchOptions options
= testDataPtr
->options
;
932 DateTimePatternGenerator
* dtpgen
= DateTimePatternGenerator::createInstance(locale
, status
);
933 if (U_FAILURE(status
)) {
934 dataerrln("Unable to create DateTimePatternGenerator instance for locale(%s): %s", locale
.getName(), u_errorName(status
));
938 UnicodeString pattern
= dtpgen
->getBestPattern(skel
, options
, status
);
939 if (pattern
.compare(expectedPattern
) != 0) {
940 errln( UnicodeString("ERROR in getBestPattern, locale ") + UnicodeString(testDataPtr
->locale
) +
941 UnicodeString(", skeleton ") + skel
+
942 ((options
)?UnicodeString(", options!=0"):UnicodeString(", options==0")) +
943 UnicodeString(", expected pattern ") + expectedPattern
+
944 UnicodeString(", got ") + pattern
);
951 * Test that DTPG can handle all valid pattern character / length combinations
954 #define FIELD_LENGTHS_COUNT 6
955 #define FIELD_LENGTH_MAX 8
956 #define MUST_INCLUDE_COUNT 5
958 typedef struct AllFieldsTestItem
{
960 int8_t fieldLengths
[FIELD_LENGTHS_COUNT
+1]; // up to FIELD_LENGTHS_COUNT lengths to try
961 // (length <=FIELD_LENGTH_MAX) plus 0 terminator
962 char mustIncludeOneOf
[MUST_INCLUDE_COUNT
+1];// resulting pattern must include at least one of
963 // these as a pattern char (0-terminated list)
966 void IntlTestDateTimePatternGeneratorAPI::testAllFieldPatterns(/*char *par*/)
968 const char * localeNames
[] = {
970 "root@calendar=japanese",
971 "root@calendar=chinese",
973 "en@calendar=japanese",
974 "en@calendar=chinese",
977 AllFieldsTestItem testData
[] = {
978 //pat fieldLengths generated pattern must
979 //chr to test include one of these
980 { 'G', {1,2,3,4,5,0}, "G" }, // era
982 { 'y', {1,2,3,4,0}, "yU" }, // year
983 { 'Y', {1,2,3,4,0}, "Y" }, // year for week of year
984 { 'u', {1,2,3,4,5,0}, "yuU" }, // extended year
985 { 'U', {1,2,3,4,5,0}, "yU" }, // cyclic year name
987 { 'Q', {1,2,3,4,0}, "Qq" }, // x
988 { 'q', {1,2,3,4,0}, "Qq" }, // standalone
990 { 'M', {1,2,3,4,5,0}, "ML" }, // x
991 { 'L', {1,2,3,4,5,0}, "ML" }, // standalone
993 { 'w', {1,2,0}, "w" }, // week of year
994 { 'W', {1,0}, "W" }, // week of month
996 { 'd', {1,2,0}, "d" }, // day of month
997 { 'D', {1,2,3,0}, "D" }, // day of year
998 { 'F', {1,0}, "F" }, // day of week in month
999 { 'g', {7,0}, "g" }, // modified julian day
1001 { 'E', {1,2,3,4,5,6}, "Eec" }, // day of week
1002 { 'e', {1,2,3,4,5,6}, "Eec" }, // local day of week
1003 { 'c', {1,2,3,4,5,6}, "Eec" }, // standalone local day of week
1005 { 'a', {1,2,3,4,5,0}, "a" }, // am or pm
1006 { 'b', {1,2,3,4,5,0}, "b" }, // dayPeriod AM/PM/noon
1007 { 'B', {1,2,3,4,5,0}, "B" }, // dayPeriod ranges
1009 { 'h', {1,2,0}, "hK" }, // 12 (1-12)
1010 { 'H', {1,2,0}, "Hk" }, // 24 (0-23)
1011 { 'K', {1,2,0}, "hK" }, // 12 (0-11)
1012 { 'k', {1,2,0}, "Hk" }, // 24 (1-24)
1013 { 'j', {1,2,0}, "hHKk" }, // locale default
1014 { 'J', {1,2,0}, "hHKk" }, // locale default, without any dayPeriod
1015 { 'C', {1,2,0}, "hHKk" }, // locale allowed first entry, possibly with b or B
1017 { 'm', {1,2,0}, "m" }, // x
1018 // second & fractions
1019 { 's', {1,2,0}, "s" }, // x
1020 { 'S', {1,2,3,4,0}, "S" }, // fractional second
1021 { 'A', {8,0}, "A" }, // milliseconds in day
1023 { 'z', {1,2,3,4,0}, "z" }, // x
1024 { 'Z', {1,2,3,4,5,0}, "Z" }, // x
1025 { 'O', {1,4,0}, "O" }, // x
1026 { 'v', {1,4,0}, "v" }, // x
1027 { 'V', {1,2,3,4,0}, "V" }, // x
1028 { 'X', {1,2,3,4,5,0}, "X" }, // x
1029 { 'x', {1,2,3,4,5,0}, "x" }, // x
1032 const char ** localeNamesPtr
= localeNames
;
1033 const char * localeName
;
1034 while ( (localeName
= *localeNamesPtr
++) != NULL
) {
1035 UErrorCode status
= U_ZERO_ERROR
;
1036 Locale locale
= Locale::createFromName(localeName
);
1037 DateTimePatternGenerator
* dtpg
= DateTimePatternGenerator::createInstance(locale
, status
);
1038 if (U_SUCCESS(status
)) {
1039 const AllFieldsTestItem
* testDataPtr
= testData
;
1040 int itemCount
= UPRV_LENGTHOF(testData
);
1041 for (; itemCount
-- > 0; ++testDataPtr
) {
1042 char skelBuf
[FIELD_LENGTH_MAX
];
1043 int32_t chrIndx
, lenIndx
;
1044 for (chrIndx
= 0; chrIndx
< FIELD_LENGTH_MAX
; chrIndx
++) {
1045 skelBuf
[chrIndx
] = testDataPtr
->patternChar
;
1047 for (lenIndx
= 0; lenIndx
< FIELD_LENGTHS_COUNT
; lenIndx
++) {
1048 int32_t skelLen
= testDataPtr
->fieldLengths
[lenIndx
];
1052 if (skelLen
> FIELD_LENGTH_MAX
) {
1055 UnicodeString
skeleton(skelBuf
, skelLen
, US_INV
);
1056 UnicodeString pattern
= dtpg
->getBestPattern(skeleton
, status
);
1057 if (U_FAILURE(status
)) {
1058 errln("DateTimePatternGenerator getBestPattern for locale %s, skelChar %c skelLength %d fails: %s",
1059 locale
.getName(), testDataPtr
->patternChar
, skelLen
, u_errorName(status
));
1060 } else if (pattern
.length() <= 0) {
1061 errln("DateTimePatternGenerator getBestPattern for locale %s, skelChar %c skelLength %d produces 0-length pattern",
1062 locale
.getName(), testDataPtr
->patternChar
, skelLen
);
1064 // test that resulting pattern has at least one char in mustIncludeOneOf
1065 UnicodeString
mustIncludeOneOf(testDataPtr
->mustIncludeOneOf
, -1, US_INV
);
1066 int32_t patIndx
, patLen
= pattern
.length();
1067 UBool inQuoted
= FALSE
;
1068 for (patIndx
= 0; patIndx
< patLen
; patIndx
++) {
1069 UChar c
= pattern
.charAt(patIndx
);
1071 inQuoted
= !inQuoted
;
1072 } else if (!inQuoted
&& c
<= 0x007A && c
>= 0x0041) {
1073 if (mustIncludeOneOf
.indexOf(c
) >= 0) {
1078 if (patIndx
>= patLen
) {
1079 errln(UnicodeString("DateTimePatternGenerator getBestPattern for locale ") +
1080 UnicodeString(locale
.getName(),-1,US_INV
) +
1081 ", skeleton " + skeleton
+
1082 ", produces pattern without required chars: " + pattern
);
1090 dataerrln("Create DateTimePatternGenerator instance for locale(%s) fails: %s",
1091 locale
.getName(), u_errorName(status
));
1096 void IntlTestDateTimePatternGeneratorAPI::testStaticGetSkeleton(/*char *par*/)
1098 // Verify that staticGetSkeleton() doesn't mangle skeletons. (Ticket #11985)
1099 static const char* const testData
[] = {
1106 for (size_t i
= 0; i
< UPRV_LENGTHOF(testData
); i
++) {
1107 UErrorCode status
= U_ZERO_ERROR
;
1108 UnicodeString skeleton
= DateTimePatternGenerator::staticGetSkeleton(testData
[i
], status
);
1109 if (!assertSuccess("staticGetSkeleton", status
)) {
1112 assertEquals("Skeleton", testData
[i
], skeleton
);
1116 void IntlTestDateTimePatternGeneratorAPI::testC() {
1117 const char* tests
[][3] = {
1118 // These may change with actual data for Bhmm/bhmm skeletons
1119 {"zh", "Cm", "Bh:mm"},
1120 {"zh", "CCm", "Bhh:mm"},
1121 {"zh", "CCCm", "BBBBh:mm"},
1122 {"zh", "CCCCm", "BBBBhh:mm"},
1123 {"zh", "CCCCCm", "BBBBBh:mm"},
1124 {"zh", "CCCCCCm", "BBBBBhh:mm"},
1125 {"de", "Cm", "HH:mm"},
1126 {"de", "CCm", "HH:mm"},
1127 {"de", "CCCm", "HH:mm"},
1128 {"de", "CCCCm", "HH:mm"},
1129 {"en", "Cm", "h:mm a"},
1130 {"en", "CCm", "hh:mm a"},
1131 {"en", "CCCm", "h:mm aaaa"},
1132 {"en", "CCCCm", "hh:mm aaaa"},
1133 {"en", "CCCCCm", "h:mm aaaaa"},
1134 {"en", "CCCCCCm", "hh:mm aaaaa"},
1135 {"en-BN", "Cm", "h:mm b"},
1136 {"gu-IN", "Cm", "h:mm B"},
1137 {"und-IN", "Cm", "h:mm B"}
1140 UErrorCode status
= U_ZERO_ERROR
;
1141 int32_t numTests
= UPRV_LENGTHOF(tests
);
1142 for (int32_t i
= 0; i
< numTests
; ++i
) {
1143 DateTimePatternGenerator
*gen
= DateTimePatternGenerator::createInstance(
1144 Locale::forLanguageTag(tests
[i
][0], status
), status
);
1146 dataerrln("FAIL: DateTimePatternGenerator::createInstance failed for %s", tests
[i
][0]);
1149 UDateTimePatternMatchOptions options
= UDATPG_MATCH_HOUR_FIELD_LENGTH
;
1150 UnicodeString pattern
= gen
->getBestPattern(tests
[i
][1], options
, status
);
1151 UnicodeString expectedPattern
= tests
[i
][2];
1153 char message
[100] = "\0";
1154 strcat(message
, tests
[i
][0]);
1155 strcat(message
, "/");
1156 strcat(message
, tests
[i
][1]);
1157 assertEquals(message
, expectedPattern
, pattern
);
1162 enum { kCharBufMax
= 31 };
1163 void IntlTestDateTimePatternGeneratorAPI::testSkeletonsWithDayPeriods() {
1164 const char * patterns
[] = {
1165 // since icu4c getEmptyInstance does not call addCanonicalItems (unlike J), set these here:
1166 "a", // should get internal skeleton a
1167 "H", // should get internalskeleton H
1168 "m", // should get internalskeleton m
1169 "s", // should get internalskeleton s
1170 // patterns from which to construct sample data for a locale
1171 //"H", // should get internalskeleton H
1172 "h a", // should get internalskeleton ah
1173 "B h", // should get internalskeleton Bh
1175 const char* testItems
[][2] = {
1176 // sample requested skeletons and results
1189 { "aaaah", "h aaaa"},
1190 { "aaaahh", "hh aaaa"},
1193 { "bbbbh", "h bbbb"},
1196 { "BBBBh", "BBBB h"},
1197 { "BBBBhh", "BBBB hh"},
1199 { "aaaaa", "aaaaa"},
1205 UErrorCode status
= U_ZERO_ERROR
;
1206 DateTimePatternGenerator
*gen
= DateTimePatternGenerator::createEmptyInstance(status
);
1207 if (U_FAILURE(status
)) {
1208 errln("ERROR: createEmptyInstance fails, status: %s", u_errorName(status
));
1210 int32_t i
, len
= UPRV_LENGTHOF(patterns
);
1211 for (i
= 0; i
< len
; i
++) {
1212 UnicodeString conflictingPattern
;
1213 (void)gen
->addPattern(UnicodeString(patterns
[i
]), TRUE
, conflictingPattern
, status
);
1214 if (U_FAILURE(status
)) {
1215 errln("ERROR: addPattern %s fail, status: %s", patterns
[i
], u_errorName(status
));
1219 if (U_SUCCESS(status
)) {
1220 len
= UPRV_LENGTHOF(testItems
);
1221 for (i
= 0; i
< len
; i
++) {
1222 status
= U_ZERO_ERROR
;
1223 UDateTimePatternMatchOptions options
= UDATPG_MATCH_HOUR_FIELD_LENGTH
;
1224 UnicodeString result
= gen
->getBestPattern(UnicodeString(testItems
[i
][0]), options
, status
);
1225 if (U_FAILURE(status
)) {
1226 errln("ERROR: getBestPattern %s fail, status: %s", testItems
[i
][0], u_errorName(status
));
1227 } else if (result
!= UnicodeString(testItems
[i
][1])) {
1228 char charResult
[kCharBufMax
+1];
1229 result
.extract(0, result
.length(), charResult
, kCharBufMax
);
1230 charResult
[kCharBufMax
] = 0; // ensure termination
1231 errln("ERROR: getBestPattern %s, expected %s, got %s", testItems
[i
][0], testItems
[i
][1], charResult
);
1239 typedef struct FieldDisplayNameData
{
1240 const char * locale
;
1241 UDateTimePatternField field
;
1242 UDateTimePGDisplayWidth width
;
1243 const char * expected
; // can have escapes such as \\u00E0
1244 } FieldDisplayNameData
;
1245 enum { kFieldDisplayNameMax
= 32 };
1247 void IntlTestDateTimePatternGeneratorAPI::testGetFieldDisplayNames() {
1248 const FieldDisplayNameData testData
[] = {
1249 /*loc field width expectedName */
1250 { "de", UDATPG_QUARTER_FIELD
, UDATPG_WIDE
, "Quartal" },
1251 { "de", UDATPG_QUARTER_FIELD
, UDATPG_ABBREVIATED
, "Quart." },
1252 { "de", UDATPG_QUARTER_FIELD
, UDATPG_NARROW
, "Q" },
1253 { "en", UDATPG_DAY_OF_WEEK_IN_MONTH_FIELD
, UDATPG_WIDE
, "weekday of the month" },
1254 { "en", UDATPG_DAY_OF_WEEK_IN_MONTH_FIELD
, UDATPG_ABBREVIATED
, "wkday. of mo." },
1255 { "en", UDATPG_DAY_OF_WEEK_IN_MONTH_FIELD
, UDATPG_NARROW
, "wkday. of mo." }, // fallback
1256 { "en_GB", UDATPG_DAY_OF_WEEK_IN_MONTH_FIELD
, UDATPG_WIDE
, "weekday of the month" },
1257 { "en_GB", UDATPG_DAY_OF_WEEK_IN_MONTH_FIELD
, UDATPG_ABBREVIATED
, "wkday of mo" }, // override
1258 { "en_GB", UDATPG_DAY_OF_WEEK_IN_MONTH_FIELD
, UDATPG_NARROW
, "wkday of mo" },
1259 { "it", UDATPG_SECOND_FIELD
, UDATPG_WIDE
, "secondo" },
1260 { "it", UDATPG_SECOND_FIELD
, UDATPG_ABBREVIATED
, "s" },
1261 { "it", UDATPG_SECOND_FIELD
, UDATPG_NARROW
, "s" },
1264 int count
= UPRV_LENGTHOF(testData
);
1265 const FieldDisplayNameData
* testDataPtr
= testData
;
1266 for (; count
-- > 0; ++testDataPtr
) {
1267 UErrorCode status
= U_ZERO_ERROR
;
1268 Locale
locale(testDataPtr
->locale
);
1269 DateTimePatternGenerator
* dtpg
= DateTimePatternGenerator::createInstance(locale
, status
);
1270 if (U_FAILURE(status
)) {
1271 dataerrln("FAIL: DateTimePatternGenerator::createInstance failed for locale %s", testDataPtr
->locale
);
1273 UChar expName
[kFieldDisplayNameMax
+1];
1274 u_unescape(testDataPtr
->expected
, expName
, kFieldDisplayNameMax
);
1275 expName
[kFieldDisplayNameMax
] = 0; // ensure 0 termination
1276 UnicodeString getName
= dtpg
->getFieldDisplayName(testDataPtr
->field
, testDataPtr
->width
);
1277 if (getName
.compare(expName
, u_strlen(expName
)) != 0) {
1278 errln("ERROR: locale %s field %d width %d, expected %s\n",
1279 testDataPtr
->locale
, testDataPtr
->field
, testDataPtr
->width
, testDataPtr
->expected
);
1286 static const UChar timeCycleChars
[] = { (UChar
)0x0048, (UChar
)0x0068, (UChar
)0x004B, (UChar
)0x006B, (UChar
)0 };
1288 void IntlTestDateTimePatternGeneratorAPI::testJjMapping() {
1289 UErrorCode status
= U_ZERO_ERROR
;
1290 UnicodeString
jSkeleton("j");
1291 // First test that j maps correctly by region in a locale for which we do not have data.
1293 const char* testLocaleID
= "de_US"; // short patterns from fallback locale "de" have "HH"
1294 Locale
testLocale(testLocaleID
);
1295 LocalPointer
<DateTimePatternGenerator
> dtpg(DateTimePatternGenerator::createInstance(testLocale
, status
));
1296 if (U_FAILURE(status
)) {
1297 dataerrln("FAIL: DateTimePatternGenerator::createInstance failed for locale %s: %s", testLocaleID
, u_errorName(status
));
1299 UnicodeString jPattern
= dtpg
->getBestPattern(jSkeleton
, UDATPG_MATCH_ALL_FIELDS_LENGTH
, status
); // get pattern with h e.g. "h 'Uhr' a"
1300 if (U_FAILURE(status
)) {
1301 errln("FAIL: DateTimePatternGenerator::getBestPattern locale %s, pattern j: %s", testLocaleID
, u_errorName(status
));
1303 UnicodeString jPatSkeleton
= DateTimePatternGenerator::staticGetSkeleton(jPattern
, status
); // strip literals, get e.g. "ah"
1304 if (U_FAILURE(status
)) {
1305 errln("FAIL: DateTimePatternGenerator::staticGetSkeleton locale %s: %s", testLocaleID
, u_errorName(status
));
1306 } else if (jPatSkeleton
.indexOf(u
'h') < 0) { // expect US preferred cycle 'h', not H or other cycle
1307 errln("ERROR: DateTimePatternGenerator::getBestPattern locale %s, pattern j did not use 'h'", testLocaleID
);
1313 // Next test that in all available Locales, the actual short time pattern uses the same cycle as produced by 'j'
1315 const Locale
* localePtr
= DateFormat::getAvailableLocales(locCount
);
1316 for (; locCount
-- > 0; localePtr
++) {
1317 const char* localeID
= localePtr
->getName();
1318 status
= U_ZERO_ERROR
;
1319 LocalPointer
<DateTimePatternGenerator
> dtpg(DateTimePatternGenerator::createInstance(*localePtr
, status
));
1320 if (U_FAILURE(status
)) {
1321 dataerrln("FAIL: DateTimePatternGenerator::createInstance failed for locale %s: %s", localeID
, u_errorName(status
));
1324 LocalPointer
<DateFormat
> dfmt(DateFormat::createTimeInstance(DateFormat::kShort
, *localePtr
));
1325 if (U_FAILURE(status
)) {
1326 dataerrln("FAIL: DateFormat::createTimeInstance kShort failed for locale %s: %s", localeID
, u_errorName(status
));
1329 const SimpleDateFormat
* sdfmt
;
1330 if ((sdfmt
= dynamic_cast<const SimpleDateFormat
*>(reinterpret_cast<const DateFormat
*>(dfmt
.getAlias()))) == NULL
) {
1333 UnicodeString shortPattern
;
1334 shortPattern
= sdfmt
->toPattern(shortPattern
);
1335 UnicodeString jPattern
= dtpg
->getBestPattern(jSkeleton
, status
);
1336 if (U_FAILURE(status
)) {
1337 errln("FAIL: DateTimePatternGenerator::getBestPattern locale %s, pattern j: %s", localeID
, u_errorName(status
));
1340 // Now check that shortPattern and jPattern use the same hour cycle
1341 UnicodeString jPatSkeleton
= DateTimePatternGenerator::staticGetSkeleton(jPattern
, status
);
1342 UnicodeString shortPatSkeleton
= DateTimePatternGenerator::staticGetSkeleton(shortPattern
, status
);
1343 if (U_FAILURE(status
)) {
1344 errln("FAIL: DateTimePatternGenerator::staticGetSkeleton locale %s: %s", localeID
, u_errorName(status
));
1347 const UChar
* charPtr
= timeCycleChars
;
1348 for (; *charPtr
!= (UChar
)0; charPtr
++) {
1349 if (jPatSkeleton
.indexOf(*charPtr
) >= 0) {
1350 if (shortPatSkeleton
.indexOf(*charPtr
) < 0) {
1351 char jcBuf
[2], spBuf
[32];
1352 u_austrncpy(jcBuf
, charPtr
, 1);
1354 shortPattern
.extract(0, shortPattern
.length(), spBuf
, 32);
1355 const char* dfmtCalType
= (dfmt
->getCalendar())->getType();
1356 errln("ERROR: locale %s, expected j resolved char %s to occur in short time pattern %s for %s", localeID
, jcBuf
, spBuf
, dfmtCalType
);
1364 #endif /* #if !UCONFIG_NO_FORMATTING */