• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
4  * COPYRIGHT:
5  * Copyright (c) 1997-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 
14 //TODO: define it in compiler flag
15 //#define DTIFMTTS_DEBUG 1
16 
17 
18 #ifdef DTIFMTTS_DEBUG
19 #include <iostream>
20 #endif
21 
22 #include "dtifmtts.h"
23 
24 #include "cmemory.h"
25 #include "cstr.h"
26 #include "cstring.h"
27 #include "simplethread.h"
28 #include "japancal.h"
29 #include "unicode/gregocal.h"
30 #include "unicode/dtintrv.h"
31 #include "unicode/dtitvinf.h"
32 #include "unicode/dtitvfmt.h"
33 #include "unicode/localpointer.h"
34 #include "unicode/timezone.h"
35 
36 
37 
38 #ifdef DTIFMTTS_DEBUG
39 //#define PRINTMESG(msg) { std::cout << "(" << __FILE__ << ":" << __LINE__ << ") " << msg << "\n"; }
40 #define PRINTMESG(msg) { std::cout << msg; }
41 #endif
42 
43 #include <stdio.h>
44 
45 
runIndexedTest(int32_t index,UBool exec,const char * & name,char *)46 void DateIntervalFormatTest::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ ) {
47     if (exec) logln("TestSuite DateIntervalFormat");
48     switch (index) {
49         TESTCASE(0, testAPI);
50         TESTCASE(1, testFormat);
51         TESTCASE(2, testFormatUserDII);
52         TESTCASE(3, testSetIntervalPatternNoSideEffect);
53         TESTCASE(4, testYearFormats);
54         TESTCASE(5, testStress);
55         TESTCASE(6, testTicket11583_2);
56         TESTCASE(7, testTicket11985);
57         TESTCASE(8, testTicket11669);
58         TESTCASE(9, testTicket12065);
59         TESTCASE(10, testFormattedDateInterval);
60         TESTCASE(11, testCreateInstanceForAllLocales);
61         TESTCASE(12, testTicket20707);
62         TESTCASE(13, testFormatMillisecond);
63         default: name = ""; break;
64     }
65 }
66 
67 /**
68  * Test various generic API methods of DateIntervalFormat for API coverage.
69  */
testAPI()70 void DateIntervalFormatTest::testAPI() {
71 
72     /* ====== Test create interval instance with default locale and skeleton
73      */
74     UErrorCode status = U_ZERO_ERROR;
75     logln("Testing DateIntervalFormat create instance with default locale and skeleton");
76 
77     DateIntervalFormat* dtitvfmt = DateIntervalFormat::createInstance(UDAT_YEAR_MONTH_DAY, status);
78     if(U_FAILURE(status)) {
79         dataerrln("ERROR: Could not create DateIntervalFormat (skeleton + default locale) - exitting");
80         return;
81     } else {
82         delete dtitvfmt;
83     }
84 
85 
86     /* ====== Test create interval instance with given locale and skeleton
87      */
88     status = U_ZERO_ERROR;
89     logln("Testing DateIntervalFormat create instance with given locale and skeleton");
90 
91     dtitvfmt = DateIntervalFormat::createInstance(UDAT_YEAR_MONTH_DAY, Locale::getJapanese(), status);
92     if(U_FAILURE(status)) {
93         dataerrln("ERROR: Could not create DateIntervalFormat (skeleton + locale) - exitting");
94         return;
95     } else {
96         delete dtitvfmt;
97     }
98 
99 
100     /* ====== Test create interval instance with dateIntervalInfo and skeleton
101      */
102     status = U_ZERO_ERROR;
103     logln("Testing DateIntervalFormat create instance with dateIntervalInfo  and skeleton");
104 
105     DateIntervalInfo* dtitvinf = new DateIntervalInfo(Locale::getSimplifiedChinese(), status);
106 
107     dtitvfmt = DateIntervalFormat::createInstance("EEEdMMMyhms", *dtitvinf, status);
108     delete dtitvinf;
109 
110     if(U_FAILURE(status)) {
111         dataerrln("ERROR: Could not create DateIntervalFormat (skeleton + DateIntervalInfo + default locale) - exitting");
112         return;
113     } else {
114         delete dtitvfmt;
115     }
116 
117 
118     /* ====== Test create interval instance with dateIntervalInfo and skeleton
119      */
120     status = U_ZERO_ERROR;
121     logln("Testing DateIntervalFormat create instance with dateIntervalInfo  and skeleton");
122 
123     dtitvinf = new DateIntervalInfo(Locale::getSimplifiedChinese(), status);
124 
125     dtitvfmt = DateIntervalFormat::createInstance("EEEdMMMyhms", Locale::getSimplifiedChinese(), *dtitvinf, status);
126     delete dtitvinf;
127     if(U_FAILURE(status)) {
128         dataerrln("ERROR: Could not create DateIntervalFormat (skeleton + DateIntervalInfo + locale) - exitting");
129         return;
130     }
131     // not deleted, test clone
132 
133 
134     // ====== Test clone()
135     status = U_ZERO_ERROR;
136     logln("Testing DateIntervalFormat clone");
137 
138     DateIntervalFormat* another = dtitvfmt->clone();
139     if ( (*another) != (*dtitvfmt) ) {
140         dataerrln("%s:%d ERROR: clone failed", __FILE__, __LINE__);
141     }
142 
143 
144     // ====== Test getDateIntervalInfo, setDateIntervalInfo, adoptDateIntervalInfo
145     status = U_ZERO_ERROR;
146     logln("Testing DateIntervalFormat getDateIntervalInfo");
147     const DateIntervalInfo* inf = another->getDateIntervalInfo();
148     dtitvfmt->setDateIntervalInfo(*inf, status);
149     const DateIntervalInfo* anotherInf = dtitvfmt->getDateIntervalInfo();
150     if ( (*inf) != (*anotherInf) || U_FAILURE(status) ) {
151         dataerrln("ERROR: getDateIntervalInfo/setDateIntervalInfo failed");
152     }
153 
154     {
155         // We make sure that setDateIntervalInfo does not corrupt the cache. See ticket 9919.
156         status = U_ZERO_ERROR;
157         logln("Testing DateIntervalFormat setDateIntervalInfo");
158         const Locale &enLocale = Locale::getEnglish();
159         LocalPointer<DateIntervalFormat> dif(DateIntervalFormat::createInstance("yMd", enLocale, status));
160         if (U_FAILURE(status)) {
161             errln("Failure encountered: %s", u_errorName(status));
162             return;
163         }
164         UnicodeString expected;
165         LocalPointer<Calendar> fromTime(Calendar::createInstance(enLocale, status));
166         LocalPointer<Calendar> toTime(Calendar::createInstance(enLocale, status));
167         if (U_FAILURE(status)) {
168             errln("Failure encountered: %s", u_errorName(status));
169             return;
170         }
171         FieldPosition pos(FieldPosition::DONT_CARE);
172         fromTime->set(2013, 3, 26);
173         toTime->set(2013, 3, 28);
174         dif->format(*fromTime, *toTime, expected, pos, status);
175         if (U_FAILURE(status)) {
176             errln("Failure encountered: %s", u_errorName(status));
177             return;
178         }
179         LocalPointer<DateIntervalInfo> dii(new DateIntervalInfo(Locale::getEnglish(), status), status);
180         if (U_FAILURE(status)) {
181             errln("Failure encountered: %s", u_errorName(status));
182             return;
183         }
184         dii->setIntervalPattern(ctou("yMd"), UCAL_DATE, ctou("M/d/y \\u2013 d"), status);
185         dif->setDateIntervalInfo(*dii, status);
186         if (U_FAILURE(status)) {
187             errln("Failure encountered: %s", u_errorName(status));
188             return;
189         }
190         dif.adoptInstead(DateIntervalFormat::createInstance("yMd", enLocale, status));
191         if (U_FAILURE(status)) {
192             errln("Failure encountered: %s", u_errorName(status));
193             return;
194         }
195         UnicodeString actual;
196         pos = 0;
197         dif->format(*fromTime, *toTime, actual, pos, status);
198         if (U_FAILURE(status)) {
199             errln("Failure encountered: %s", u_errorName(status));
200             return;
201         }
202         if (expected != actual) {
203             errln("DateIntervalFormat.setIntervalInfo should have no side effects.");
204         }
205     }
206 
207     /*
208     status = U_ZERO_ERROR;
209     DateIntervalInfo* nonConstInf = inf->clone();
210     dtitvfmt->adoptDateIntervalInfo(nonConstInf, status);
211     anotherInf = dtitvfmt->getDateIntervalInfo();
212     if ( (*inf) != (*anotherInf) || U_FAILURE(status) ) {
213         dataerrln("ERROR: adoptDateIntervalInfo failed");
214     }
215     */
216 
217     // ====== Test getDateFormat, setDateFormat, adoptDateFormat
218 
219     status = U_ZERO_ERROR;
220     logln("Testing DateIntervalFormat getDateFormat");
221     /*
222     const DateFormat* fmt = another->getDateFormat();
223     dtitvfmt->setDateFormat(*fmt, status);
224     const DateFormat* anotherFmt = dtitvfmt->getDateFormat();
225     if ( (*fmt) != (*anotherFmt) || U_FAILURE(status) ) {
226         dataerrln("ERROR: getDateFormat/setDateFormat failed");
227     }
228 
229     status = U_ZERO_ERROR;
230     DateFormat* nonConstFmt = fmt->clone();
231     dtitvfmt->adoptDateFormat(nonConstFmt, status);
232     anotherFmt = dtitvfmt->getDateFormat();
233     if ( (*fmt) != (*anotherFmt) || U_FAILURE(status) ) {
234         dataerrln("ERROR: adoptDateFormat failed");
235     }
236     delete fmt;
237     */
238 
239 
240     // ======= Test getStaticClassID()
241 
242     logln("Testing getStaticClassID()");
243 
244 
245     if(dtitvfmt->getDynamicClassID() != DateIntervalFormat::getStaticClassID()) {
246         errln("ERROR: getDynamicClassID() didn't return the expected value");
247     }
248 
249     delete another;
250 
251     // ====== test constructor/copy constructor and assignment
252     /* they are protected, no test
253     logln("Testing DateIntervalFormat constructor and assigment operator");
254     status = U_ZERO_ERROR;
255 
256     DateFormat* constFmt = dtitvfmt->getDateFormat()->clone();
257     inf = dtitvfmt->getDateIntervalInfo()->clone();
258 
259 
260     DateIntervalFormat* dtifmt = new DateIntervalFormat(fmt, inf, status);
261     if(U_FAILURE(status)) {
262         dataerrln("ERROR: Could not create DateIntervalFormat (default) - exitting");
263         return;
264     }
265 
266     DateIntervalFormat* dtifmt2 = new(dtifmt);
267     if ( (*dtifmt) != (*dtifmt2) ) {
268         dataerrln("ERROR: Could not create DateIntervalFormat (default) - exitting");
269         return;
270     }
271 
272     DateIntervalFormat dtifmt3 = (*dtifmt);
273     if ( (*dtifmt) != dtifmt3 ) {
274         dataerrln("ERROR: Could not create DateIntervalFormat (default) - exitting");
275         return;
276     }
277 
278     delete dtifmt2;
279     delete dtifmt3;
280     delete dtifmt;
281     */
282 
283 
284     //===== test format and parse ==================
285     Formattable formattable;
286     formattable.setInt64(10);
287     UnicodeString res;
288     FieldPosition pos(FieldPosition::DONT_CARE);
289     status = U_ZERO_ERROR;
290     dtitvfmt->format(formattable, res, pos, status);
291     if ( status != U_ILLEGAL_ARGUMENT_ERROR ) {
292         dataerrln("ERROR: format non-date-interval object should set U_ILLEGAL_ARGUMENT_ERROR - exitting");
293         return;
294     }
295 
296     DateInterval* dtitv = new DateInterval(3600*24*365, 3600*24*366);
297     formattable.adoptObject(dtitv);
298     res.remove();
299     pos = 0;
300     status = U_ZERO_ERROR;
301     dtitvfmt->format(formattable, res, pos, status);
302     if ( U_FAILURE(status) ) {
303         dataerrln("ERROR: format date interval failed - exitting");
304         return;
305     }
306 
307     const DateFormat* dfmt = dtitvfmt->getDateFormat();
308     Calendar* fromCal = dfmt->getCalendar()->clone();
309     Calendar* toCal = dfmt->getCalendar()->clone();
310     res.remove();
311     pos = 0;
312     status = U_ZERO_ERROR;
313     dtitvfmt->format(*fromCal, *toCal, res, pos, status);
314     if ( U_FAILURE(status) ) {
315         dataerrln("ERROR: format date interval failed - exitting");
316         return;
317     }
318     delete fromCal;
319     delete toCal;
320 
321 
322     Formattable fmttable;
323     status = U_ZERO_ERROR;
324     // TODO: why do I need cast?
325     ((Format*)dtitvfmt)->parseObject(res, fmttable, status);
326     if ( status != U_INVALID_FORMAT_ERROR ) {
327         dataerrln("ERROR: parse should set U_INVALID_FORMAT_ERROR - exitting");
328         return;
329     }
330 
331     delete dtitvfmt;
332 
333     //====== test setting time zone
334     logln("Testing DateIntervalFormat set & format with different time zones, get time zone");
335     status = U_ZERO_ERROR;
336     dtitvfmt = DateIntervalFormat::createInstance("MMMdHHmm", Locale::getEnglish(), status);
337     if ( U_SUCCESS(status) ) {
338         UDate date1 = 1299090600000.0; // 2011-Mar-02 1030 in US/Pacific, 2011-Mar-03 0330 in Asia/Tokyo
339         UDate date2 = 1299115800000.0; // 2011-Mar-02 1730 in US/Pacific, 2011-Mar-03 1030 in Asia/Tokyo
340 
341         DateInterval * dtitv12 = new DateInterval(date1, date2);
342         TimeZone * tzCalif = TimeZone::createTimeZone("US/Pacific");
343         TimeZone * tzTokyo = TimeZone::createTimeZone("Asia/Tokyo");
344         UnicodeString fmtCalif = UnicodeString(ctou("Mar 2, 10:30 \\u2013 17:30"));
345         UnicodeString fmtTokyo = UnicodeString(ctou("Mar 3, 03:30 \\u2013 10:30"));
346 
347         dtitvfmt->adoptTimeZone(tzCalif);
348         res.remove();
349         pos = 0;
350         status = U_ZERO_ERROR;
351         dtitvfmt->format(dtitv12, res, pos, status);
352         if ( U_SUCCESS(status) ) {
353             if ( res.compare(fmtCalif) != 0 ) {
354                 errln("ERROR: DateIntervalFormat::format for tzCalif, expect " + fmtCalif + ", get " + res);
355             }
356         } else {
357             errln("ERROR: DateIntervalFormat::format for tzCalif, status %s", u_errorName(status));
358         }
359 
360         dtitvfmt->setTimeZone(*tzTokyo);
361         res.remove();
362         pos = 0;
363         status = U_ZERO_ERROR;
364         dtitvfmt->format(dtitv12, res, pos, status);
365         if ( U_SUCCESS(status) ) {
366             if ( res.compare(fmtTokyo) != 0 ) {
367                 errln("ERROR: DateIntervalFormat::format for fmtTokyo, expect " + fmtTokyo + ", get " + res);
368             }
369         } else {
370             errln("ERROR: DateIntervalFormat::format for tzTokyo, status %s", u_errorName(status));
371         }
372 
373         if ( dtitvfmt->getTimeZone() != *tzTokyo ) {
374             errln("ERROR: DateIntervalFormat::getTimeZone returns mismatch.");
375         }
376 
377         delete tzTokyo; // tzCalif was owned by dtitvfmt which should have deleted it
378         delete dtitv12;
379         delete dtitvfmt;
380     } else {
381         errln("ERROR: DateIntervalFormat::createInstance(\"MdHH\", Locale::getEnglish(), ...), status %s", u_errorName(status));
382     }
383     //====== test format  in testFormat()
384 
385     //====== test DateInterval class (better coverage)
386     DateInterval dtitv1(3600*24*365, 3600*24*366);
387     DateInterval dtitv2(dtitv1);
388 
389     if (!(dtitv1 == dtitv2)) {
390         errln("ERROR: Copy constructor failed for DateInterval.");
391     }
392 
393     DateInterval dtitv3(3600*365, 3600*366);
394     dtitv3 = dtitv1;
395     if (!(dtitv3 == dtitv1)) {
396         errln("ERROR: Equal operator failed for DateInterval.");
397     }
398 
399     DateInterval *dtitv4 = dtitv1.clone();
400     if (*dtitv4 != dtitv1) {
401         errln("ERROR: Equal operator failed for DateInterval.");
402     }
403     delete dtitv4;
404 }
405 
406 
407 /**
408  * Test format
409  */
testFormat()410 void DateIntervalFormatTest::testFormat() {
411     // first item is date pattern
412     // followed by a group of locale/from_data/to_data/skeleton/interval_data
413     // Note that from_data/to_data are specified using era names from root, for the calendar specified by locale.
414     const char* DATA[] = {
415         "GGGGG y MM dd HH:mm:ss", // pattern for from_data/to_data
416         // test root
417         "root", "CE 2007 11 10 10:10:10", "CE 2007 12 10 10:10:10", "yM", "2007-11 \\u2013 2007-12",
418 
419         // test 'H' and 'h', using availableFormat in fallback
420         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 10 15:10:10", "Hms", "10:10:10 \\u2013 15:10:10",
421         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 10 15:10:10", "hms", "10:10:10 AM \\u2013 3:10:10 PM",
422 
423         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "MMMM", "October 2007 \\u2013 October 2008",
424         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "MMM", "Oct 2007 \\u2013 Oct 2008",
425         // test skeleton with both date and time
426         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dMMMyhm", "Nov 10, 2007, 10:10 AM \\u2013 Nov 20, 2007, 10:10 AM",
427 
428         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 10 11:10:10", "dMMMyhm", "Nov 10, 2007, 10:10 \\u2013 11:10 AM",
429 
430         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 10 11:10:10", "hms", "10:10:10 AM \\u2013 11:10:10 AM",
431         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 10 11:10:10", "Hms", "10:10:10 \\u2013 11:10:10",
432         "en", "CE 2007 11 10 20:10:10", "CE 2007 11 10 21:10:10", "Hms", "20:10:10 \\u2013 21:10:10",
433 
434         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EEEEdMMMMy", "Wednesday, October 10, 2007 \\u2013 Friday, October 10, 2008",
435 
436         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "dMMMMy", "October 10, 2007 \\u2013 October 10, 2008",
437 
438         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "dMMMM", "October 10, 2007 \\u2013 October 10, 2008",
439 
440         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "MMMMy", "October 2007 \\u2013 October 2008",
441 
442         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EEEEdMMMM", "Wednesday, October 10, 2007 \\u2013 Friday, October 10, 2008",
443 
444         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EdMMMy", "Wed, Oct 10, 2007 \\u2013 Fri, Oct 10, 2008",
445 
446         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "dMMMy", "Oct 10, 2007 \\u2013 Oct 10, 2008",
447 
448         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "dMMM", "Oct 10, 2007 \\u2013 Oct 10, 2008",
449 
450         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "MMMy", "Oct 2007 \\u2013 Oct 2008",
451 
452         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EdMMM", "Wed, Oct 10, 2007 \\u2013 Fri, Oct 10, 2008",
453 
454         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EdMy", "Wed, 10/10/2007 \\u2013 Fri, 10/10/2008",
455 
456         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "dMy", "10/10/2007 \\u2013 10/10/2008",
457 
458         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "dM", "10/10/2007 \\u2013 10/10/2008",
459 
460         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "My", "10/2007 \\u2013 10/2008",
461 
462         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EdM", "Wed, 10/10/2007 \\u2013 Fri, 10/10/2008",
463 
464         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "d", "10/10/2007 \\u2013 10/10/2008",
465 
466         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "Ed", "10 Wed \\u2013 10 Fri",
467 
468         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "y", "2007 \\u2013 2008",
469 
470         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "M", "10/2007 \\u2013 10/2008",
471 
472 
473 
474         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "hm", "10/10/2007, 10:10 AM \\u2013 10/10/2008, 10:10 AM",
475         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "Hm", "10/10/2007, 10:10 \\u2013 10/10/2008, 10:10",
476         "en", "CE 2007 10 10 20:10:10", "CE 2008 10 10 20:10:10", "Hm", "10/10/2007, 20:10 \\u2013 10/10/2008, 20:10",
477 
478         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "hmv", "10/10/2007, 10:10 AM PT \\u2013 10/10/2008, 10:10 AM PT",
479 
480         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "hmz", "10/10/2007, 10:10 AM PDT \\u2013 10/10/2008, 10:10 AM PDT",
481 
482         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "h", "10/10/2007, 10 AM \\u2013 10/10/2008, 10 AM",
483 
484         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "hv", "10/10/2007, 10 AM PT \\u2013 10/10/2008, 10 AM PT",
485 
486         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "hz", "10/10/2007, 10 AM PDT \\u2013 10/10/2008, 10 AM PDT",
487 
488         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EEddMMyyyy", "Wed, 10/10/2007 \\u2013 Fri, 10/10/2008",
489 
490         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EddMMy", "Wed, 10/10/2007 \\u2013 Fri, 10/10/2008",
491 
492         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "hhmm", "10/10/2007, 10:10 AM \\u2013 10/10/2008, 10:10 AM",
493 
494         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "hhmmzz", "10/10/2007, 10:10 AM PDT \\u2013 10/10/2008, 10:10 AM PDT",
495 
496         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "hms", "10/10/2007, 10:10:10 AM \\u2013 10/10/2008, 10:10:10 AM",
497 
498         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "dMMMMMy", "O 10, 2007 \\u2013 O 10, 2008",
499 
500         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EEEEEdM", "W, 10/10/2007 \\u2013 F, 10/10/2008",
501 
502         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EEEEdMMMMy", "Wednesday, October 10 \\u2013 Saturday, November 10, 2007",
503 
504         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "dMMMMy", "October 10 \\u2013 November 10, 2007",
505 
506         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "dMMMM", "October 10 \\u2013 November 10",
507 
508         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "MMMMy", "October \\u2013 November 2007",
509 
510         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EEEEdMMMM", "Wednesday, October 10 \\u2013 Saturday, November 10",
511 
512         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EdMMMy", "Wed, Oct 10 \\u2013 Sat, Nov 10, 2007",
513 
514         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "dMMMy", "Oct 10 \\u2013 Nov 10, 2007",
515 
516         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "dMMM", "Oct 10 \\u2013 Nov 10",
517 
518         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "MMMy", "Oct \\u2013 Nov 2007",
519 
520         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EdMMM", "Wed, Oct 10 \\u2013 Sat, Nov 10",
521 
522         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EdMy", "Wed, 10/10/2007 \\u2013 Sat, 11/10/2007",
523 
524         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "dMy", "10/10/2007 \\u2013 11/10/2007",
525 
526 
527         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "My", "10/2007 \\u2013 11/2007",
528 
529         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EdM", "Wed, 10/10 \\u2013 Sat, 11/10",
530 
531         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "d", "10/10 \\u2013 11/10",
532 
533         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "Ed", "10 Wed \\u2013 10 Sat",
534 
535         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "y", "2007",
536 
537         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "M", "10 \\u2013 11",
538 
539         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "MMM", "Oct \\u2013 Nov",
540 
541         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "MMMM", "October \\u2013 November",
542 
543         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "hm", "10/10/2007, 10:10 AM \\u2013 11/10/2007, 10:10 AM",
544         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "Hm", "10/10/2007, 10:10 \\u2013 11/10/2007, 10:10",
545         "en", "CE 2007 10 10 20:10:10", "CE 2007 11 10 20:10:10", "Hm", "10/10/2007, 20:10 \\u2013 11/10/2007, 20:10",
546 
547         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "hmv", "10/10/2007, 10:10 AM PT \\u2013 11/10/2007, 10:10 AM PT",
548 
549         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "hmz", "10/10/2007, 10:10 AM PDT \\u2013 11/10/2007, 10:10 AM PST",
550 
551         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "h", "10/10/2007, 10 AM \\u2013 11/10/2007, 10 AM",
552 
553         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "hv", "10/10/2007, 10 AM PT \\u2013 11/10/2007, 10 AM PT",
554 
555         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "hz", "10/10/2007, 10 AM PDT \\u2013 11/10/2007, 10 AM PST",
556 
557         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EEddMMyyyy", "Wed, 10/10/2007 \\u2013 Sat, 11/10/2007",
558 
559         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EddMMy", "Wed, 10/10/2007 \\u2013 Sat, 11/10/2007",
560 
561 
562         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "hhmmzz", "10/10/2007, 10:10 AM PDT \\u2013 11/10/2007, 10:10 AM PST",
563 
564         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "hms", "10/10/2007, 10:10:10 AM \\u2013 11/10/2007, 10:10:10 AM",
565 
566         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "dMMMMMy", "O 10 \\u2013 N 10, 2007",
567 
568         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EEEEEdM", "W, 10/10 \\u2013 S, 11/10",
569 
570         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EEEEdMMMMy", "Saturday, November 10 \\u2013 Tuesday, November 20, 2007",
571 
572         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dMMMMy", "November 10 \\u2013 20, 2007",
573 
574         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dMMMM", "November 10 \\u2013 20",
575 
576 
577         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EEEEdMMMM", "Saturday, November 10 \\u2013 Tuesday, November 20",
578 
579         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EdMMMy", "Sat, Nov 10 \\u2013 Tue, Nov 20, 2007",
580 
581         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dMMMy", "Nov 10 \\u2013 20, 2007",
582 
583         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dMMM", "Nov 10 \\u2013 20",
584 
585         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "MMMy", "Nov 2007",
586 
587         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EdMMM", "Sat, Nov 10 \\u2013 Tue, Nov 20",
588 
589         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EdMy", "Sat, 11/10/2007 \\u2013 Tue, 11/20/2007",
590 
591         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dMy", "11/10/2007 \\u2013 11/20/2007",
592 
593         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dM", "11/10 \\u2013 11/20",
594 
595         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "My", "11/2007",
596 
597         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EdM", "Sat, 11/10 \\u2013 Tue, 11/20",
598 
599         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "d", "10 \\u2013 20",
600 
601         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "Ed", "10 Sat \\u2013 20 Tue",
602 
603         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "y", "2007",
604 
605         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "M", "11",
606 
607         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "MMM", "Nov",
608 
609         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "MMMM", "November",
610 
611         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "hm", "11/10/2007, 10:10 AM \\u2013 11/20/2007, 10:10 AM",
612         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "Hm", "11/10/2007, 10:10 \\u2013 11/20/2007, 10:10",
613         "en", "CE 2007 11 10 20:10:10", "CE 2007 11 20 20:10:10", "Hm", "11/10/2007, 20:10 \\u2013 11/20/2007, 20:10",
614 
615         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "hmv", "11/10/2007, 10:10 AM PT \\u2013 11/20/2007, 10:10 AM PT",
616 
617         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "hmz", "11/10/2007, 10:10 AM PST \\u2013 11/20/2007, 10:10 AM PST",
618 
619         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "h", "11/10/2007, 10 AM \\u2013 11/20/2007, 10 AM",
620 
621         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "hv", "11/10/2007, 10 AM PT \\u2013 11/20/2007, 10 AM PT",
622 
623         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "hz", "11/10/2007, 10 AM PST \\u2013 11/20/2007, 10 AM PST",
624 
625         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EEddMMyyyy", "Sat, 11/10/2007 \\u2013 Tue, 11/20/2007",
626 
627         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EddMMy", "Sat, 11/10/2007 \\u2013 Tue, 11/20/2007",
628 
629         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "hhmm", "11/10/2007, 10:10 AM \\u2013 11/20/2007, 10:10 AM",
630 
631         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "hhmmzz", "11/10/2007, 10:10 AM PST \\u2013 11/20/2007, 10:10 AM PST",
632 
633         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "hms", "11/10/2007, 10:10:10 AM \\u2013 11/20/2007, 10:10:10 AM",
634         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "Hms", "11/10/2007, 10:10:10 \\u2013 11/20/2007, 10:10:10",
635         "en", "CE 2007 11 10 20:10:10", "CE 2007 11 20 20:10:10", "Hms", "11/10/2007, 20:10:10 \\u2013 11/20/2007, 20:10:10",
636 
637         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dMMMMMy", "N 10 \\u2013 20, 2007",
638 
639         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EEEEEdM", "S, 11/10 \\u2013 T, 11/20",
640 
641         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "EEEEdMMMMy", "Wednesday, January 10, 2007",
642 
643         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "dMMMMy", "January 10, 2007",
644 
645         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "dMMMM", "January 10",
646 
647         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "MMMMy", "January 2007",
648 
649         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "EEEEdMMMM", "Wednesday, January 10",
650 
651         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "EdMMMy", "Wed, Jan 10, 2007",
652 
653         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "dMMMy", "Jan 10, 2007",
654 
655         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "dMMM", "Jan 10",
656 
657         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "MMMy", "Jan 2007",
658 
659         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "EdMMM", "Wed, Jan 10",
660 
661 
662         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "dMy", "1/10/2007",
663 
664         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "dM", "1/10",
665 
666         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "My", "1/2007",
667 
668         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "EdM", "Wed, 1/10",
669 
670         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "d", "10",
671 
672         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "Ed", "10 Wed",
673 
674         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "y", "2007",
675 
676         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "M", "1",
677 
678         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "MMM", "Jan",
679 
680         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "MMMM", "January",
681 
682         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "hm", "10:00 AM \\u2013 2:10 PM",
683         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "Hm", "10:00 \\u2013 14:10",
684 
685         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "hmv", "10:00 AM \\u2013 2:10 PM PT",
686 
687         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "hmz", "10:00 AM \\u2013 2:10 PM PST",
688 
689         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "h", "10 AM \\u2013 2 PM",
690         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "H", "10 \\u2013 14",
691 
692 
693         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "hz", "10 AM \\u2013 2 PM PST",
694 
695         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "EEddMMyyyy", "Wed, 01/10/2007",
696 
697         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "EddMMy", "Wed, 01/10/2007",
698 
699         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "hhmm", "10:00 AM \\u2013 2:10 PM",
700         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "HHmm", "10:00 \\u2013 14:10",
701 
702         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "hhmmzz", "10:00 AM \\u2013 2:10 PM PST",
703 
704         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "hms", "10:00:10 AM \\u2013 2:10:10 PM",
705         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "Hms", "10:00:10 \\u2013 14:10:10",
706 
707         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "dMMMMMy", "J 10, 2007",
708 
709         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "EEEEEdM", "W, 1/10",
710         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "dMMMMy", "January 10, 2007",
711 
712         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "dMMMM", "January 10",
713 
714         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "MMMMy", "January 2007",
715 
716         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "EEEEdMMMM", "Wednesday, January 10",
717 
718         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "EdMMMy", "Wed, Jan 10, 2007",
719 
720         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "dMMMy", "Jan 10, 2007",
721 
722         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "dMMM", "Jan 10",
723 
724 
725         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "EdMMM", "Wed, Jan 10",
726 
727         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "EdMy", "Wed, 1/10/2007",
728 
729         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "dMy", "1/10/2007",
730 
731 
732         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "My", "1/2007",
733 
734         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "EdM", "Wed, 1/10",
735 
736         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "d", "10",
737 
738 
739         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "y", "2007",
740 
741         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "M", "1",
742 
743 
744 
745         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hm", "10:00 \\u2013 10:20 AM",
746         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "Hm", "10:00 \\u2013 10:20",
747 
748 
749         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hmz", "10:00 \\u2013 10:20 AM PST",
750 
751 
752         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hv", "10 AM PT",
753 
754 
755 
756         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "EddMMy", "Wed, 01/10/2007",
757 
758         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hhmm", "10:00 \\u2013 10:20 AM",
759         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "HHmm", "10:00 \\u2013 10:20",
760 
761         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hhmmzz", "10:00 \\u2013 10:20 AM PST",
762 
763 
764         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "dMMMMMy", "J 10, 2007",
765 
766 
767         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "EEEEdMMMMy", "Wednesday, January 10, 2007",
768 
769         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "dMMMMy", "January 10, 2007",
770 
771 
772         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "MMMMy", "January 2007",
773 
774         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "EEEEdMMMM", "Wednesday, January 10",
775 
776 
777         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "dMMMy", "Jan 10, 2007",
778 
779         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "dMMM", "Jan 10",
780 
781 
782         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "EdMMM", "Wed, Jan 10",
783 
784         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "EdMy", "Wed, 1/10/2007",
785 
786         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "dMy", "1/10/2007",
787 
788 
789         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "My", "1/2007",
790 
791         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "EdM", "Wed, 1/10",
792 
793         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "d", "10",
794 
795 
796         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "y", "2007",
797 
798         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "M", "1",
799 
800 
801         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "MMMM", "January",
802 
803         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hm", "10:10 AM",
804         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "Hm", "10:10",
805 
806 
807         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hmz", "10:10 AM PST",
808 
809         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "h", "10 AM",
810 
811         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hv", "10 AM PT",
812 
813 
814         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "EEddMMyyyy", "Wed, 01/10/2007",
815 
816 
817         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hhmm", "10:10 AM",
818         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "HHmm", "10:10",
819 
820         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hhmmzz", "10:10 AM PST",
821 
822 
823         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "dMMMMMy", "J 10, 2007",
824 
825         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "EEEEEdM", "W, 1/10",
826 
827         "zh", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EEEEdMMMMy", "2007\\u5e7410\\u670810\\u65e5\\u661f\\u671f\\u4e09\\u81f32008\\u5e7410\\u670810\\u65e5\\u661f\\u671f\\u4e94",
828 
829 
830         "zh", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "dMMMMy", "2007\\u5e7410\\u670810\\u65e5\\u81f311\\u670810\\u65e5",
831 
832 
833         "zh", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "MMMMy", "2007\\u5e7410\\u6708\\u81f311\\u6708",
834 
835 
836         "zh", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "hmv", "2007/10/10 \\u6D1B\\u6749\\u77F6\\u65F6\\u95F4 \\u4E0A\\u534810:10 \\u2013 2007/11/10 \\u6D1B\\u6749\\u77F6\\u65F6\\u95F4 \\u4E0A\\u534810:10",
837 
838         "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EEEEdMMMMy", "2007\\u5e7411\\u670810\\u65e5\\u661f\\u671f\\u516d\\u81f320\\u65e5\\u661f\\u671f\\u4e8c",
839 
840 
841         "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dMMMM", "11\\u670810\\u65e5\\u81f320\\u65e5",
842 
843         "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "MMMMy", "2007\\u5E7411\\u6708", // (fixed expected result per ticket:6626:)
844 
845         "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EEEEdMMMM", "11\\u670810\\u65e5\\u661f\\u671f\\u516d\\u81f320\\u65e5\\u661f\\u671f\\u4e8c",
846 
847 
848         "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EdMy", "2007/11/10\\u5468\\u516d\\u81f32007/11/20\\u5468\\u4e8c",
849 
850 
851         "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dM", "11/10 \\u2013 11/20",
852 
853         "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "My", "2007\\u5E7411\\u6708",
854 
855         "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EdM", "11/10\\u5468\\u516d\\u81f311/20\\u5468\\u4e8c",
856 
857 
858         "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "y", "2007\\u5E74", // (fixed expected result per ticket:6626:)
859 
860         "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "M", "11\\u6708",
861 
862         "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "MMM", "11\\u6708", // (fixed expected result per ticket:6626: and others)
863 
864 
865         "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "hmz", "2007/11/10 GMT-8 \\u4e0a\\u534810:10 \\u2013 2007/11/20 GMT-8 \\u4e0a\\u534810:10",
866 
867         "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "h", "2007/11/10 \\u4e0a\\u534810\\u65f6 \\u2013 2007/11/20 \\u4e0a\\u534810\\u65f6",
868 
869         "zh", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "EEEEdMMMMy", "2007\\u5e741\\u670810\\u65e5\\u661f\\u671f\\u4e09", // (fixed expected result per ticket:6626:)
870 
871         "zh", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "hm", "\\u4e0a\\u534810:00\\u81f3\\u4e0b\\u53482:10",
872 
873 
874         "zh", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "hmz", "GMT-8\\u4e0a\\u534810:00\\u81f3\\u4e0b\\u53482:10",
875 
876         "zh", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "h", "\\u4e0a\\u534810\\u65F6\\u81f3\\u4e0b\\u53482\\u65f6",
877 
878         "zh", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "hv", "\\u6D1B\\u6749\\u77F6\\u65F6\\u95F4\\u4E0A\\u534810\\u65F6\\u81F3\\u4E0B\\u53482\\u65F6",
879 
880         "zh", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hm", "\\u4e0a\\u534810:00\\u81f310:20",
881 
882         "zh", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hmv", "\\u6D1B\\u6749\\u77F6\\u65F6\\u95F4\\u4E0A\\u534810:00\\u81F310:20",
883 
884         "zh", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hz", "GMT-8\\u4e0a\\u534810\\u65f6",
885 
886         "zh", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hm", "\\u4e0a\\u534810:10",
887 
888         "zh", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "h", "\\u4e0a\\u534810\\u65f6",
889 
890         "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EEEEdMMMy", "Mittwoch, 10. Okt. 2007 \\u2013 Freitag, 10. Okt. 2008",
891 
892 
893         "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "dMMM", "10. Okt. 2007 \\u2013 10. Okt. 2008",
894 
895         "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "MMMy", "Okt. 2007 \\u2013 Okt. 2008",
896 
897 
898         "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EdMy", "Mi., 10.10.2007 \\u2013 Fr., 10.10.2008",
899 
900         "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "dMy", "10.10.2007 \\u2013 10.10.2008",
901 
902 
903         "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "My", "10.2007 \\u2013 10.2008",
904 
905         "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EdM", "Mi., 10.10.2007 \\u2013 Fr., 10.10.2008",
906 
907 
908         "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "y", "2007\\u20132008",
909 
910         "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "M", "10.2007 \\u2013 10.2008",
911 
912 
913         "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "hm", "10.10.2007, 10:10 AM \\u2013 10.10.2008, 10:10 AM",
914         "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "Hm", "10.10.2007, 10:10 \\u2013 10.10.2008, 10:10",
915 
916         "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EEEEdMMMy", "Mittwoch, 10. Okt. \\u2013 Samstag, 10. Nov. 2007",
917 
918 
919         "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "dMMM", "10. Okt. \\u2013 10. Nov.",
920 
921         "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "MMMy", "Okt.\\u2013Nov. 2007",
922 
923         "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EEEEdMMM", "Mittwoch, 10. Okt. \\u2013 Samstag, 10. Nov.",
924 
925 
926         "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "dM", "10.10. \\u2013 10.11.",
927 
928         "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "My", "10.2007 \\u2013 11.2007",
929 
930 
931         "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "d", "10.10. \\u2013 10.11.",
932 
933         "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "y", "2007",
934 
935 
936         "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "MMM", "Okt.\\u2013Nov.",
937 
938 
939         "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "hms", "10.10.2007, 10:10:10 AM \\u2013 10.11.2007, 10:10:10 AM",
940         "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "Hms", "10.10.2007, 10:10:10 \\u2013 10.11.2007, 10:10:10",
941 
942         "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EEEEdMMMy", "Samstag, 10. \\u2013 Dienstag, 20. Nov. 2007",
943 
944         "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dMMMy", "10.\\u201320. Nov. 2007",
945 
946 
947         "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "MMMy", "Nov. 2007",
948 
949         "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EEEEdMMM", "Samstag, 10. \\u2013 Dienstag, 20. Nov.",
950 
951         "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EdMy", "Sa., 10. \\u2013 Di., 20.11.2007",
952 
953 
954         "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dM", "10.\\u201320.11.",
955 
956         "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "My", "11.2007",
957 
958 
959         "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "d", "10.\\u201320.",
960 
961         "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "y", "2007",
962 
963 
964         "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "hmv", "10.11.2007, 10:10 AM Los Angeles Zeit \\u2013 20.11.2007, 10:10 AM Los Angeles Zeit",
965 
966         "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "EEEEdMMMy", "Mittwoch, 10. Jan. 2007",
967 
968 
969         "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "dMMM", "10. Jan.",
970 
971         "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "MMMy", "Jan. 2007",
972 
973         "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "EEEEdMMM", "Mittwoch, 10. Jan.",
974 
975         /* Following is an important test, because the 'h' in 'Uhr' is interpreted as a pattern
976            if not escaped properly. */
977         "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "h", "10 Uhr AM \\u2013 2 Uhr PM",
978         "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "H", "10\\u201314 Uhr",
979 
980         "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "EEEEdMMM", "Mittwoch, 10. Jan.",
981 
982 
983         "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hmv", "10:00\\u201310:20 AM Los Angeles Zeit",
984 
985         "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hmz", "10:00\\u201310:20 AM GMT-8",
986 
987         "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "h", "10 Uhr AM",
988         "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "H", "10 Uhr",
989 
990 
991         "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hz", "10 Uhr AM GMT-8",
992 
993         "de", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "EEEEdMMMy", "Mittwoch, 10. Jan. 2007",
994 
995 
996         "de", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hmv", "10:10 AM Los Angeles Zeit",
997 
998         "de", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hmz", "10:10 AM GMT-8",
999 
1000 
1001         "de", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hv", "10 Uhr AM Los Angeles Zeit",
1002 
1003         "de", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hz", "10 Uhr AM GMT-8",
1004 
1005         // Thai (default calendar buddhist)
1006 
1007         "th", "BE 2550 10 10 10:10:10", "BE 2551 10 10 10:10:10", "EEEEdMMMy", "\\u0E27\\u0E31\\u0E19\\u0E1E\\u0E38\\u0E18\\u0E17\\u0E35\\u0E48 10 \\u0E15.\\u0E04. 2550 \\u2013 \\u0E27\\u0E31\\u0E19\\u0E28\\u0E38\\u0E01\\u0E23\\u0E4C\\u0E17\\u0E35\\u0E48 10 \\u0E15.\\u0E04. 2551",
1008 
1009 
1010         "th", "BE 2550 10 10 10:10:10", "BE 2551 10 10 10:10:10", "dMMM", "10 \\u0E15.\\u0E04. 2550 \\u2013 10 \\u0E15.\\u0E04. 2551",
1011 
1012         "th", "BE 2550 10 10 10:10:10", "BE 2551 10 10 10:10:10", "MMMy", "\\u0E15.\\u0E04. 2550 \\u2013 \\u0E15.\\u0E04. 2551",
1013 
1014 
1015         "th", "BE 2550 10 10 10:10:10", "BE 2551 10 10 10:10:10", "EdMy", "\\u0E1E. 10/10/2550 \\u2013 \\u0E28. 10/10/2551",
1016 
1017         "th", "BE 2550 10 10 10:10:10", "BE 2551 10 10 10:10:10", "dMy", "10/10/2550 \\u2013 10/10/2551",
1018 
1019 
1020         "th", "BE 2550 10 10 10:10:10", "BE 2551 10 10 10:10:10", "My", "10/2550 \\u2013 10/2551",
1021 
1022         "th", "BE 2550 10 10 10:10:10", "BE 2551 10 10 10:10:10", "EdM", "\\u0E1E. 10/10/2550 \\u2013 \\u0E28. 10/10/2551",
1023 
1024 
1025         "th", "BE 2550 10 10 10:10:10", "BE 2551 10 10 10:10:10", "y", "2550\\u20132551",
1026 
1027         "th", "BE 2550 10 10 10:10:10", "BE 2551 10 10 10:10:10", "M", "10/2550 \\u2013 10/2551",
1028 
1029 
1030         "th", "BE 2550 10 10 10:10:10", "BE 2550 11 10 10:10:10", "EEEEdMMMy", "\\u0E27\\u0E31\\u0E19\\u0E1E\\u0E38\\u0E18\\u0E17\\u0E35\\u0E48 10 \\u0E15.\\u0E04. \\u2013 \\u0E27\\u0E31\\u0E19\\u0E40\\u0E2A\\u0E32\\u0E23\\u0E4C\\u0E17\\u0E35\\u0E48 10 \\u0E1E.\\u0E22. 2550",
1031 
1032 
1033         "th", "BE 2550 10 10 10:10:10", "BE 2550 11 10 10:10:10", "dMMM", "10 \\u0E15.\\u0E04. \\u2013 10 \\u0E1E.\\u0E22.",
1034 
1035         "th", "BE 2550 10 10 10:10:10", "BE 2550 11 10 10:10:10", "MMMy", "\\u0E15.\\u0E04.\\u2013\\u0E1E.\\u0E22. 2550",
1036 
1037         "th", "2550 10 10 10:10:10", "2550 11 10 10:10:10", "dM", "10/10 \\u2013 10/11",
1038 
1039         "th", "BE 2550 10 10 10:10:10", "BE 2550 11 10 10:10:10", "My", "10/2550 \\u2013 11/2550",
1040 
1041 
1042         "th", "BE 2550 10 10 10:10:10", "BE 2550 11 10 10:10:10", "d", "10/10 \\u2013 10/11",
1043 
1044         "th", "BE 2550 10 10 10:10:10", "BE 2550 11 10 10:10:10", "y", "\\u0E1E.\\u0E28. 2550",
1045 
1046 
1047         "th", "BE 2550 10 10 10:10:10", "BE 2550 11 10 10:10:10", "MMM", "\\u0E15.\\u0E04.\\u2013\\u0E1E.\\u0E22.",
1048 
1049         // Tests for Japanese calendar with eras, including new era in 2019 (Heisei 31 through April 30, then new era)
1050 
1051         "en-u-ca-japanese", "H 31 03 15 09:00:00", "H 31 04 15 09:00:00", "GyMMMd", "Mar 15 \\u2013 Apr 15, 31 Heisei",
1052 
1053         "en-u-ca-japanese", "H 31 03 15 09:00:00", "H 31 04 15 09:00:00", "GGGGGyMd", "3/15/31 \\u2013 4/15/31 H",
1054 
1055         "en-u-ca-japanese", "S 64 01 05 09:00:00", "H 1 01 15 09:00:00",  "GyMMMd", "Jan 5, 64 Sh\\u014Dwa \\u2013 Jan 15, 1 Heisei",
1056 
1057         "en-u-ca-japanese", "S 64 01 05 09:00:00", "H 1 01 15 09:00:00",  "GGGGGyMd", "1/5/64 S \\u2013 1/15/1 H",
1058 
1059         "en-u-ca-japanese", "H 31 04 15 09:00:00", JP_ERA_2019_NARROW " 1 05 15 09:00:00",  "GyMMMd", "Apr 15, 31 Heisei \\u2013 May 15, 1 " JP_ERA_2019_ROOT,
1060 
1061         "en-u-ca-japanese", "H 31 04 15 09:00:00", JP_ERA_2019_NARROW " 1 05 15 09:00:00",  "GGGGGyMd", "4/15/31 H \\u2013 5/15/1 " JP_ERA_2019_NARROW,
1062 
1063 
1064         "ja-u-ca-japanese", "H 31 03 15 09:00:00", "H 31 04 15 09:00:00", "GyMMMd", "\\u5E73\\u621031\\u5E743\\u670815\\u65E5\\uFF5E4\\u670815\\u65E5",
1065 
1066         "ja-u-ca-japanese", "H 31 03 15 09:00:00", "H 31 04 15 09:00:00", "GGGGGyMd", "H31/03/15\\uFF5E31/04/15",
1067 
1068         "ja-u-ca-japanese", "S 64 01 05 09:00:00", "H 1 01 15 09:00:00",  "GyMMMd", "\\u662D\\u548C64\\u5E741\\u67085\\u65E5\\uFF5E\\u5E73\\u6210\\u5143\\u5E741\\u670815\\u65E5",
1069 
1070         "ja-u-ca-japanese", "S 64 01 05 09:00:00", "H 1 01 15 09:00:00",  "GGGGGyMd", "S64/01/05\\uFF5EH1/01/15",
1071 
1072         "ja-u-ca-japanese", "H 31 04 15 09:00:00", JP_ERA_2019_NARROW " 1 05 15 09:00:00", "GGGGGyMd", "H31/04/15\\uFF5E" JP_ERA_2019_NARROW "1/05/15",
1073 
1074     };
1075     expect(DATA, UPRV_LENGTHOF(DATA));
1076 }
1077 
1078 
expect(const char ** data,int32_t data_length)1079 void DateIntervalFormatTest::expect(const char** data, int32_t data_length) {
1080     int32_t i = 0;
1081     UErrorCode ec = U_ZERO_ERROR;
1082     UnicodeString str, str2;
1083     const char* pattern = data[i++];
1084 
1085     while (i<data_length) {
1086         const char* locName = data[i++];
1087         const char* datestr = data[i++];
1088         const char* datestr_2 = data[i++];
1089 
1090         Locale loc(locName);
1091         LocalPointer<Calendar> defCal(Calendar::createInstance(loc, ec));
1092         if (U_FAILURE(ec)) {
1093             dataerrln("Calendar::createInstance fails for loc %s with: %s", locName, u_errorName(ec));
1094             return;
1095         }
1096         const char* calType = defCal->getType();
1097 
1098         Locale refLoc("root");
1099         if (calType) {
1100             refLoc.setKeywordValue("calendar", calType, ec);
1101         }
1102         SimpleDateFormat ref(pattern, refLoc, ec);
1103         logln( "case %d, locale: %s\n", (i-1)/5, locName);
1104         if (U_FAILURE(ec)) {
1105             dataerrln("contruct SimpleDateFormat in expect failed: %s", u_errorName(ec));
1106             return;
1107         }
1108 
1109         // 'f'
1110         logln("original date: %s - %s\n", datestr, datestr_2);
1111         UDate date = ref.parse(ctou(datestr), ec);
1112         if (!assertSuccess("parse 1st data in expect", ec)) return;
1113         UDate date_2 = ref.parse(ctou(datestr_2), ec);
1114         if (!assertSuccess("parse 2nd data in expect", ec)) return;
1115         DateInterval dtitv(date, date_2);
1116 
1117         const UnicodeString& oneSkeleton(ctou(data[i++]));
1118 
1119         DateIntervalFormat* dtitvfmt = DateIntervalFormat::createInstance(oneSkeleton, loc, ec);
1120         if (!assertSuccess("createInstance(skeleton) in expect", ec)) return;
1121         FieldPosition pos(FieldPosition::DONT_CARE);
1122         dtitvfmt->format(&dtitv, str.remove(), pos, ec);
1123         if (!assertSuccess("format in expect", ec)) return;
1124         assertEquals((UnicodeString)"\"" + locName + "\\" + oneSkeleton + "\\" + ctou(datestr) + "\\" + ctou(datestr_2) + "\"", ctou(data[i++]), str);
1125 
1126         logln("interval date:" + str + "\"" + locName + "\", "
1127                  + "\"" + datestr + "\", "
1128               + "\"" + datestr_2 + "\", " + oneSkeleton);
1129         delete dtitvfmt;
1130     }
1131 }
1132 
1133 
1134 /*
1135  * Test format using user defined DateIntervalInfo
1136  */
testFormatUserDII()1137 void DateIntervalFormatTest::testFormatUserDII() {
1138     // first item is date pattern
1139     const char* DATA[] = {
1140         "yyyy MM dd HH:mm:ss",
1141         "en", "2007 10 10 10:10:10", "2008 10 10 10:10:10", "Oct 10, 2007 --- Oct 10, 2008",
1142 
1143         "en", "2007 10 10 10:10:10", "2007 11 10 10:10:10", "2007 Oct 10 - Nov 2007",
1144 
1145         "en", "2007 11 10 10:10:10", "2007 11 20 10:10:10", "Nov 10, 2007 --- Nov 20, 2007",
1146 
1147         "en", "2007 01 10 10:00:10", "2007 01 10 14:10:10", "Jan 10, 2007",
1148 
1149         "en", "2007 01 10 10:00:10", "2007 01 10 10:20:10", "Jan 10, 2007",
1150 
1151         "en", "2007 01 10 10:10:10", "2007 01 10 10:10:20", "Jan 10, 2007",
1152 
1153         "zh", "2007 10 10 10:10:10", "2008 10 10 10:10:10", "2007\\u5e7410\\u670810\\u65e5 --- 2008\\u5e7410\\u670810\\u65e5",
1154 
1155         "zh", "2007 10 10 10:10:10", "2007 11 10 10:10:10", "2007 10\\u6708 10 - 11\\u6708 2007",
1156 
1157         "zh", "2007 11 10 10:10:10", "2007 11 20 10:10:10", "2007\\u5e7411\\u670810\\u65e5 --- 2007\\u5e7411\\u670820\\u65e5",
1158 
1159         "zh", "2007 01 10 10:00:10", "2007 01 10 14:10:10", "2007\\u5e741\\u670810\\u65e5", // (fixed expected result per ticket:6626:)
1160 
1161         "zh", "2007 01 10 10:00:10", "2007 01 10 10:20:10", "2007\\u5e741\\u670810\\u65e5", // (fixed expected result per ticket:6626:)
1162 
1163         "zh", "2007 01 10 10:10:10", "2007 01 10 10:10:20", "2007\\u5e741\\u670810\\u65e5", // (fixed expected result per ticket:6626:)
1164 
1165         "de", "2007 10 10 10:10:10", "2008 10 10 10:10:10", "10. Okt. 2007 --- 10. Okt. 2008",
1166 
1167 
1168         "de", "2007 11 10 10:10:10", "2007 11 20 10:10:10", "10. Nov. 2007 --- 20. Nov. 2007",
1169 
1170         "de", "2007 01 10 10:00:10", "2007 01 10 14:10:10", "10. Jan. 2007",
1171 
1172         "de", "2007 01 10 10:00:10", "2007 01 10 10:20:10", "10. Jan. 2007",
1173 
1174 
1175         "es", "2007 10 10 10:10:10", "2008 10 10 10:10:10", "10 oct. 2007 --- 10 oct. 2008",
1176 
1177         "es", "2007 10 10 10:10:10", "2007 11 10 10:10:10", "2007 oct. 10 - nov. 2007",
1178 
1179         "es", "2007 11 10 10:10:10", "2007 11 20 10:10:10", "10 nov. 2007 --- 20 nov. 2007",
1180 
1181         "es", "2007 01 10 10:00:10", "2007 01 10 14:10:10", "10 ene. 2007",
1182 
1183         "es", "2007 01 10 10:00:10", "2007 01 10 10:20:10", "10 ene. 2007",
1184 
1185         "es", "2007 01 10 10:10:10", "2007 01 10 10:10:20", "10 ene. 2007",
1186     };
1187     expectUserDII(DATA, UPRV_LENGTHOF(DATA));
1188 }
1189 
1190 
testSetIntervalPatternNoSideEffect()1191 void DateIntervalFormatTest::testSetIntervalPatternNoSideEffect() {
1192     UErrorCode ec = U_ZERO_ERROR;
1193     LocalPointer<DateIntervalInfo> dtitvinf(new DateIntervalInfo(ec), ec);
1194     if (U_FAILURE(ec)) {
1195         errln("Failure encountered: %s", u_errorName(ec));
1196         return;
1197     }
1198     UnicodeString expected;
1199     dtitvinf->getIntervalPattern(ctou("yMd"), UCAL_DATE, expected, ec);
1200     dtitvinf->setIntervalPattern(ctou("yMd"), UCAL_DATE, ctou("M/d/y \\u2013 d"), ec);
1201     if (U_FAILURE(ec)) {
1202         errln("Failure encountered: %s", u_errorName(ec));
1203         return;
1204     }
1205     dtitvinf.adoptInsteadAndCheckErrorCode(new DateIntervalInfo(ec), ec);
1206     if (U_FAILURE(ec)) {
1207         errln("Failure encountered: %s", u_errorName(ec));
1208         return;
1209     }
1210     UnicodeString actual;
1211     dtitvinf->getIntervalPattern(ctou("yMd"), UCAL_DATE, actual, ec);
1212     if (U_FAILURE(ec)) {
1213         errln("Failure encountered: %s", u_errorName(ec));
1214         return;
1215     }
1216     if (expected != actual) {
1217         errln("DateIntervalInfo.setIntervalPattern should have no side effects.");
1218     }
1219 }
1220 
testYearFormats()1221 void DateIntervalFormatTest::testYearFormats() {
1222     const Locale &enLocale = Locale::getEnglish();
1223     UErrorCode status = U_ZERO_ERROR;
1224     LocalPointer<Calendar> fromTime(Calendar::createInstance(enLocale, status));
1225     LocalPointer<Calendar> toTime(Calendar::createInstance(enLocale, status));
1226     if (U_FAILURE(status)) {
1227         errln("Failure encountered: %s", u_errorName(status));
1228         return;
1229     }
1230     // April 26, 113. Three digit year so that we can test 2 digit years;
1231     // 4 digit years with padded 0's and full years.
1232     fromTime->set(113, 3, 26);
1233     // April 28, 113.
1234     toTime->set(113, 3, 28);
1235     {
1236         LocalPointer<DateIntervalFormat> dif(DateIntervalFormat::createInstance("yyyyMd", enLocale, status));
1237         if (U_FAILURE(status)) {
1238             dataerrln("Failure encountered: %s", u_errorName(status));
1239             return;
1240         }
1241         UnicodeString actual;
1242         UnicodeString expected(ctou("4/26/0113 \\u2013 4/28/0113"));
1243         FieldPosition pos;
1244         dif->format(*fromTime, *toTime, actual, pos, status);
1245         if (U_FAILURE(status)) {
1246             errln("Failure encountered: %s", u_errorName(status));
1247             return;
1248         }
1249         if (actual != expected) {
1250             errln("Expected " + expected + ", got: " + actual);
1251         }
1252     }
1253     {
1254         LocalPointer<DateIntervalFormat> dif(DateIntervalFormat::createInstance("yyMd", enLocale, status));
1255         if (U_FAILURE(status)) {
1256             errln("Failure encountered: %s", u_errorName(status));
1257             return;
1258         }
1259         UnicodeString actual;
1260         UnicodeString expected(ctou("4/26/13 \\u2013 4/28/13"));
1261         FieldPosition pos(FieldPosition::DONT_CARE);
1262         dif->format(*fromTime, *toTime, actual, pos, status);
1263         if (U_FAILURE(status)) {
1264             errln("Failure encountered: %s", u_errorName(status));
1265             return;
1266         }
1267         if (actual != expected) {
1268             errln("Expected " + expected + ", got: " + actual);
1269         }
1270     }
1271     {
1272         LocalPointer<DateIntervalFormat> dif(DateIntervalFormat::createInstance("yMd", enLocale, status));
1273         if (U_FAILURE(status)) {
1274             errln("Failure encountered: %s", u_errorName(status));
1275             return;
1276         }
1277         UnicodeString actual;
1278         UnicodeString expected(ctou("4/26/113 \\u2013 4/28/113"));
1279         FieldPosition pos(FieldPosition::DONT_CARE);
1280         dif->format(*fromTime, *toTime, actual, pos, status);
1281         if (U_FAILURE(status)) {
1282             errln("Failure encountered: %s", u_errorName(status));
1283             return;
1284         }
1285         if (actual != expected) {
1286             errln("Expected " + expected + ", got: " + actual);
1287         }
1288     }
1289 }
1290 
expectUserDII(const char ** data,int32_t data_length)1291 void DateIntervalFormatTest::expectUserDII(const char** data,
1292                                            int32_t data_length) {
1293     int32_t i = 0;
1294     UnicodeString str;
1295     UErrorCode ec = U_ZERO_ERROR;
1296     const char* pattern = data[0];
1297     i++;
1298 
1299     while ( i < data_length ) {
1300         const char* locName = data[i++];
1301         Locale loc(locName);
1302         SimpleDateFormat ref(pattern, loc, ec);
1303         if (U_FAILURE(ec)) {
1304             dataerrln("contruct SimpleDateFormat in expectUserDII failed: %s", u_errorName(ec));
1305             return;
1306         }
1307         const char* datestr = data[i++];
1308         const char* datestr_2 = data[i++];
1309         UDate date = ref.parse(ctou(datestr), ec);
1310         if (!assertSuccess("parse in expectUserDII", ec)) return;
1311         UDate date_2 = ref.parse(ctou(datestr_2), ec);
1312         if (!assertSuccess("parse in expectUserDII", ec)) return;
1313         DateInterval dtitv(date, date_2);
1314 
1315         ec = U_ZERO_ERROR;
1316         // test user created DateIntervalInfo
1317         DateIntervalInfo* dtitvinf = new DateIntervalInfo(ec);
1318         dtitvinf->setFallbackIntervalPattern("{0} --- {1}", ec);
1319         dtitvinf->setIntervalPattern(UDAT_YEAR_ABBR_MONTH_DAY, UCAL_MONTH, "yyyy MMM d - MMM y",ec);
1320         if (!assertSuccess("DateIntervalInfo::setIntervalPattern", ec)) return;
1321         dtitvinf->setIntervalPattern(UDAT_YEAR_ABBR_MONTH_DAY, UCAL_HOUR_OF_DAY, "yyyy MMM d HH:mm - HH:mm", ec);
1322         if (!assertSuccess("DateIntervalInfo::setIntervalPattern", ec)) return;
1323         DateIntervalFormat* dtitvfmt = DateIntervalFormat::createInstance(UDAT_YEAR_ABBR_MONTH_DAY, loc, *dtitvinf, ec);
1324         delete dtitvinf;
1325         if (!assertSuccess("createInstance(skeleton,dtitvinf) in expectUserDII", ec)) return;
1326         FieldPosition pos(FieldPosition::DONT_CARE);
1327         dtitvfmt->format(&dtitv, str.remove(), pos, ec);
1328         if (!assertSuccess("format in expectUserDII", ec)) return;
1329         assertEquals((UnicodeString)"\"" + locName + "\\" + datestr + "\\" + datestr_2 + "\"", ctou(data[i++]), str);
1330 #ifdef DTIFMTTS_DEBUG
1331         char result[1000];
1332         char mesg[1000];
1333         PRINTMESG("interval format using user defined DateIntervalInfo\n");
1334         str.extract(0,  str.length(), result, "UTF-8");
1335         sprintf(mesg, "interval date: %s\n", result);
1336         PRINTMESG(mesg);
1337 #endif
1338         delete dtitvfmt;
1339     }
1340 }
1341 
1342 
testStress()1343 void DateIntervalFormatTest::testStress() {
1344     if(quick){
1345     	logln("Quick mode: Skipping test");
1346     	return;
1347     }
1348 	const char* DATA[] = {
1349         "yyyy MM dd HH:mm:ss",
1350         "2007 10 10 10:10:10", "2008 10 10 10:10:10",
1351         "2007 10 10 10:10:10", "2007 11 10 10:10:10",
1352         "2007 11 10 10:10:10", "2007 11 20 10:10:10",
1353         "2007 01 10 10:00:10", "2007 01 10 14:10:10",
1354         "2007 01 10 10:00:10", "2007 01 10 10:20:10",
1355         "2007 01 10 10:10:10", "2007 01 10 10:10:20",
1356     };
1357 
1358     const char* testLocale[][3] = {
1359         //{"th", "", ""},
1360         {"en", "", ""},
1361         {"zh", "", ""},
1362         {"de", "", ""},
1363         {"ar", "", ""},
1364         {"en", "GB",  ""},
1365         {"fr", "", ""},
1366         {"it", "", ""},
1367         {"nl", "", ""},
1368         {"zh", "TW",  ""},
1369         {"ja", "", ""},
1370         {"pt", "BR", ""},
1371         {"ru", "", ""},
1372         {"pl", "", ""},
1373         {"tr", "", ""},
1374         {"es", "", ""},
1375         {"ko", "", ""},
1376         {"sv", "", ""},
1377         {"fi", "", ""},
1378         {"da", "", ""},
1379         {"pt", "PT", ""},
1380         {"ro", "", ""},
1381         {"hu", "", ""},
1382         {"he", "", ""},
1383         {"in", "", ""},
1384         {"cs", "", ""},
1385         {"el", "", ""},
1386         {"no", "", ""},
1387         {"vi", "", ""},
1388         {"bg", "", ""},
1389         {"hr", "", ""},
1390         {"lt", "", ""},
1391         {"sk", "", ""},
1392         {"sl", "", ""},
1393         {"sr", "", ""},
1394         {"ca", "", ""},
1395         {"lv", "", ""},
1396         {"uk", "", ""},
1397         {"hi", "", ""},
1398     };
1399 
1400     uint32_t localeIndex;
1401     for ( localeIndex = 0; localeIndex < UPRV_LENGTHOF(testLocale); ++localeIndex ) {
1402         char locName[32];
1403         uprv_strcpy(locName, testLocale[localeIndex][0]);
1404         uprv_strcat(locName, testLocale[localeIndex][1]);
1405         stress(DATA, UPRV_LENGTHOF(DATA), Locale(testLocale[localeIndex][0], testLocale[localeIndex][1], testLocale[localeIndex][2]), locName);
1406     }
1407 }
1408 
1409 
stress(const char ** data,int32_t data_length,const Locale & loc,const char * locName)1410 void DateIntervalFormatTest::stress(const char** data, int32_t data_length,
1411                                     const Locale& loc, const char* locName) {
1412     UnicodeString skeleton[] = {
1413         "EEEEdMMMMy",
1414         "dMMMMy",
1415         "dMMMM",
1416         "MMMMy",
1417         "EEEEdMMMM",
1418         "EdMMMy",
1419         "dMMMy",
1420         "dMMM",
1421         "MMMy",
1422         "EdMMM",
1423         "EdMy",
1424         "dMy",
1425         "dM",
1426         "My",
1427         "EdM",
1428         "d",
1429         "Ed",
1430         "y",
1431         "M",
1432         "MMM",
1433         "MMMM",
1434         "hm",
1435         "hmv",
1436         "hmz",
1437         "h",
1438         "hv",
1439         "hz",
1440         "EEddMMyyyy", // following could be normalized
1441         "EddMMy",
1442         "hhmm",
1443         "hhmmzz",
1444         "hms",  // following could not be normalized
1445         "dMMMMMy",
1446         "EEEEEdM",
1447     };
1448 
1449     int32_t i = 0;
1450     UErrorCode ec = U_ZERO_ERROR;
1451     UnicodeString str, str2;
1452     SimpleDateFormat ref(data[i++], loc, ec);
1453     if (!assertSuccess("construct SimpleDateFormat", ec)) return;
1454 
1455 #ifdef DTIFMTTS_DEBUG
1456     char result[1000];
1457     char mesg[1000];
1458     sprintf(mesg, "locale: %s\n", locName);
1459     PRINTMESG(mesg);
1460 #endif
1461 
1462     while (i<data_length) {
1463 
1464         // 'f'
1465         const char* datestr = data[i++];
1466         const char* datestr_2 = data[i++];
1467 #ifdef DTIFMTTS_DEBUG
1468         sprintf(mesg, "original date: %s - %s\n", datestr, datestr_2);
1469         PRINTMESG(mesg)
1470 #endif
1471         UDate date = ref.parse(ctou(datestr), ec);
1472         if (!assertSuccess("parse", ec)) return;
1473         UDate date_2 = ref.parse(ctou(datestr_2), ec);
1474         if (!assertSuccess("parse", ec)) return;
1475         DateInterval dtitv(date, date_2);
1476 
1477         for ( uint32_t skeletonIndex = 0;
1478               skeletonIndex < UPRV_LENGTHOF(skeleton);
1479               ++skeletonIndex ) {
1480             const UnicodeString& oneSkeleton = skeleton[skeletonIndex];
1481             DateIntervalFormat* dtitvfmt = DateIntervalFormat::createInstance(oneSkeleton, loc, ec);
1482             if (!assertSuccess("createInstance(skeleton)", ec)) return;
1483             /*
1484             // reset the calendar to be Gregorian calendar for "th"
1485             if ( uprv_strcmp(locName, "th") == 0 ) {
1486                 GregorianCalendar* gregCal = new GregorianCalendar(loc, ec);
1487                 if (!assertSuccess("GregorianCalendar()", ec)) return;
1488                 const DateFormat* dformat = dtitvfmt->getDateFormat();
1489                 DateFormat* newOne = dformat->clone();
1490                 newOne->adoptCalendar(gregCal);
1491                 //dtitvfmt->adoptDateFormat(newOne, ec);
1492                 dtitvfmt->setDateFormat(*newOne, ec);
1493                 delete newOne;
1494                 if (!assertSuccess("adoptDateFormat()", ec)) return;
1495             }
1496             */
1497             FieldPosition pos(FieldPosition::DONT_CARE);
1498             dtitvfmt->format(&dtitv, str.remove(), pos, ec);
1499             if (!assertSuccess("format", ec)) return;
1500 #ifdef DTIFMTTS_DEBUG
1501             oneSkeleton.extract(0,  oneSkeleton.length(), result, "UTF-8");
1502             sprintf(mesg, "interval by skeleton: %s\n", result);
1503             PRINTMESG(mesg)
1504             str.extract(0,  str.length(), result, "UTF-8");
1505             sprintf(mesg, "interval date: %s\n", result);
1506             PRINTMESG(mesg)
1507 #endif
1508             delete dtitvfmt;
1509         }
1510 
1511         // test user created DateIntervalInfo
1512         ec = U_ZERO_ERROR;
1513         DateIntervalInfo* dtitvinf = new DateIntervalInfo(ec);
1514         dtitvinf->setFallbackIntervalPattern("{0} --- {1}", ec);
1515         dtitvinf->setIntervalPattern(UDAT_YEAR_ABBR_MONTH_DAY, UCAL_MONTH, "yyyy MMM d - MMM y",ec);
1516         if (!assertSuccess("DateIntervalInfo::setIntervalPattern", ec)) return;
1517         dtitvinf->setIntervalPattern(UDAT_YEAR_ABBR_MONTH_DAY, UCAL_HOUR_OF_DAY, "yyyy MMM d HH:mm - HH:mm", ec);
1518         if (!assertSuccess("DateIntervalInfo::setIntervalPattern", ec)) return;
1519         DateIntervalFormat* dtitvfmt = DateIntervalFormat::createInstance(UDAT_YEAR_ABBR_MONTH_DAY, loc, *dtitvinf, ec);
1520         delete dtitvinf;
1521         if (!assertSuccess("createInstance(skeleton,dtitvinf)", ec)) return;
1522         FieldPosition pos(FieldPosition::DONT_CARE);
1523         dtitvfmt->format(&dtitv, str.remove(), pos, ec);
1524         if ( uprv_strcmp(locName, "th") ) {
1525             if (!assertSuccess("format", ec)) return;
1526 #ifdef DTIFMTTS_DEBUG
1527             PRINTMESG("interval format using user defined DateIntervalInfo\n");
1528             str.extract(0,  str.length(), result, "UTF-8");
1529             sprintf(mesg, "interval date: %s\n", result);
1530             PRINTMESG(mesg)
1531 #endif
1532         } else {
1533             // for "th", the default calendar is Budhist,
1534             // not Gregorian.
1535             assertTrue("Default calendar for \"th\" is Budhist", ec == U_ILLEGAL_ARGUMENT_ERROR);
1536             ec = U_ZERO_ERROR;
1537         }
1538         delete dtitvfmt;
1539     }
1540 }
1541 
testTicket11583_2()1542 void DateIntervalFormatTest::testTicket11583_2() {
1543     UErrorCode status = U_ZERO_ERROR;
1544     LocalPointer<DateIntervalFormat> fmt(
1545             DateIntervalFormat::createInstance("yMMM", "es-US", status));
1546     if (!assertSuccess("Error create format object", status)) {
1547         return;
1548     }
1549     DateInterval interval((UDate) 1232364615000.0, (UDate) 1328787015000.0);
1550     UnicodeString appendTo;
1551     FieldPosition fpos(FieldPosition::DONT_CARE);
1552     UnicodeString expected("ene. de 2009 \\u2013 feb. de 2012");
1553     assertEquals(
1554             "",
1555             expected.unescape(),
1556             fmt->format(&interval, appendTo, fpos, status));
1557     if (!assertSuccess("Error formatting", status)) {
1558         return;
1559     }
1560 }
1561 
1562 
testTicket11985()1563 void DateIntervalFormatTest::testTicket11985() {
1564     UErrorCode status = U_ZERO_ERROR;
1565     LocalPointer<DateIntervalFormat> fmt(
1566             DateIntervalFormat::createInstance(UDAT_HOUR_MINUTE, Locale::getEnglish(), status));
1567     if (!assertSuccess("createInstance", status)) {
1568         return;
1569     }
1570     UnicodeString pattern;
1571     static_cast<const SimpleDateFormat*>(fmt->getDateFormat())->toPattern(pattern);
1572     assertEquals("Format pattern", "h:mm a", pattern);
1573 }
1574 
1575 // Ticket 11669 - thread safety of DateIntervalFormat::format(). This test failed before
1576 //                the implementation was fixed.
1577 
1578 static const DateIntervalFormat *gIntervalFormatter = NULL;      // The Formatter to be used concurrently by test threads.
1579 static const DateInterval *gInterval = NULL;                     // The date interval to be formatted concurrently.
1580 static const UnicodeString *gExpectedResult = NULL;
1581 
threadFunc11669(int32_t threadNum)1582 void DateIntervalFormatTest::threadFunc11669(int32_t threadNum) {
1583     (void)threadNum;
1584     for (int loop=0; loop<1000; ++loop) {
1585         UErrorCode status = U_ZERO_ERROR;
1586         FieldPosition pos(FieldPosition::DONT_CARE);
1587         UnicodeString result;
1588         gIntervalFormatter->format(gInterval, result, pos, status);
1589         if (U_FAILURE(status)) {
1590             errln("%s:%d %s", __FILE__, __LINE__, u_errorName(status));
1591             return;
1592         }
1593         if (result != *gExpectedResult) {
1594             errln("%s:%d Expected \"%s\", got \"%s\"", __FILE__, __LINE__, CStr(*gExpectedResult)(), CStr(result)());
1595             return;
1596         }
1597     }
1598 }
1599 
testTicket11669()1600 void DateIntervalFormatTest::testTicket11669() {
1601     UErrorCode status = U_ZERO_ERROR;
1602     LocalPointer<DateIntervalFormat> formatter(DateIntervalFormat::createInstance(UDAT_YEAR_MONTH_DAY, Locale::getEnglish(), status), status);
1603     LocalPointer<TimeZone> tz(TimeZone::createTimeZone("America/Los_Angleles"), status);
1604     LocalPointer<Calendar> intervalStart(Calendar::createInstance(*tz, Locale::getEnglish(), status), status);
1605     LocalPointer<Calendar> intervalEnd(Calendar::createInstance(*tz, Locale::getEnglish(), status), status);
1606     if (U_FAILURE(status)) {
1607         errcheckln(status, "%s:%d %s", __FILE__, __LINE__, u_errorName(status));
1608         return;
1609     }
1610 
1611     intervalStart->set(2009, 6, 1, 14, 0);
1612     intervalEnd->set(2009, 6, 2, 14, 0);
1613     DateInterval interval(intervalStart->getTime(status), intervalEnd->getTime(status));
1614     FieldPosition pos(FieldPosition::DONT_CARE);
1615     UnicodeString expectedResult;
1616     formatter->format(&interval, expectedResult, pos, status);
1617     if (U_FAILURE(status)) {
1618         errln("%s:%d %s", __FILE__, __LINE__, u_errorName(status));
1619         return;
1620     }
1621 
1622     gInterval = &interval;
1623     gIntervalFormatter = formatter.getAlias();
1624     gExpectedResult = &expectedResult;
1625 
1626     ThreadPool<DateIntervalFormatTest> threads(this, 4, &DateIntervalFormatTest::threadFunc11669);
1627     threads.start();
1628     threads.join();
1629 
1630     gInterval = NULL;             // Don't leave dangling pointers lying around. Not strictly necessary.
1631     gIntervalFormatter = NULL;
1632     gExpectedResult = NULL;
1633 }
1634 
1635 
1636 // testTicket12065
1637 //    Using a DateIntervalFormat to format shouldn't change its state in any way
1638 //    that changes how the behavior of operator ==.
testTicket12065()1639 void DateIntervalFormatTest::testTicket12065() {
1640     UErrorCode status = U_ZERO_ERROR;
1641     LocalPointer<DateIntervalFormat> formatter(DateIntervalFormat::createInstance(UDAT_YEAR_MONTH_DAY, Locale::getEnglish(), status), status);
1642     if (formatter.isNull()) {
1643         dataerrln("FAIL: DateIntervalFormat::createInstance failed for Locale::getEnglish()");
1644         return;
1645     }
1646     LocalPointer<DateIntervalFormat> clone(formatter->clone());
1647     if (*formatter != *clone) {
1648         errln("%s:%d DateIntervalFormat and clone are not equal.", __FILE__, __LINE__);
1649         return;
1650     }
1651     DateInterval interval((UDate) 1232364615000.0, (UDate) 1328787015000.0);
1652     UnicodeString appendTo;
1653     FieldPosition fpos(FieldPosition::DONT_CARE);
1654     formatter->format(&interval, appendTo, fpos, status);
1655     if (*formatter != *clone) {
1656         errln("%s:%d DateIntervalFormat and clone are not equal after formatting.", __FILE__, __LINE__);
1657         return;
1658     }
1659     if (U_FAILURE(status)) {
1660         errln("%s:%d %s", __FILE__, __LINE__, u_errorName(status));
1661     }
1662 }
1663 
1664 
testFormattedDateInterval()1665 void DateIntervalFormatTest::testFormattedDateInterval() {
1666     IcuTestErrorCode status(*this, "testFormattedDateInterval");
1667     LocalPointer<DateIntervalFormat> fmt(DateIntervalFormat::createInstance(u"dMMMMy", "en-US", status), status);
1668 
1669     {
1670         const char16_t* message = u"FormattedDateInterval test 1";
1671         const char16_t* expectedString = u"July 20 \u2013 25, 2018";
1672         LocalPointer<Calendar> input1(Calendar::createInstance("en-GB", status));
1673         if (status.errIfFailureAndReset()) { return; }
1674         LocalPointer<Calendar> input2(Calendar::createInstance("en-GB", status));
1675         if (status.errIfFailureAndReset()) { return; }
1676         input1->set(2018, 6, 20);
1677         input2->set(2018, 6, 25);
1678         FormattedDateInterval result = fmt->formatToValue(*input1, *input2, status);
1679         static const UFieldPositionWithCategory expectedFieldPositions[] = {
1680             // field, begin index, end index
1681             {UFIELD_CATEGORY_DATE, UDAT_MONTH_FIELD, 0, 4},
1682             {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 0, 5, 7},
1683             {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 5, 7},
1684             {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 1, 10, 12},
1685             {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 10, 12},
1686             {UFIELD_CATEGORY_DATE, UDAT_YEAR_FIELD, 14, 18}};
1687         checkMixedFormattedValue(
1688             message,
1689             result,
1690             expectedString,
1691             expectedFieldPositions,
1692             UPRV_LENGTHOF(expectedFieldPositions));
1693     }
1694 
1695     {
1696         const char16_t* message = u"FormattedDateInterval identical dates test: no span field";
1697         const char16_t* expectedString = u"July 20, 2018";
1698         LocalPointer<Calendar> input1(Calendar::createInstance("en-GB", status));
1699         input1->set(2018, 6, 20);
1700         FormattedDateInterval result = fmt->formatToValue(*input1, *input1, status);
1701         static const UFieldPositionWithCategory expectedFieldPositions[] = {
1702             // field, begin index, end index
1703             {UFIELD_CATEGORY_DATE, UDAT_MONTH_FIELD, 0, 4},
1704             {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 5, 7},
1705             {UFIELD_CATEGORY_DATE, UDAT_YEAR_FIELD, 9, 13}};
1706         checkMixedFormattedValue(
1707             message,
1708             result,
1709             expectedString,
1710             expectedFieldPositions,
1711             UPRV_LENGTHOF(expectedFieldPositions));
1712     }
1713 
1714     // Test sample code
1715     {
1716         LocalPointer<Calendar> input1(Calendar::createInstance("en-GB", status));
1717         LocalPointer<Calendar> input2(Calendar::createInstance("en-GB", status));
1718         input1->set(2018, 6, 20);
1719         input2->set(2018, 7, 3);
1720 
1721         // Let fmt be a DateIntervalFormat for locale en-US and skeleton dMMMMy
1722         // Let input1 be July 20, 2018 and input2 be August 3, 2018:
1723         FormattedDateInterval result = fmt->formatToValue(*input1, *input2, status);
1724         assertEquals("Expected output from format",
1725             u"July 20 \u2013 August 3, 2018", result.toString(status));
1726         ConstrainedFieldPosition cfpos;
1727         cfpos.constrainField(UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 0);
1728         if (result.nextPosition(cfpos, status)) {
1729             assertEquals("Expect start index", 0, cfpos.getStart());
1730             assertEquals("Expect end index", 7, cfpos.getLimit());
1731         } else {
1732             // No such span: can happen if input dates are equal.
1733         }
1734         assertFalse("No more than one occurrence of the field",
1735             result.nextPosition(cfpos, status));
1736     }
1737 
1738     // To test the fallback pattern behavior, make a custom DateIntervalInfo.
1739     DateIntervalInfo dtitvinf(status);
1740     dtitvinf.setFallbackIntervalPattern("<< {1} --- {0} >>", status);
1741     fmt.adoptInsteadAndCheckErrorCode(
1742         DateIntervalFormat::createInstance(u"dMMMMy", "en-US", dtitvinf, status),
1743         status);
1744 
1745     {
1746         const char16_t* message = u"FormattedDateInterval with fallback format test 1";
1747         const char16_t* expectedString = u"<< July 25, 2018 --- July 20, 2018 >>";
1748         LocalPointer<Calendar> input1(Calendar::createInstance("en-GB", status));
1749         if (status.errIfFailureAndReset()) { return; }
1750         LocalPointer<Calendar> input2(Calendar::createInstance("en-GB", status));
1751         if (status.errIfFailureAndReset()) { return; }
1752         input1->set(2018, 6, 20);
1753         input2->set(2018, 6, 25);
1754         FormattedDateInterval result = fmt->formatToValue(*input1, *input2, status);
1755         static const UFieldPositionWithCategory expectedFieldPositions[] = {
1756             // field, begin index, end index
1757             {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 1, 3, 16},
1758             {UFIELD_CATEGORY_DATE, UDAT_MONTH_FIELD, 3, 7},
1759             {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 8, 10},
1760             {UFIELD_CATEGORY_DATE, UDAT_YEAR_FIELD, 12, 16},
1761             {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 0, 21, 34},
1762             {UFIELD_CATEGORY_DATE, UDAT_MONTH_FIELD, 21, 25},
1763             {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 26, 28},
1764             {UFIELD_CATEGORY_DATE, UDAT_YEAR_FIELD, 30, 34}};
1765         checkMixedFormattedValue(
1766             message,
1767             result,
1768             expectedString,
1769             expectedFieldPositions,
1770             UPRV_LENGTHOF(expectedFieldPositions));
1771     }
1772 }
1773 
testCreateInstanceForAllLocales()1774 void DateIntervalFormatTest::testCreateInstanceForAllLocales() {
1775     IcuTestErrorCode status(*this, "testCreateInstanceForAllLocales");
1776     int32_t locale_count = 0;
1777     const Locale* locales = icu::Locale::getAvailableLocales(locale_count);
1778     // Iterate through all locales
1779     for (int32_t i = 0; i < locale_count; i++) {
1780         std::unique_ptr<icu::StringEnumeration> calendars(
1781             icu::Calendar::getKeywordValuesForLocale(
1782                 "calendar", locales[i], FALSE, status));
1783         int32_t calendar_count = calendars->count(status);
1784         if (status.errIfFailureAndReset()) { break; }
1785         // In quick mode, only run 1/5 of locale combination
1786         // to make the test run faster.
1787         if (quick && (i % 5 != 0)) continue;
1788         LocalPointer<DateIntervalFormat> fmt(
1789             DateIntervalFormat::createInstance(u"dMMMMy", locales[i], status),
1790             status);
1791         if (status.errIfFailureAndReset(locales[i].getName())) {
1792             continue;
1793         }
1794         // Iterate through all calendars in this locale
1795         for (int32_t j = 0; j < calendar_count; j++) {
1796             // In quick mode, only run 1/7 of locale/calendar combination
1797             // to make the test run faster.
1798             if (quick && ((i * j) % 7 != 0)) continue;
1799             const char* calendar = calendars->next(nullptr, status);
1800             Locale locale(locales[i]);
1801             locale.setKeywordValue("calendar", calendar, status);
1802             fmt.adoptInsteadAndCheckErrorCode(
1803                 DateIntervalFormat::createInstance(u"dMMMMy", locale, status),
1804                 status);
1805             status.errIfFailureAndReset(locales[i].getName());
1806         }
1807     }
1808 }
1809 
testFormatMillisecond()1810 void DateIntervalFormatTest::testFormatMillisecond() {
1811     struct
1812     {
1813         int year;
1814         int month;
1815         int day;
1816         int from_hour;
1817         int from_miniute;
1818         int from_second;
1819         int from_millisecond;
1820         int to_hour;
1821         int to_miniute;
1822         int to_second;
1823         int to_millisecond;
1824         const char* skeleton;
1825         const char16_t* expected;
1826     }
1827     kTestCases [] =
1828     {
1829         //           From            To
1830         //   y  m  d   h  m   s   ms   h  m   s   ms   skeleton  expected
1831         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 321, "ms",     u"23:45"},
1832         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 321, "msS",    u"23:45.3"},
1833         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 321, "msSS",   u"23:45.32"},
1834         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 321, "msSSS",  u"23:45.321"},
1835         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 987, "ms",     u"23:45"},
1836         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 987, "msS",    u"23:45.3 \u2013 23:45.9"},
1837         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 987, "msSS",   u"23:45.32 \u2013 23:45.98"},
1838         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 987, "msSSS",  u"23:45.321 \u2013 23:45.987"},
1839         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 987, "ms",     u"23:45 \u2013 23:46"},
1840         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 987, "msS",    u"23:45.3 \u2013 23:46.9"},
1841         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 987, "msSS",   u"23:45.32 \u2013 23:46.98"},
1842         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 987, "msSSS",  u"23:45.321 \u2013 23:46.987"},
1843         { 2019, 2, 10, 1, 23, 45, 321, 2, 24, 45, 987, "ms",     u"23:45 \u2013 24:45"},
1844         { 2019, 2, 10, 1, 23, 45, 321, 2, 24, 45, 987, "msS",    u"23:45.3 \u2013 24:45.9"},
1845         { 2019, 2, 10, 1, 23, 45, 321, 2, 24, 45, 987, "msSS",   u"23:45.32 \u2013 24:45.98"},
1846         { 2019, 2, 10, 1, 23, 45, 321, 2, 24, 45, 987, "msSSS",  u"23:45.321 \u2013 24:45.987"},
1847         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 321, "s",      u"45"},
1848         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 321, "sS",     u"45.3"},
1849         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 321, "sSS",    u"45.32"},
1850         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 321, "sSSS",   u"45.321"},
1851         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 987, "s",      u"45"},
1852         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 987, "sS",     u"45.3 \u2013 45.9"},
1853         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 987, "sSS",    u"45.32 \u2013 45.98"},
1854         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 987, "sSSS",   u"45.321 \u2013 45.987"},
1855         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 987, "s",      u"45 \u2013 46"},
1856         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 987, "sS",     u"45.3 \u2013 46.9"},
1857         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 987, "sSS",    u"45.32 \u2013 46.98"},
1858         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 987, "sSSS",   u"45.321 \u2013 46.987"},
1859         { 2019, 2, 10, 1, 23, 45, 321, 2, 24, 45, 987, "s",      u"45 \u2013 45"},
1860         { 2019, 2, 10, 1, 23, 45, 321, 2, 24, 45, 987, "sS",     u"45.3 \u2013 45.9"},
1861         { 2019, 2, 10, 1, 23, 45, 321, 2, 24, 45, 987, "sSS",    u"45.32 \u2013 45.98"},
1862         { 2019, 2, 10, 1, 23, 45, 321, 2, 24, 45, 987, "sSSS",   u"45.321 \u2013 45.987"},
1863         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 321, "S",      u"3"},
1864         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 321, "SS",     u"32"},
1865         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 321, "SSS",    u"321"},
1866 
1867         // Same millisecond but in different second.
1868         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 321, "S",      u"3 \u2013 3"},
1869         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 321, "SS",     u"32 \u2013 32"},
1870         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 321, "SSS",    u"321 \u2013 321"},
1871 
1872         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 987, "S",      u"3 \u2013 9"},
1873         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 987, "SS",     u"32 \u2013 98"},
1874         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 987, "SSS",    u"321 \u2013 987"},
1875         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 987, "S",      u"3 \u2013 9"},
1876         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 987, "SS",     u"32 \u2013 98"},
1877         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 987, "SSS",    u"321 \u2013 987"},
1878         { 2019, 2, 10, 1, 23, 45, 321, 2, 24, 45, 987, "S",      u"3 \u2013 9"},
1879         { 2019, 2, 10, 1, 23, 45, 321, 2, 24, 45, 987, "SS",     u"32 \u2013 98"},
1880         { 2019, 2, 10, 1, 23, 45, 321, 2, 24, 45, 987, "SSS",    u"321 \u2013 987"},
1881         { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr, nullptr},
1882     };
1883 
1884     const Locale &enLocale = Locale::getEnglish();
1885     IcuTestErrorCode status(*this, "testFormatMillisecond");
1886     LocalPointer<Calendar> calendar(Calendar::createInstance(enLocale, status));
1887     if (status.errIfFailureAndReset()) { return; }
1888 
1889     for (int32_t i = 0; kTestCases[i].year > 0; i++) {
1890         LocalPointer<DateIntervalFormat> fmt(DateIntervalFormat::createInstance(
1891             kTestCases[i].skeleton, enLocale, status));
1892         if (status.errIfFailureAndReset()) { continue; }
1893 
1894         calendar->clear();
1895         calendar->set(kTestCases[i].year, kTestCases[i].month, kTestCases[i].day,
1896                       kTestCases[i].from_hour, kTestCases[i].from_miniute, kTestCases[i].from_second);
1897         UDate from = calendar->getTime(status) + kTestCases[i].from_millisecond;
1898         if (status.errIfFailureAndReset()) { continue; }
1899 
1900         calendar->clear();
1901         calendar->set(kTestCases[i].year, kTestCases[i].month, kTestCases[i].day,
1902                       kTestCases[i].to_hour, kTestCases[i].to_miniute, kTestCases[i].to_second);
1903         UDate to = calendar->getTime(status) + kTestCases[i].to_millisecond;
1904         FormattedDateInterval  res = fmt->formatToValue(DateInterval(from, to), status);
1905         if (status.errIfFailureAndReset()) { continue; }
1906 
1907         UnicodeString formatted = res.toString(status);
1908         if (status.errIfFailureAndReset()) { continue; }
1909         if (formatted != kTestCases[i].expected) {
1910             std::string tmp1;
1911             std::string tmp2;
1912             errln("Case %d for skeleton %s : Got %s but expect %s",
1913                   i, kTestCases[i].skeleton, formatted.toUTF8String<std::string>(tmp1).c_str(),
1914                   UnicodeString(kTestCases[i].expected).toUTF8String<std::string>(tmp2).c_str());
1915         }
1916     }
1917 }
1918 
testTicket20707()1919 void DateIntervalFormatTest::testTicket20707() {
1920     IcuTestErrorCode status(*this, "testTicket20707");
1921 
1922     const char16_t timeZone[] = u"UTC";
1923     Locale locales[] = {"en-u-hc-h24", "en-u-hc-h23", "en-u-hc-h12", "en-u-hc-h11", "en", "en-u-hc-h25", "hi-IN-u-hc-h11"};
1924 
1925     // Clomuns: hh, HH, kk, KK, jj, JJs, CC
1926     UnicodeString expected[][7] = {
1927         // Hour-cycle: k
1928         {u"12 AM", u"24", u"24", u"12 AM", u"24", u"0 (hour: 24)", u"12 AM"},
1929         // Hour-cycle: H
1930         {u"12 AM", u"00", u"00", u"12 AM", u"00", u"0 (hour: 00)", u"12 AM"},
1931         // Hour-cycle: h
1932         {u"12 AM", u"00", u"00", u"12 AM", u"12 AM", u"0 (hour: 12)", u"12 AM"},
1933         // Hour-cycle: K
1934         {u"0 AM", u"00", u"00", u"0 AM", u"0 AM", u"0 (hour: 00)", u"0 AM"},
1935         {u"12 AM", u"00", u"00", u"12 AM", u"12 AM", u"0 (hour: 12)", u"12 AM"},
1936         {u"12 AM", u"00", u"00", u"12 AM", u"12 AM", u"0 (hour: 12)", u"12 AM"},
1937         // Hour-cycle: K
1938         {u"0 am", u"00", u"00", u"0 am", u"0 am", u"0 (\u0918\u0902\u091F\u093E: 00)", u"\u0930\u093E\u0924 0"}
1939     };
1940 
1941     int32_t i = 0;
1942     for (Locale locale : locales) {
1943         int32_t j = 0;
1944         for (const UnicodeString skeleton : {u"hh", u"HH", u"kk", u"KK", u"jj", u"JJs", u"CC"}) {
1945             LocalPointer<DateIntervalFormat> dtifmt(DateIntervalFormat::createInstance(skeleton, locale, status));
1946             if (status.errDataIfFailureAndReset()) {
1947                 continue;
1948             }
1949             FieldPosition fposition;
1950             UnicodeString result;
1951             LocalPointer<Calendar> calendar(Calendar::createInstance(TimeZone::createTimeZone(timeZone), status));
1952             calendar->setTime(UDate(1563235200000), status);
1953             dtifmt->format(*calendar, *calendar, result, fposition, status);
1954 
1955             assertEquals("Formatted result", expected[i][j++], result);
1956         }
1957         i++;
1958     }
1959 }
1960 
1961 #endif /* #if !UCONFIG_NO_FORMATTING */
1962