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