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