1/********************************************************************
2 * COPYRIGHT:
3 * Copyright (c) 2008-2010, International Business Machines Corporation and
4 * others. All Rights Reserved.
5 ********************************************************************/
6
7#include "unicode/utypes.h"
8
9#if !UCONFIG_NO_FORMATTING
10
11#include <stdio.h>
12#include <stdlib.h>
13#include "dtptngts.h"
14
15#include "unicode/calendar.h"
16#include "unicode/smpdtfmt.h"
17#include "unicode/dtfmtsym.h"
18#include "unicode/dtptngen.h"
19#include "loctest.h"
20
21
22// This is an API test, not a unit test.  It doesn't test very many cases, and doesn't
23// try to test the full functionality.  It just calls each function in the class and
24// verifies that it works on a basic level.
25
26void IntlTestDateTimePatternGeneratorAPI::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ )
27{
28    if (exec) logln("TestSuite DateTimePatternGeneratorAPI");
29    switch (index) {
30        TESTCASE(0, testAPI);
31        TESTCASE(1, testOptions);
32        default: name = ""; break;
33    }
34}
35
36#define MAX_LOCALE   8
37
38/**
39 * Test various generic API methods of DateTimePatternGenerator for API coverage.
40 */
41void IntlTestDateTimePatternGeneratorAPI::testAPI(/*char *par*/)
42{
43    UnicodeString patternData[] = {
44        UnicodeString("yM"),
45        UnicodeString("yMMM"),
46        UnicodeString("yMd"),
47        UnicodeString("yMMMd"),
48        UnicodeString("Md"),
49        UnicodeString("MMMd"),
50        UnicodeString("yQQQ"),
51        UnicodeString("hhmm"),
52        UnicodeString("HHmm"),
53        UnicodeString("jjmm"),
54        UnicodeString("mmss"),
55        UnicodeString("yyyyMMMM"),
56        UnicodeString(),
57     };
58
59    const char* testLocale[MAX_LOCALE][4] = {
60        {"en", "US", "", ""},
61        {"en", "US", "", "calendar=japanese"},
62        {"zh", "Hans", "CN", ""},
63        {"de", "DE", "", ""},
64        {"fi", "", "", ""},
65        {"ja", "", "", ""},
66        {"ja", "", "", "calendar=japanese"},
67        {"zh", "TW", "", "calendar=roc"},
68     };
69
70    UnicodeString patternResults[] = {
71        UnicodeString("1/1999"),                              // en_US
72        UnicodeString("Jan 1999"),
73        UnicodeString("1/13/1999"),
74        UnicodeString("Jan 13, 1999"),
75        UnicodeString("1/13"),
76        UnicodeString("Jan 13"),
77        UnicodeString("Q1 1999"),
78        UnicodeString("11:58 PM"),
79        UnicodeString("23:58"),
80        UnicodeString("11:58 PM"),                            // en_US  9: jjmm
81        UnicodeString("58:59"),
82        UnicodeString("January 1999"),                        // en_US 11: yyyyMMMM
83
84        // currently the following for en_US@calendar=japanese just verify the correct fallback behavior for ticket:5702;
85        // however some are not the "correct" results. To fix that, root needs better DateTimePatterns/availableFormats
86        // data; cldrbug #1994 is for that.
87        UnicodeString("H 11-01"),                             // en_US@calendar=japanese  0: yM
88        UnicodeString("H 11 Jan"),                            // en_US@calendar=japanese  1: yMMM
89        UnicodeString("H 11-01-13"),                          // en_US@calendar=japanese  2: yMd
90        UnicodeString("H 11 Jan 13"),                         // en_US@calendar=japanese  3: yMMMd
91        UnicodeString("1-13"),                                // en_US@calendar=japanese  4: Md
92        UnicodeString("Jan 13"),                              // en_US@calendar=japanese  5: MMMd
93        UnicodeString("H 11 Q1"),                             // en_US@calendar=japanese  6: yQQQ
94        UnicodeString("11:58 PM"),                            // en_US@calendar=japanese  7: hhmm
95        UnicodeString("23:58"),                               // en_US@calendar=japanese  8: HHmm
96        UnicodeString("23:58"),                               // en_US@calendar=japanese  9: jjmm
97        UnicodeString("58:59"),                               // en_US@calendar=japanese 10: mmss
98        UnicodeString("H 11 January"),                        // en_US@calendar=japanese 11: yyyyMMMM
99
100        UnicodeString("1999-1", -1, US_INV),                  // zh_Hans_CN: yM
101        CharsToUnicodeString("1999\\u5E741\\u6708"),          // zh_Hans_CN: yMMM  -> yyyy\u5E74MMM (fixed expected result per ticket:6626:)
102        CharsToUnicodeString("1999\\u5E741\\u670813\\u65E5"),
103        CharsToUnicodeString("1999\\u5E741\\u670813\\u65E5"), // zh_Hans_CN: yMMMd -> yyyy\u5E74MMMd\u65E5 (fixed expected result per ticket:6626:)
104        UnicodeString("1-13"),
105        CharsToUnicodeString("1\\u670813\\u65E5"),            // zh_Hans_CN: MMMd  -> MMMd\u65E5 (fixed expected result per ticket:6626:)
106        CharsToUnicodeString("1999\\u5E741\\u5B63"),
107        CharsToUnicodeString("\\u4E0B\\u534811:58"),
108        UnicodeString("23:58"),
109        CharsToUnicodeString("\\u4E0B\\u534811:58"),          // zh_Hans_CN  9: jjmm
110        UnicodeString("58:59"),
111        CharsToUnicodeString("1999\\u5E741\\u6708"),          // zh_Hans_CN 11: yyyyMMMM  -> yyyy\u5E74MMM
112
113        UnicodeString("1.1999"),  // de_DE
114        UnicodeString("Jan 1999"),
115        UnicodeString("13.1.1999"),
116        UnicodeString("13. Jan 1999"),
117        UnicodeString("13.1."),
118        UnicodeString("13. Jan"),
119        UnicodeString("Q1 1999"),
120        UnicodeString("11:58 nachm."),
121        UnicodeString("23:58"),
122        UnicodeString("23:58"),                               // de  9: jjmm
123        UnicodeString("58:59"),
124        UnicodeString("Januar 1999"),                         // de 11: yyyyMMMM
125
126        UnicodeString("1.1999"),                              // fi  0: yM (fixed expected result per ticket:6626:)
127        UnicodeString("tammi 1999"),                          // fi  1: yMMM
128        UnicodeString("13.1.1999"),
129        UnicodeString("13. tammikuuta 1999"),                 // fi  3: yMMMd
130        UnicodeString("13.1."),
131        UnicodeString("13. tammikuuta"),                      // fi  5: MMMd
132        UnicodeString("1. nelj. 1999"),
133        UnicodeString("11.58 ip."),                           // fi  7: hhmm
134        UnicodeString("23.58"),
135        UnicodeString("23.58"),                               // fi  9: jjmm
136        UnicodeString("58.59"),
137        UnicodeString("tammikuu 1999"),                       // fi 11: yyyyMMMM
138
139        UnicodeString("1999/1"),                              // ja 0: yM    -> y/M
140        CharsToUnicodeString("1999\\u5E741\\u6708"),          // ja 1: yMMM  -> y\u5E74M\u6708
141        UnicodeString("1999/1/13"),                           // ja 2: yMd   -> y/M/d
142        CharsToUnicodeString("1999\\u5E741\\u670813\\u65E5"), // ja 3: yMMMd -> y\u5E74M\u6708d\u65E5
143        UnicodeString("1/13"),                                // ja 4: Md    -> M/d
144        CharsToUnicodeString("1\\u670813\\u65E5"),            // ja 5: MMMd  -> M\u6708d\u65E5
145        UnicodeString("1999Q1"),                              // ja 6: yQQQ  -> yQQQ
146        CharsToUnicodeString("\\u5348\\u5F8C11:58"),          // ja 7: hhmm
147        UnicodeString("23:58"),                               // ja 8: HHmm  -> HH:mm
148        UnicodeString("23:58"),                               // ja 9: jjmm
149        UnicodeString("58:59"),                               // ja 10: mmss  -> mm:ss
150        CharsToUnicodeString("1999\\u5E741\\u6708"),          // ja 11: yyyyMMMM  -> y\u5E74M\u6708
151
152        CharsToUnicodeString("\\u5E73\\u621011/1"),                       // ja@japanese 0: yM    -> Gy/m
153        CharsToUnicodeString("\\u5E73\\u621011\\u5E741\\u6708"),          // ja@japanese 1: yMMM  -> Gy\u5E74M\u6708
154        CharsToUnicodeString("\\u5E73\\u621011/1/13"),                    // ja@japanese 2: yMd   -> Gy/m/d
155        CharsToUnicodeString("\\u5E73\\u621011\\u5E741\\u670813\\u65E5"), // ja@japanese 3: yMMMd -> Gy\u5E74M\u6708d\u65E5
156        UnicodeString("1/13"),                                            // ja@japanese 4: Md    -> M/d
157        CharsToUnicodeString("1\\u670813\\u65E5"),                        // ja@japanese 5: MMMd  -> M\u6708d\u65E5
158        CharsToUnicodeString("\\u5E73\\u621011/Q1"),                      // ja@japanese 6: yQQQ  -> Gy/QQQ
159        CharsToUnicodeString("\\u5348\\u5F8C11:58"),                      // ja@japanese 7: hhmm  ->
160        UnicodeString("23:58"),                                           // ja@japanese 8: HHmm  -> HH:mm          (as for ja)
161        UnicodeString("23:58"),                                           // ja@japanese 9: jjmm
162        UnicodeString("58:59"),                                           // ja@japanese 10: mmss  -> mm:ss          (as for ja)
163        CharsToUnicodeString("\\u5E73\\u621011\\u5E741\\u6708"),          // ja@japanese 11: yyyyMMMM  -> Gyyyy\u5E74M\u6708
164
165        CharsToUnicodeString("\\u6C11\\u570B88/1"),                       // zh_TW@roc 0: yM    -> Gy/M
166        CharsToUnicodeString("\\u6C11\\u570B88\\u5E741\\u6708"),          // zh_TW@roc 1: yMMM  -> Gy\u5E74M\u6708
167        CharsToUnicodeString("\\u6C11\\u570B88/1/13"),                    // zh_TW@roc 2: yMd   -> Gy/M/d
168        CharsToUnicodeString("\\u6C11\\u570B88\\u5E741\\u670813\\u65E5"), // zh_TW@roc 3: yMMMd -> Gy\u5E74M\u6708d\u65E5
169        UnicodeString("1/13"),                                            // zh_TW@roc 4: Md    -> M/d
170        CharsToUnicodeString("1\\u670813\\u65E5"),                        // zh_TW@roc 5: MMMd  ->M\u6708d\u65E5
171        CharsToUnicodeString("\\u6C11\\u570B88 1\\u5B63"),                // zh_TW@roc 6: yQQQ  -> Gy QQQ
172        CharsToUnicodeString("\\u4E0B\\u534811:58"),                      // zh_TW@roc 7: hhmm  ->
173        UnicodeString("23:58"),                                           // zh_TW@roc 8: HHmm  ->
174        CharsToUnicodeString("\\u4E0B\\u534811:58"),                      // zh_TW@roc 9: jjmm
175        UnicodeString("58:59"),                                           // zh_TW@roc 10: mmss  ->
176        CharsToUnicodeString("\\u6C11\\u570B88\\u5E741\\u6708"),          // zh_TW@roc 11: yyyyMMMM  -> Gy\u5E74M\u670
177
178        UnicodeString(),
179    };
180
181    UnicodeString patternTests2[] = {
182        UnicodeString("yyyyMMMdd"),
183        UnicodeString("yyyyqqqq"),
184        UnicodeString("yMMMdd"),
185        UnicodeString("EyyyyMMMdd"),
186        UnicodeString("yyyyMMdd"),
187        UnicodeString("yyyyMMM"),
188        UnicodeString("yyyyMM"),
189        UnicodeString("yyMM"),
190        UnicodeString("yMMMMMd"),
191        UnicodeString("EEEEEMMMMMd"),
192        UnicodeString("MMMd"),
193        UnicodeString("MMMdhmm"),
194        UnicodeString("EMMMdhmms"),
195        UnicodeString("MMdhmm"),
196        UnicodeString("EEEEMMMdhmms"),
197        UnicodeString("yyyyMMMddhhmmss"),
198        UnicodeString("EyyyyMMMddhhmmss"),
199        UnicodeString("hmm"),
200        UnicodeString("hhmm"),
201        UnicodeString("hhmmVVVV"),
202        UnicodeString(""),
203    };
204    UnicodeString patternResults2[] = {
205        UnicodeString("Oct 14, 1999"),
206        UnicodeString("4th quarter 1999"),
207        UnicodeString("Oct 14, 1999"),
208        UnicodeString("Thu, Oct 14, 1999"),
209        UnicodeString("10/14/1999"),
210        UnicodeString("Oct 1999"),
211        UnicodeString("10/1999"),
212        UnicodeString("10/99"),
213        UnicodeString("O 14, 1999"),
214        UnicodeString("T, O 14"),
215        UnicodeString("Oct 14"),
216        UnicodeString("Oct 14 6:58 AM"),
217        UnicodeString("Thu, Oct 14 6:58:59 AM"),
218        UnicodeString("10/14 6:58 AM"),
219        UnicodeString("Thursday, Oct 14 6:58:59 AM"),
220        UnicodeString("Oct 14, 1999 6:58:59 AM"),
221        UnicodeString("Thu, Oct 14, 1999 6:58:59 AM"),
222        UnicodeString("6:58 AM"),
223        UnicodeString("6:58 AM"),
224        UnicodeString("6:58 AM GMT+00:00"),
225        UnicodeString(""),
226    };
227
228    // results for getSkeletons() and getPatternForSkeleton()
229    const UnicodeString testSkeletonsResults[] = {
230        UnicodeString("HH:mm"),
231        UnicodeString("MMMMd"),
232        UnicodeString("MMMMMd"),
233    };
234
235    const UnicodeString testBaseSkeletonsResults[] = {
236        UnicodeString("Hm"),
237        UnicodeString("MMMd"),
238        UnicodeString("MMMd"),
239    };
240
241    UnicodeString newDecimal(" "); // space
242    UnicodeString newAppendItemName("hrs.");
243    UnicodeString newAppendItemFormat("{1} {0}");
244    UnicodeString newDateTimeFormat("{1} {0}");
245    UErrorCode status = U_ZERO_ERROR;
246    UnicodeString conflictingPattern;
247    UDateTimePatternConflict conflictingStatus;
248
249    // ======= Test CreateInstance with default locale
250    logln("Testing DateTimePatternGenerator createInstance from default locale");
251
252    DateTimePatternGenerator *instFromDefaultLocale=DateTimePatternGenerator::createInstance(status);
253    if (U_FAILURE(status)) {
254        dataerrln("ERROR: Could not create DateTimePatternGenerator (default) - exitting");
255        return;
256    }
257    else {
258        delete instFromDefaultLocale;
259    }
260
261    // ======= Test CreateInstance with given locale
262    logln("Testing DateTimePatternGenerator createInstance from French locale");
263    status = U_ZERO_ERROR;
264    DateTimePatternGenerator *instFromLocale=DateTimePatternGenerator::createInstance(Locale::getFrench(), status);
265    if (U_FAILURE(status)) {
266        dataerrln("ERROR: Could not create DateTimePatternGenerator (Locale::getFrench()) - exitting");
267        return;
268    }
269
270    // ======= Test clone DateTimePatternGenerator
271    logln("Testing DateTimePatternGenerator::clone()");
272    status = U_ZERO_ERROR;
273
274
275    UnicodeString decimalSymbol = instFromLocale->getDecimal();
276    UnicodeString newDecimalSymbol = UnicodeString("*");
277    decimalSymbol = instFromLocale->getDecimal();
278    instFromLocale->setDecimal(newDecimalSymbol);
279    DateTimePatternGenerator *cloneDTPatternGen=instFromLocale->clone();
280    decimalSymbol = cloneDTPatternGen->getDecimal();
281    if (decimalSymbol != newDecimalSymbol) {
282        errln("ERROR: inconsistency is found in cloned object.");
283    }
284    if ( !(*cloneDTPatternGen == *instFromLocale) ) {
285        errln("ERROR: inconsistency is found in cloned object.");
286    }
287
288    if ( *cloneDTPatternGen != *instFromLocale ) {
289        errln("ERROR: inconsistency is found in cloned object.");
290    }
291
292    delete instFromLocale;
293    delete cloneDTPatternGen;
294
295    // ======= Test simple use cases
296    logln("Testing simple use cases");
297    status = U_ZERO_ERROR;
298    Locale deLocale=Locale::getGermany();
299    UDate sampleDate=LocaleTest::date(99, 9, 13, 23, 58, 59);
300    DateTimePatternGenerator *gen = DateTimePatternGenerator::createInstance(deLocale, status);
301    if (U_FAILURE(status)) {
302        dataerrln("ERROR: Could not create DateTimePatternGenerator (Locale::getGermany()) - exitting");
303        return;
304    }
305    UnicodeString findPattern = gen->getBestPattern(UnicodeString("MMMddHmm"), status);
306    SimpleDateFormat *format = new SimpleDateFormat(findPattern, deLocale, status);
307    if (U_FAILURE(status)) {
308        dataerrln("ERROR: Could not create SimpleDateFormat (Locale::getGermany())");
309        delete gen;
310        return;
311    }
312    TimeZone *zone = TimeZone::createTimeZone(UnicodeString("ECT"));
313    if (zone==NULL) {
314        dataerrln("ERROR: Could not create TimeZone ECT");
315        delete gen;
316        delete format;
317        return;
318    }
319    format->setTimeZone(*zone);
320    UnicodeString dateReturned, expectedResult;
321    dateReturned.remove();
322    dateReturned = format->format(sampleDate, dateReturned, status);
323    expectedResult=UnicodeString("14. Okt 08:58", -1, US_INV);
324    if ( dateReturned != expectedResult ) {
325        errln("ERROR: Simple test in getBestPattern with Locale::getGermany()).");
326    }
327    // add new pattern
328    status = U_ZERO_ERROR;
329    conflictingStatus = gen->addPattern(UnicodeString("d'. von' MMMM", -1, US_INV), true, conflictingPattern, status);
330    if (U_FAILURE(status)) {
331        errln("ERROR: Could not addPattern - d\'. von\' MMMM");
332    }
333    status = U_ZERO_ERROR;
334    UnicodeString testPattern=gen->getBestPattern(UnicodeString("MMMMdd"), status);
335    testPattern=gen->getBestPattern(UnicodeString("MMMddHmm"), status);
336    format->applyPattern(gen->getBestPattern(UnicodeString("MMMMdHmm"), status));
337    dateReturned.remove();
338    dateReturned = format->format(sampleDate, dateReturned, status);
339    expectedResult=UnicodeString("14. von Oktober 08:58", -1, US_INV);
340    if ( dateReturned != expectedResult ) {
341        errln(UnicodeString("ERROR: Simple test addPattern failed!: d\'. von\' MMMM   Got: ") + dateReturned + UnicodeString(" Expected: ") + expectedResult);
342    }
343    delete format;
344
345    // get a pattern and modify it
346    format = (SimpleDateFormat *)DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull,
347                                                                  deLocale);
348    format->setTimeZone(*zone);
349    UnicodeString pattern;
350    pattern = format->toPattern(pattern);
351    dateReturned.remove();
352    dateReturned = format->format(sampleDate, dateReturned, status);
353    expectedResult=CharsToUnicodeString("Donnerstag, 14. Oktober 1999 08:58:59 Mitteleurop\\u00E4ische Sommerzeit");
354    if ( dateReturned != expectedResult ) {
355        errln("ERROR: Simple test uses full date format.");
356        errln(UnicodeString(" Got: ") + dateReturned + UnicodeString(" Expected: ") + expectedResult);
357    }
358
359    // modify it to change the zone.
360    UnicodeString newPattern = gen->replaceFieldTypes(pattern, UnicodeString("vvvv"), status);
361    format->applyPattern(newPattern);
362    dateReturned.remove();
363    dateReturned = format->format(sampleDate, dateReturned, status);
364    expectedResult=UnicodeString("Donnerstag, 14. Oktober 1999 08:58:59 (Frankreich)");
365    if ( dateReturned != expectedResult ) {
366        errln("ERROR: Simple test modify the timezone!");
367        errln(UnicodeString(" Got: ")+ dateReturned + UnicodeString(" Expected: ") + expectedResult);
368    }
369
370    // setDeciaml(), getDeciaml()
371    gen->setDecimal(newDecimal);
372    if (newDecimal != gen->getDecimal()) {
373        errln("ERROR: unexpected result from setDecimal() and getDecimal()!.\n");
374    }
375
376    // setAppenItemName() , getAppendItemName()
377    gen->setAppendItemName(UDATPG_HOUR_FIELD, newAppendItemName);
378    if (newAppendItemName != gen->getAppendItemName(UDATPG_HOUR_FIELD)) {
379        errln("ERROR: unexpected result from setAppendItemName() and getAppendItemName()!.\n");
380    }
381
382    // setAppenItemFormat() , getAppendItemFormat()
383    gen->setAppendItemFormat(UDATPG_HOUR_FIELD, newAppendItemFormat);
384    if (newAppendItemFormat != gen->getAppendItemFormat(UDATPG_HOUR_FIELD)) {
385        errln("ERROR: unexpected result from setAppendItemFormat() and getAppendItemFormat()!.\n");
386    }
387
388    // setDateTimeFormat() , getDateTimeFormat()
389    gen->setDateTimeFormat(newDateTimeFormat);
390    if (newDateTimeFormat != gen->getDateTimeFormat()) {
391        errln("ERROR: unexpected result from setDateTimeFormat() and getDateTimeFormat()!.\n");
392    }
393
394    // ======== Test getSkeleton and getBaseSkeleton
395    status = U_ZERO_ERROR;
396    pattern = UnicodeString("dd-MMM");
397    UnicodeString expectedSkeleton = UnicodeString("MMMdd");
398    UnicodeString expectedBaseSkeleton = UnicodeString("MMMd");
399    UnicodeString retSkeleton = gen->getSkeleton(pattern, status);
400    if(U_FAILURE(status) || retSkeleton != expectedSkeleton ) {
401         errln("ERROR: Unexpected result from getSkeleton().\n");
402         errln(UnicodeString(" Got: ") + retSkeleton + UnicodeString(" Expected: ") + expectedSkeleton );
403    }
404    retSkeleton = gen->getBaseSkeleton(pattern, status);
405    if(U_FAILURE(status) || retSkeleton !=  expectedBaseSkeleton) {
406         errln("ERROR: Unexpected result from getBaseSkeleton().\n");
407         errln(UnicodeString(" Got: ") + retSkeleton + UnicodeString(" Expected:")+ expectedBaseSkeleton);
408    }
409
410    pattern = UnicodeString("dd/MMMM/yy");
411    expectedSkeleton = UnicodeString("yyMMMMdd");
412    expectedBaseSkeleton = UnicodeString("yMMMd");
413    retSkeleton = gen->getSkeleton(pattern, status);
414    if(U_FAILURE(status) || retSkeleton != expectedSkeleton ) {
415         errln("ERROR: Unexpected result from getSkeleton().\n");
416         errln(UnicodeString(" Got: ") + retSkeleton + UnicodeString(" Expected: ") + expectedSkeleton );
417    }
418    retSkeleton = gen->getBaseSkeleton(pattern, status);
419    if(U_FAILURE(status) || retSkeleton !=  expectedBaseSkeleton) {
420         errln("ERROR: Unexpected result from getBaseSkeleton().\n");
421         errln(UnicodeString(" Got: ") + retSkeleton + UnicodeString(" Expected:")+ expectedBaseSkeleton);
422    }
423    delete format;
424    delete zone;
425    delete gen;
426
427    {
428        // Trac# 6104
429        status = U_ZERO_ERROR;
430        pattern = UnicodeString("YYYYMMM");
431        UnicodeString expR = CharsToUnicodeString("1999\\u5E741\\u6708"); // fixed expected result per ticket:6626:
432        Locale loc("ja");
433        UDate testDate1= LocaleTest::date(99, 0, 13, 23, 58, 59);
434        DateTimePatternGenerator *patGen=DateTimePatternGenerator::createInstance(loc, status);
435        if(U_FAILURE(status)) {
436            dataerrln("ERROR: Could not create DateTimePatternGenerator");
437            return;
438        }
439        UnicodeString bPattern = patGen->getBestPattern(pattern, status);
440        UnicodeString rDate;
441        SimpleDateFormat sdf(bPattern, loc, status);
442        rDate.remove();
443        rDate = sdf.format(testDate1, rDate);
444
445        logln(UnicodeString(" ja locale with skeleton: YYYYMMM  Best Pattern:") + bPattern);
446        logln(UnicodeString("  Formatted date:") + rDate);
447
448        if ( expR!= rDate ) {
449            errln(UnicodeString("\nERROR: Test Japanese month hack Got: ") + rDate +
450                  UnicodeString(" Expected: ") + expR );
451        }
452
453        delete patGen;
454    }
455    {   // Trac# 6104
456        Locale loc("zh");
457        UnicodeString expR = CharsToUnicodeString("1999\\u5E741\\u6708"); // fixed expected result per ticket:6626:
458        UDate testDate1= LocaleTest::date(99, 0, 13, 23, 58, 59);
459        DateTimePatternGenerator *patGen=DateTimePatternGenerator::createInstance(loc, status);
460        if(U_FAILURE(status)) {
461            dataerrln("ERROR: Could not create DateTimePatternGenerator");
462            return;
463        }
464        UnicodeString bPattern = patGen->getBestPattern(pattern, status);
465        UnicodeString rDate;
466        SimpleDateFormat sdf(bPattern, loc, status);
467        rDate.remove();
468        rDate = sdf.format(testDate1, rDate);
469
470        logln(UnicodeString(" zh locale with skeleton: YYYYMMM  Best Pattern:") + bPattern);
471        logln(UnicodeString("  Formatted date:") + rDate);
472        if ( expR!= rDate ) {
473            errln(UnicodeString("\nERROR: Test Chinese month hack Got: ") + rDate +
474                  UnicodeString(" Expected: ") + expR );
475        }
476        delete patGen;
477    }
478
479    {
480         // Trac# 6172 duplicate time pattern
481         status = U_ZERO_ERROR;
482         pattern = UnicodeString("hmv");
483         UnicodeString expR = UnicodeString("h:mm a v"); // avail formats has hm -> "h:mm a" (fixed expected result per ticket:6626:)
484         Locale loc("en");
485         DateTimePatternGenerator *patGen=DateTimePatternGenerator::createInstance(loc, status);
486         if(U_FAILURE(status)) {
487             dataerrln("ERROR: Could not create DateTimePatternGenerator");
488             return;
489         }
490         UnicodeString bPattern = patGen->getBestPattern(pattern, status);
491         logln(UnicodeString(" en locale with skeleton: hmv  Best Pattern:") + bPattern);
492
493         if ( expR!= bPattern ) {
494             errln(UnicodeString("\nERROR: Test EN time format Got: ") + bPattern +
495                   UnicodeString(" Expected: ") + expR );
496         }
497
498         delete patGen;
499     }
500
501
502    // ======= Test various skeletons.
503    logln("Testing DateTimePatternGenerator with various skeleton");
504
505    status = U_ZERO_ERROR;
506    int32_t localeIndex=0;
507    int32_t resultIndex=0;
508    UnicodeString resultDate;
509    UDate testDate= LocaleTest::date(99, 0, 13, 23, 58, 59);
510    while (localeIndex < MAX_LOCALE )
511    {
512        int32_t dataIndex=0;
513        UnicodeString bestPattern;
514
515        Locale loc(testLocale[localeIndex][0], testLocale[localeIndex][1], testLocale[localeIndex][2], testLocale[localeIndex][3]);
516        logln("\n\n Locale: %s_%s_%s@%s", testLocale[localeIndex][0], testLocale[localeIndex][1], testLocale[localeIndex][2], testLocale[localeIndex][3]);
517        DateTimePatternGenerator *patGen=DateTimePatternGenerator::createInstance(loc, status);
518        if(U_FAILURE(status)) {
519            dataerrln("ERROR: Could not create DateTimePatternGenerator with locale index:%d . - exitting\n", localeIndex);
520            return;
521        }
522        while (patternData[dataIndex].length() > 0) {
523            log(patternData[dataIndex]);
524            bestPattern = patGen->getBestPattern(patternData[dataIndex++], status);
525            logln(UnicodeString(" -> ") + bestPattern);
526
527            SimpleDateFormat sdf(bestPattern, loc, status);
528            resultDate.remove();
529            resultDate = sdf.format(testDate, resultDate);
530            if ( resultDate != patternResults[resultIndex] ) {
531                errln(UnicodeString("\nERROR: Test various skeletons[") + (dataIndex-1) + UnicodeString("], localeIndex ") + localeIndex +
532                      UnicodeString(". Got: ") + resultDate + UnicodeString(" Expected: ") + patternResults[resultIndex] );
533            }
534
535            resultIndex++;
536        }
537        delete patGen;
538        localeIndex++;
539    }
540
541    // ======= More tests ticket#6110
542    logln("Testing DateTimePatternGenerator with various skeleton");
543
544    status = U_ZERO_ERROR;
545    localeIndex=0;
546    resultIndex=0;
547    testDate= LocaleTest::date(99, 9, 13, 23, 58, 59);
548    {
549        int32_t dataIndex=0;
550        UnicodeString bestPattern;
551        logln("\n\n Test various skeletons for English locale...");
552        DateTimePatternGenerator *patGen=DateTimePatternGenerator::createInstance(Locale::getEnglish(), status);
553        if(U_FAILURE(status)) {
554            dataerrln("ERROR: Could not create DateTimePatternGenerator with locale English . - exitting\n");
555            return;
556        }
557        TimeZone *enZone = TimeZone::createTimeZone(UnicodeString("ECT/GMT"));
558        if (enZone==NULL) {
559            dataerrln("ERROR: Could not create TimeZone ECT");
560            delete patGen;
561            return;
562        }
563        SimpleDateFormat *enFormat = (SimpleDateFormat *)DateFormat::createDateTimeInstance(DateFormat::kFull,
564                         DateFormat::kFull, Locale::getEnglish());
565        enFormat->setTimeZone(*enZone);
566        while (patternTests2[dataIndex].length() > 0) {
567            logln(patternTests2[dataIndex]);
568            bestPattern = patGen->getBestPattern(patternTests2[dataIndex], status);
569            logln(UnicodeString(" -> ") + bestPattern);
570            enFormat->applyPattern(bestPattern);
571            resultDate.remove();
572            resultDate = enFormat->format(testDate, resultDate);
573            if ( resultDate != patternResults2[resultIndex] ) {
574                errln(UnicodeString("\nERROR: Test various skeletons[") + dataIndex
575                    + UnicodeString("]. Got: ") + resultDate + UnicodeString(" Expected: ") +
576                    patternResults2[resultIndex] );
577            }
578            dataIndex++;
579            resultIndex++;
580        }
581        delete patGen;
582        delete enZone;
583        delete enFormat;
584    }
585
586
587
588    // ======= Test random skeleton
589    DateTimePatternGenerator *randDTGen= DateTimePatternGenerator::createInstance(status);
590    if (U_FAILURE(status)) {
591        dataerrln("ERROR: Could not create DateTimePatternGenerator (Locale::getFrench()) - exitting");
592        return;
593    }
594    UChar newChar;
595    int32_t i;
596    for (i=0; i<10; ++i) {
597        UnicodeString randomSkeleton;
598        int32_t len = rand() % 20;
599        for (int32_t j=0; j<len; ++j ) {
600            while ((newChar = (UChar)(rand()%0x7f))>=(UChar)0x20) {
601                randomSkeleton += newChar;
602            }
603        }
604        UnicodeString bestPattern = randDTGen->getBestPattern(randomSkeleton, status);
605    }
606    delete randDTGen;
607
608    // UnicodeString randomString=Unicode
609    // ======= Test getStaticClassID()
610
611    logln("Testing getStaticClassID()");
612    status = U_ZERO_ERROR;
613    DateTimePatternGenerator *test= DateTimePatternGenerator::createInstance(status);
614
615    if(test->getDynamicClassID() != DateTimePatternGenerator::getStaticClassID()) {
616        errln("ERROR: getDynamicClassID() didn't return the expected value");
617    }
618    delete test;
619
620    // ====== Test createEmptyInstance()
621
622    logln("Testing createEmptyInstance()");
623    status = U_ZERO_ERROR;
624
625    test = DateTimePatternGenerator::createEmptyInstance(status);
626    if(U_FAILURE(status)) {
627         errln("ERROR: Fail to create an empty instance ! - exitting.\n");
628         delete test;
629         return;
630    }
631
632    conflictingStatus = test->addPattern(UnicodeString("MMMMd"), true, conflictingPattern, status);
633    status = U_ZERO_ERROR;
634    testPattern=test->getBestPattern(UnicodeString("MMMMdd"), status);
635    conflictingStatus = test->addPattern(UnicodeString("HH:mm"), true, conflictingPattern, status);
636    conflictingStatus = test->addPattern(UnicodeString("MMMMMd"), true, conflictingPattern, status); //duplicate pattern
637    StringEnumeration *output=NULL;
638    output = test->getRedundants(status);
639    expectedResult=UnicodeString("MMMMd");
640    if (output != NULL) {
641        output->reset(status);
642        const UnicodeString *dupPattern=output->snext(status);
643        if ( (dupPattern==NULL) || (*dupPattern != expectedResult) ) {
644            errln("ERROR: Fail in getRedundants !\n");
645        }
646    }
647
648    // ======== Test getSkeletons and getBaseSkeletons
649    StringEnumeration* ptrSkeletonEnum = test->getSkeletons(status);
650    if(U_FAILURE(status)) {
651        errln("ERROR: Fail to get skeletons !\n");
652    }
653    UnicodeString returnPattern, *ptrSkeleton;
654    ptrSkeletonEnum->reset(status);
655    int32_t count=ptrSkeletonEnum->count(status);
656    for (i=0; i<count; ++i) {
657        ptrSkeleton = (UnicodeString *)ptrSkeletonEnum->snext(status);
658        returnPattern = test->getPatternForSkeleton(*ptrSkeleton);
659        if ( returnPattern != testSkeletonsResults[i] ) {
660            errln(UnicodeString("ERROR: Unexpected result from getSkeletons and getPatternForSkeleton\nGot: ") + returnPattern
661               + UnicodeString("\nExpected: ") + testSkeletonsResults[i]
662               + UnicodeString("\n"));
663        }
664    }
665    StringEnumeration* ptrBaseSkeletonEnum = test->getBaseSkeletons(status);
666    if(U_FAILURE(status)) {
667        errln("ERROR: Fail to get base skeletons !\n");
668    }
669    count=ptrBaseSkeletonEnum->count(status);
670    for (i=0; i<count; ++i) {
671        ptrSkeleton = (UnicodeString *)ptrBaseSkeletonEnum->snext(status);
672        if ( *ptrSkeleton != testBaseSkeletonsResults[i] ) {
673            errln("ERROR: Unexpected result from getBaseSkeletons() !\n");
674        }
675    }
676
677    // ========= DateTimePatternGenerator sample code in Userguide
678    // set up the generator
679    Locale locale = Locale::getFrench();
680    status = U_ZERO_ERROR;
681    DateTimePatternGenerator *generator = DateTimePatternGenerator::createInstance( locale, status);
682
683    // get a pattern for an abbreviated month and day
684    pattern = generator->getBestPattern(UnicodeString("MMMd"), status);
685    SimpleDateFormat formatter(pattern, locale, status);
686
687    zone = TimeZone::createTimeZone(UnicodeString("GMT"));
688    formatter.setTimeZone(*zone);
689    // use it to format (or parse)
690    UnicodeString formatted;
691    formatted = formatter.format(Calendar::getNow(), formatted, status);
692    // for French, the result is "13 sept."
693    formatted.remove();
694    // cannot use the result from getNow() because the value change evreyday.
695    testDate= LocaleTest::date(99, 0, 13, 23, 58, 59);
696    formatted = formatter.format(testDate, formatted, status);
697    expectedResult=UnicodeString("14 janv.");
698    if ( formatted != expectedResult ) {
699        errln("ERROR: Userguide sample code result!");
700        errln(UnicodeString(" Got: ")+ formatted + UnicodeString(" Expected: ") + expectedResult);
701    }
702
703    delete zone;
704    delete output;
705    delete ptrSkeletonEnum;
706    delete ptrBaseSkeletonEnum;
707    delete test;
708    delete generator;
709}
710
711/**
712 * Test handling of options
713 *
714 * For reference, as of ICU 4.3.3,
715 *  root/gregorian has
716 *      Hm{"H:mm"}
717 *      Hms{"H:mm:ss"}
718 *      hm{"h:mm a"}
719 *      hms{"h:mm:ss a"}
720 *  en/gregorian has
721 *      Hm{"H:mm"}
722 *      Hms{"H:mm:ss"}
723 *      hm{"h:mm a"}
724 *  be/gregorian has
725 *      HHmmss{"HH.mm.ss"}
726 *      Hm{"HH.mm"}
727 *      hm{"h.mm a"}
728 *      hms{"h.mm.ss a"}
729 */
730typedef struct DTPtnGenOptionsData {
731    const char *locale;
732    const char *skel;
733    const char *expectedPattern;
734    UDateTimePatternMatchOptions    options;
735} DTPtnGenOptionsData;
736void IntlTestDateTimePatternGeneratorAPI::testOptions(/*char *par*/)
737{
738    DTPtnGenOptionsData testData[] = {
739    //   locale  skel   expectedPattern     options
740        { "en", "Hmm",  "HH:mm",   UDATPG_MATCH_NO_OPTIONS        },
741        { "en", "HHmm", "HH:mm",   UDATPG_MATCH_NO_OPTIONS        },
742        { "en", "hhmm", "h:mm a",  UDATPG_MATCH_NO_OPTIONS        },
743        { "en", "Hmm",  "HH:mm",   UDATPG_MATCH_HOUR_FIELD_LENGTH },
744        { "en", "HHmm", "HH:mm",   UDATPG_MATCH_HOUR_FIELD_LENGTH },
745        { "en", "hhmm", "hh:mm a", UDATPG_MATCH_HOUR_FIELD_LENGTH },
746        { "be", "Hmm",  "HH.mm",   UDATPG_MATCH_NO_OPTIONS        },
747        { "be", "HHmm", "HH.mm",   UDATPG_MATCH_NO_OPTIONS        },
748        { "be", "hhmm", "h.mm a",  UDATPG_MATCH_NO_OPTIONS        },
749        { "be", "Hmm",  "H.mm",    UDATPG_MATCH_HOUR_FIELD_LENGTH },
750        { "be", "HHmm", "HH.mm",   UDATPG_MATCH_HOUR_FIELD_LENGTH },
751        { "be", "hhmm", "hh.mm a", UDATPG_MATCH_HOUR_FIELD_LENGTH },
752    };
753
754    int count = sizeof(testData) / sizeof(testData[0]);
755    const DTPtnGenOptionsData * testDataPtr = testData;
756
757    for (; count-- > 0; ++testDataPtr) {
758        UErrorCode status = U_ZERO_ERROR;
759
760        Locale locale(testDataPtr->locale);
761        UnicodeString skel(testDataPtr->skel);
762        UnicodeString expectedPattern(testDataPtr->expectedPattern);
763        UDateTimePatternMatchOptions options = testDataPtr->options;
764
765        DateTimePatternGenerator * dtpgen = DateTimePatternGenerator::createInstance(locale, status);
766        if (U_FAILURE(status)) {
767            dataerrln("Unable to create DateTimePatternGenerator instance for locale(%s): %s", locale.getName(), u_errorName(status));
768            delete dtpgen;
769            continue;
770        }
771        UnicodeString pattern = dtpgen->getBestPattern(skel, options, status);
772        if (pattern.compare(expectedPattern) != 0) {
773            errln( UnicodeString("ERROR in getBestPattern, locale ") + UnicodeString(testDataPtr->locale) +
774                   UnicodeString(", skeleton ") + skel +
775                   ((options)?UnicodeString(", options!=0"):UnicodeString(", options==0")) +
776                   UnicodeString(", expected pattern ") + expectedPattern +
777                   UnicodeString(", got ") + pattern );
778        }
779        delete dtpgen;
780    }
781}
782
783#endif /* #if !UCONFIG_NO_FORMATTING */
784