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 
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)26 void 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  */
testAPI()42 void 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 \\u0433."),     // 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         CharsToUnicodeString("11:58 \\u041F\\u041F"),                     // 08: 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 \\u0433."), // 12: yyyyMMMM -> LLLL y
266         CharsToUnicodeString("\\u0441\\u0440, 13 \\u044F\\u043D\\u0432."), // 13: MMMEd -> ccc, d MMM
267         CharsToUnicodeString("\\u0441\\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  */
843 typedef struct DTPtnGenOptionsData {
844     const char *locale;
845     const char *skel;
846     const char *expectedPattern;
847     UDateTimePatternMatchOptions    options;
848 } DTPtnGenOptionsData;
testOptions()849 void 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         { "da", "Hmm",  "HH.mm",   UDATPG_MATCH_NO_OPTIONS        },
860         { "da", "HHmm", "HH.mm",   UDATPG_MATCH_NO_OPTIONS        },
861         { "da", "hhmm", "h.mm a",  UDATPG_MATCH_NO_OPTIONS        },
862         { "da", "Hmm",  "H.mm",    UDATPG_MATCH_HOUR_FIELD_LENGTH },
863         { "da", "HHmm", "HH.mm",   UDATPG_MATCH_HOUR_FIELD_LENGTH },
864         { "da", "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 
927 typedef 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 
testAllFieldPatterns()935 void 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