• 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     TESTCASE_AUTO_BEGIN;
49     TESTCASE_AUTO(testAPI);
50     TESTCASE_AUTO(testFormat);
51     TESTCASE_AUTO(testFormatUserDII);
52     TESTCASE_AUTO(testSetIntervalPatternNoSideEffect);
53     TESTCASE_AUTO(testYearFormats);
54     TESTCASE_AUTO(testStress);
55     TESTCASE_AUTO(testTicket11583_2);
56     TESTCASE_AUTO(testTicket11985);
57     TESTCASE_AUTO(testTicket11669);
58     TESTCASE_AUTO(testTicket12065);
59     TESTCASE_AUTO(testFormattedDateInterval);
60     TESTCASE_AUTO(testCreateInstanceForAllLocales);
61     TESTCASE_AUTO(testTicket20707);
62     TESTCASE_AUTO(testFormatMillisecond);
63     TESTCASE_AUTO(testHourMetacharacters);
64     TESTCASE_AUTO(testContext);
65     TESTCASE_AUTO(testTicket21222GregorianEraDiff);
66     TESTCASE_AUTO(testTicket21222ROCEraDiff);
67     TESTCASE_AUTO(testTicket21222JapaneseEraDiff);
68     TESTCASE_AUTO(testTicket21939);
69     TESTCASE_AUTO(testTicket20710_FieldIdentity);
70     TESTCASE_AUTO(testTicket20710_IntervalIdentity);
71     TESTCASE_AUTO_END;
72 }
73 
74 /**
75  * Test various generic API methods of DateIntervalFormat for API coverage.
76  */
testAPI()77 void DateIntervalFormatTest::testAPI() {
78 
79     /* ====== Test create interval instance with default locale and skeleton
80      */
81     UErrorCode status = U_ZERO_ERROR;
82     logln("Testing DateIntervalFormat create instance with default locale and skeleton");
83 
84     DateIntervalFormat* dtitvfmt = DateIntervalFormat::createInstance(UDAT_YEAR_MONTH_DAY, status);
85     if(U_FAILURE(status)) {
86         dataerrln("ERROR: Could not create DateIntervalFormat (skeleton + default locale) - exiting");
87         return;
88     } else {
89         delete dtitvfmt;
90     }
91 
92 
93     /* ====== Test create interval instance with given locale and skeleton
94      */
95     status = U_ZERO_ERROR;
96     logln("Testing DateIntervalFormat create instance with given locale and skeleton");
97 
98     dtitvfmt = DateIntervalFormat::createInstance(UDAT_YEAR_MONTH_DAY, Locale::getJapanese(), status);
99     if(U_FAILURE(status)) {
100         dataerrln("ERROR: Could not create DateIntervalFormat (skeleton + locale) - exiting");
101         return;
102     } else {
103         delete dtitvfmt;
104     }
105 
106 
107     /* ====== Test create interval instance with dateIntervalInfo and skeleton
108      */
109     status = U_ZERO_ERROR;
110     logln("Testing DateIntervalFormat create instance with dateIntervalInfo  and skeleton");
111 
112     DateIntervalInfo* dtitvinf = new DateIntervalInfo(Locale::getSimplifiedChinese(), status);
113 
114     dtitvfmt = DateIntervalFormat::createInstance("EEEdMMMyhms", *dtitvinf, status);
115     delete dtitvinf;
116 
117     if(U_FAILURE(status)) {
118         dataerrln("ERROR: Could not create DateIntervalFormat (skeleton + DateIntervalInfo + default locale) - exiting");
119         return;
120     } else {
121         delete dtitvfmt;
122     }
123 
124 
125     /* ====== Test create interval instance with dateIntervalInfo and skeleton
126      */
127     status = U_ZERO_ERROR;
128     logln("Testing DateIntervalFormat create instance with dateIntervalInfo  and skeleton");
129 
130     dtitvinf = new DateIntervalInfo(Locale::getSimplifiedChinese(), status);
131 
132     dtitvfmt = DateIntervalFormat::createInstance("EEEdMMMyhms", Locale::getSimplifiedChinese(), *dtitvinf, status);
133     delete dtitvinf;
134     if(U_FAILURE(status)) {
135         dataerrln("ERROR: Could not create DateIntervalFormat (skeleton + DateIntervalInfo + locale) - exiting");
136         return;
137     }
138     // not deleted, test clone
139 
140 
141     // ====== Test clone()
142     status = U_ZERO_ERROR;
143     logln("Testing DateIntervalFormat clone");
144 
145     DateIntervalFormat* another = dtitvfmt->clone();
146     if ( (*another) != (*dtitvfmt) ) {
147         dataerrln("%s:%d ERROR: clone failed", __FILE__, __LINE__);
148     }
149 
150 
151     // ====== Test getDateIntervalInfo, setDateIntervalInfo, adoptDateIntervalInfo
152     status = U_ZERO_ERROR;
153     logln("Testing DateIntervalFormat getDateIntervalInfo");
154     const DateIntervalInfo* inf = another->getDateIntervalInfo();
155     dtitvfmt->setDateIntervalInfo(*inf, status);
156     const DateIntervalInfo* anotherInf = dtitvfmt->getDateIntervalInfo();
157     if ( (*inf) != (*anotherInf) || U_FAILURE(status) ) {
158         dataerrln("ERROR: getDateIntervalInfo/setDateIntervalInfo failed");
159     }
160 
161     {
162         // We make sure that setDateIntervalInfo does not corrupt the cache. See ticket 9919.
163         status = U_ZERO_ERROR;
164         logln("Testing DateIntervalFormat setDateIntervalInfo");
165         const Locale &enLocale = Locale::getEnglish();
166         LocalPointer<DateIntervalFormat> dif(DateIntervalFormat::createInstance("yMd", enLocale, status));
167         if (U_FAILURE(status)) {
168             errln("Failure encountered: %s", u_errorName(status));
169             return;
170         }
171         UnicodeString expected;
172         LocalPointer<Calendar> fromTime(Calendar::createInstance(enLocale, status));
173         LocalPointer<Calendar> toTime(Calendar::createInstance(enLocale, status));
174         if (U_FAILURE(status)) {
175             errln("Failure encountered: %s", u_errorName(status));
176             return;
177         }
178         FieldPosition pos(FieldPosition::DONT_CARE);
179         fromTime->set(2013, 3, 26);
180         toTime->set(2013, 3, 28);
181         dif->format(*fromTime, *toTime, expected, pos, status);
182         if (U_FAILURE(status)) {
183             errln("Failure encountered: %s", u_errorName(status));
184             return;
185         }
186         LocalPointer<DateIntervalInfo> dii(new DateIntervalInfo(Locale::getEnglish(), status), status);
187         if (U_FAILURE(status)) {
188             errln("Failure encountered: %s", u_errorName(status));
189             return;
190         }
191         dii->setIntervalPattern(ctou("yMd"), UCAL_DATE, ctou("M/d/y \\u2013 d"), status);
192         dif->setDateIntervalInfo(*dii, status);
193         if (U_FAILURE(status)) {
194             errln("Failure encountered: %s", u_errorName(status));
195             return;
196         }
197         dif.adoptInstead(DateIntervalFormat::createInstance("yMd", enLocale, status));
198         if (U_FAILURE(status)) {
199             errln("Failure encountered: %s", u_errorName(status));
200             return;
201         }
202         UnicodeString actual;
203         pos = 0;
204         dif->format(*fromTime, *toTime, actual, pos, status);
205         if (U_FAILURE(status)) {
206             errln("Failure encountered: %s", u_errorName(status));
207             return;
208         }
209         if (expected != actual) {
210             errln("DateIntervalFormat.setIntervalInfo should have no side effects.");
211         }
212     }
213 
214     /*
215     status = U_ZERO_ERROR;
216     DateIntervalInfo* nonConstInf = inf->clone();
217     dtitvfmt->adoptDateIntervalInfo(nonConstInf, status);
218     anotherInf = dtitvfmt->getDateIntervalInfo();
219     if ( (*inf) != (*anotherInf) || U_FAILURE(status) ) {
220         dataerrln("ERROR: adoptDateIntervalInfo failed");
221     }
222     */
223 
224     // ====== Test getDateFormat, setDateFormat, adoptDateFormat
225 
226     status = U_ZERO_ERROR;
227     logln("Testing DateIntervalFormat getDateFormat");
228     /*
229     const DateFormat* fmt = another->getDateFormat();
230     dtitvfmt->setDateFormat(*fmt, status);
231     const DateFormat* anotherFmt = dtitvfmt->getDateFormat();
232     if ( (*fmt) != (*anotherFmt) || U_FAILURE(status) ) {
233         dataerrln("ERROR: getDateFormat/setDateFormat failed");
234     }
235 
236     status = U_ZERO_ERROR;
237     DateFormat* nonConstFmt = fmt->clone();
238     dtitvfmt->adoptDateFormat(nonConstFmt, status);
239     anotherFmt = dtitvfmt->getDateFormat();
240     if ( (*fmt) != (*anotherFmt) || U_FAILURE(status) ) {
241         dataerrln("ERROR: adoptDateFormat failed");
242     }
243     delete fmt;
244     */
245 
246 
247     // ======= Test getStaticClassID()
248 
249     logln("Testing getStaticClassID()");
250 
251 
252     if(dtitvfmt->getDynamicClassID() != DateIntervalFormat::getStaticClassID()) {
253         errln("ERROR: getDynamicClassID() didn't return the expected value");
254     }
255 
256     delete another;
257 
258     // ====== test constructor/copy constructor and assignment
259     /* they are protected, no test
260     logln("Testing DateIntervalFormat constructor and assignment operator");
261     status = U_ZERO_ERROR;
262 
263     DateFormat* constFmt = dtitvfmt->getDateFormat()->clone();
264     inf = dtitvfmt->getDateIntervalInfo()->clone();
265 
266 
267     DateIntervalFormat* dtifmt = new DateIntervalFormat(fmt, inf, status);
268     if(U_FAILURE(status)) {
269         dataerrln("ERROR: Could not create DateIntervalFormat (default) - exiting");
270         return;
271     }
272 
273     DateIntervalFormat* dtifmt2 = new(dtifmt);
274     if ( (*dtifmt) != (*dtifmt2) ) {
275         dataerrln("ERROR: Could not create DateIntervalFormat (default) - exiting");
276         return;
277     }
278 
279     DateIntervalFormat dtifmt3 = (*dtifmt);
280     if ( (*dtifmt) != dtifmt3 ) {
281         dataerrln("ERROR: Could not create DateIntervalFormat (default) - exiting");
282         return;
283     }
284 
285     delete dtifmt2;
286     delete dtifmt3;
287     delete dtifmt;
288     */
289 
290 
291     //===== test format and parse ==================
292     Formattable formattable;
293     formattable.setInt64(10);
294     UnicodeString res;
295     FieldPosition pos(FieldPosition::DONT_CARE);
296     status = U_ZERO_ERROR;
297     dtitvfmt->format(formattable, res, pos, status);
298     if ( status != U_ILLEGAL_ARGUMENT_ERROR ) {
299         dataerrln("ERROR: format non-date-interval object should set U_ILLEGAL_ARGUMENT_ERROR - exiting");
300         return;
301     }
302 
303     DateInterval* dtitv = new DateInterval(3600*24*365, 3600*24*366);
304     formattable.adoptObject(dtitv);
305     res.remove();
306     pos = 0;
307     status = U_ZERO_ERROR;
308     dtitvfmt->format(formattable, res, pos, status);
309     if ( U_FAILURE(status) ) {
310         dataerrln("ERROR: format date interval failed - exiting");
311         return;
312     }
313 
314     const DateFormat* dfmt = dtitvfmt->getDateFormat();
315     Calendar* fromCal = dfmt->getCalendar()->clone();
316     Calendar* toCal = dfmt->getCalendar()->clone();
317     res.remove();
318     pos = 0;
319     status = U_ZERO_ERROR;
320     dtitvfmt->format(*fromCal, *toCal, res, pos, status);
321     if ( U_FAILURE(status) ) {
322         dataerrln("ERROR: format date interval failed - exiting");
323         return;
324     }
325     delete fromCal;
326     delete toCal;
327 
328 
329     Formattable fmttable;
330     status = U_ZERO_ERROR;
331     // TODO: why do I need cast?
332     (dynamic_cast<Format*>(dtitvfmt))->parseObject(res, fmttable, status);
333     if ( status != U_INVALID_FORMAT_ERROR ) {
334         dataerrln("ERROR: parse should set U_INVALID_FORMAT_ERROR - exiting");
335         return;
336     }
337 
338     delete dtitvfmt;
339 
340     //====== test setting time zone
341     logln("Testing DateIntervalFormat set & format with different time zones, get time zone");
342     status = U_ZERO_ERROR;
343     dtitvfmt = DateIntervalFormat::createInstance("MMMdHHmm", Locale::getEnglish(), status);
344     if ( U_SUCCESS(status) ) {
345         UDate date1 = 1299090600000.0; // 2011-Mar-02 1030 in US/Pacific, 2011-Mar-03 0330 in Asia/Tokyo
346         UDate date2 = 1299115800000.0; // 2011-Mar-02 1730 in US/Pacific, 2011-Mar-03 1030 in Asia/Tokyo
347 
348         DateInterval * dtitv12 = new DateInterval(date1, date2);
349         TimeZone * tzCalif = TimeZone::createTimeZone("US/Pacific");
350         TimeZone * tzTokyo = TimeZone::createTimeZone("Asia/Tokyo");
351         UnicodeString fmtCalif = UnicodeString(u"Mar 2, 10:30\u2009\u2013\u200917:30", -1);
352         UnicodeString fmtTokyo = UnicodeString(u"Mar 3, 03:30\u2009\u2013\u200910:30", -1);
353 
354         dtitvfmt->adoptTimeZone(tzCalif);
355         res.remove();
356         pos = 0;
357         status = U_ZERO_ERROR;
358         dtitvfmt->format(dtitv12, res, pos, status);
359         if ( U_SUCCESS(status) ) {
360             if ( res.compare(fmtCalif) != 0 ) {
361                 errln("ERROR: DateIntervalFormat::format for tzCalif, expect " + fmtCalif + ", get " + res);
362             }
363         } else {
364             errln("ERROR: DateIntervalFormat::format for tzCalif, status %s", u_errorName(status));
365         }
366 
367         dtitvfmt->setTimeZone(*tzTokyo);
368         res.remove();
369         pos = 0;
370         status = U_ZERO_ERROR;
371         dtitvfmt->format(dtitv12, res, pos, status);
372         if ( U_SUCCESS(status) ) {
373             if ( res.compare(fmtTokyo) != 0 ) {
374                 errln("ERROR: DateIntervalFormat::format for tzTokyo, expect " + fmtTokyo + ", get " + res);
375             }
376         } else {
377             errln("ERROR: DateIntervalFormat::format for tzTokyo, status %s", u_errorName(status));
378         }
379 
380         if ( dtitvfmt->getTimeZone() != *tzTokyo ) {
381             errln("ERROR: DateIntervalFormat::getTimeZone returns mismatch.");
382         }
383 
384         delete tzTokyo; // tzCalif was owned by dtitvfmt which should have deleted it
385         delete dtitv12;
386         delete dtitvfmt;
387     } else {
388         errln("ERROR: DateIntervalFormat::createInstance(\"MdHH\", Locale::getEnglish(), ...), status %s", u_errorName(status));
389     }
390     //====== test format  in testFormat()
391 
392     //====== test DateInterval class (better coverage)
393     DateInterval dtitv1(3600*24*365, 3600*24*366);
394     DateInterval dtitv2(dtitv1);
395 
396     if (!(dtitv1 == dtitv2)) {
397         errln("ERROR: Copy constructor failed for DateInterval.");
398     }
399 
400     DateInterval dtitv3(3600*365, 3600*366);
401     dtitv3 = dtitv1;
402     if (!(dtitv3 == dtitv1)) {
403         errln("ERROR: Equal operator failed for DateInterval.");
404     }
405 
406     DateInterval *dtitv4 = dtitv1.clone();
407     if (*dtitv4 != dtitv1) {
408         errln("ERROR: Equal operator failed for DateInterval.");
409     }
410     delete dtitv4;
411 }
412 
413 
414 /**
415  * Test format
416  */
testFormat()417 void DateIntervalFormatTest::testFormat() {
418     // first item is date pattern
419     // followed by a group of locale/from_data/to_data/skeleton/interval_data
420     // Note that from_data/to_data are specified using era names from root, for the calendar specified by locale.
421     const char* DATA[] = {
422         "GGGGG y MM dd HH:mm:ss", // pattern for from_data/to_data
423         // test root
424         "root", "CE 2007 11 10 10:10:10", "CE 2007 12 10 10:10:10", "yM", "2007-11 \\u2013 2007-12",
425 
426         // test 'H' and 'h', using availableFormat in fallback
427         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 10 15:10:10", "Hms", "10:10:10\\u2009\\u2013\\u200915:10:10",
428         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 10 15:10:10", "hms", "10:10:10\\u202FAM\\u2009\\u2013\\u20093:10:10\\u202FPM",
429 
430         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "MMMM", "October 2007\\u2009\\u2013\\u2009October 2008",
431         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "MMM", "Oct 2007\\u2009\\u2013\\u2009Oct 2008",
432         // test skeleton with both date and time
433         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dMMMyhm", "Nov 10, 2007, 10:10\\u202FAM\\u2009\\u2013\\u2009Nov 20, 2007, 10:10\\u202FAM",
434 
435         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 10 11:10:10", "dMMMyhm", "Nov 10, 2007, 10:10\\u2009\\u2013\\u200911:10\\u202FAM",
436 
437         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 10 11:10:10", "hms", "10:10:10\\u202FAM\\u2009\\u2013\\u200911:10:10\\u202FAM",
438         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 10 11:10:10", "Hms", "10:10:10\\u2009\\u2013\\u200911:10:10",
439         "en", "CE 2007 11 10 20:10:10", "CE 2007 11 10 21:10:10", "Hms", "20:10:10\\u2009\\u2013\\u200921:10:10",
440 
441         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EEEEdMMMMy", "Wednesday, October 10, 2007\\u2009\\u2013\\u2009Friday, October 10, 2008",
442 
443         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "dMMMMy", "October 10, 2007\\u2009\\u2013\\u2009October 10, 2008",
444 
445         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "dMMMM", "October 10, 2007\\u2009\\u2013\\u2009October 10, 2008",
446 
447         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "MMMMy", "October 2007\\u2009\\u2013\\u2009October 2008",
448 
449         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EEEEdMMMM", "Wednesday, October 10, 2007\\u2009\\u2013\\u2009Friday, October 10, 2008",
450 
451         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EdMMMy", "Wed, Oct 10, 2007\\u2009\\u2013\\u2009Fri, Oct 10, 2008",
452 
453         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "dMMMy", "Oct 10, 2007\\u2009\\u2013\\u2009Oct 10, 2008",
454 
455         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "dMMM", "Oct 10, 2007\\u2009\\u2013\\u2009Oct 10, 2008",
456 
457         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "MMMy", "Oct 2007\\u2009\\u2013\\u2009Oct 2008",
458 
459         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EdMMM", "Wed, Oct 10, 2007\\u2009\\u2013\\u2009Fri, Oct 10, 2008",
460 
461         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EdMy", "Wed, 10/10/2007\\u2009\\u2013\\u2009Fri, 10/10/2008",
462 
463         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "dMy", "10/10/2007\\u2009\\u2013\\u200910/10/2008",
464 
465         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "dM", "10/10/2007\\u2009\\u2013\\u200910/10/2008",
466 
467         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "My", "10/2007\\u2009\\u2013\\u200910/2008",
468 
469         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EdM", "Wed, 10/10/2007\\u2009\\u2013\\u2009Fri, 10/10/2008",
470 
471         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "d", "10/10/2007\\u2009\\u2013\\u200910/10/2008",
472 
473         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "Ed", "10 Wed\\u2009\\u2013\\u200910 Fri",
474 
475         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "y", "2007\\u2009\\u2013\\u20092008",
476 
477         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "M", "10/2007\\u2009\\u2013\\u200910/2008",
478 
479 
480 
481         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "hm", "10/10/2007, 10:10\\u202FAM\\u2009\\u2013\\u200910/10/2008, 10:10\\u202FAM",
482         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "Hm", "10/10/2007, 10:10\\u2009\\u2013\\u200910/10/2008, 10:10",
483         "en", "CE 2007 10 10 20:10:10", "CE 2008 10 10 20:10:10", "Hm", "10/10/2007, 20:10\\u2009\\u2013\\u200910/10/2008, 20:10",
484 
485         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "hmv", "10/10/2007, 10:10\\u202FAM PT\\u2009\\u2013\\u200910/10/2008, 10:10\\u202FAM PT",
486 
487         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "hmz", "10/10/2007, 10:10\\u202FAM PDT\\u2009\\u2013\\u200910/10/2008, 10:10\\u202FAM PDT",
488 
489         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "h", "10/10/2007, 10\\u202FAM\\u2009\\u2013\\u200910/10/2008, 10\\u202FAM",
490 
491         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "hv", "10/10/2007, 10\\u202FAM PT\\u2009\\u2013\\u200910/10/2008, 10\\u202FAM PT",
492 
493         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "hz", "10/10/2007, 10\\u202FAM PDT\\u2009\\u2013\\u200910/10/2008, 10\\u202FAM PDT",
494 
495         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EEddMMyyyy", "Wed, 10/10/2007\\u2009\\u2013\\u2009Fri, 10/10/2008",
496 
497         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EddMMy", "Wed, 10/10/2007\\u2009\\u2013\\u2009Fri, 10/10/2008",
498 
499         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "hhmm", "10/10/2007, 10:10\\u202FAM\\u2009\\u2013\\u200910/10/2008, 10:10\\u202FAM",
500 
501         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "hhmmzz", "10/10/2007, 10:10\\u202FAM PDT\\u2009\\u2013\\u200910/10/2008, 10:10\\u202FAM PDT",
502 
503         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "hms", "10/10/2007, 10:10:10\\u202FAM\\u2009\\u2013\\u200910/10/2008, 10:10:10\\u202FAM",
504 
505         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "dMMMMMy", "O 10, 2007\\u2009\\u2013\\u2009O 10, 2008",
506 
507         "en", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EEEEEdM", "W, 10/10/2007\\u2009\\u2013\\u2009F, 10/10/2008",
508 
509         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EEEEdMMMMy", "Wednesday, October 10\\u2009\\u2013\\u2009Saturday, November 10, 2007",
510 
511         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "dMMMMy", "October 10\\u2009\\u2013\\u2009November 10, 2007",
512 
513         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "dMMMM", "October 10\\u2009\\u2013\\u2009November 10",
514 
515         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "MMMMy", "October\\u2009\\u2013\\u2009November 2007",
516 
517         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EEEEdMMMM", "Wednesday, October 10\\u2009\\u2013\\u2009Saturday, November 10",
518 
519         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EdMMMy", "Wed, Oct 10\\u2009\\u2013\\u2009Sat, Nov 10, 2007",
520 
521         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "dMMMy", "Oct 10\\u2009\\u2013\\u2009Nov 10, 2007",
522 
523         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "dMMM", "Oct 10\\u2009\\u2013\\u2009Nov 10",
524 
525         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "MMMy", "Oct\\u2009\\u2013\\u2009Nov 2007",
526 
527         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EdMMM", "Wed, Oct 10\\u2009\\u2013\\u2009Sat, Nov 10",
528 
529         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EdMy", "Wed, 10/10/2007\\u2009\\u2013\\u2009Sat, 11/10/2007",
530 
531         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "dMy", "10/10/2007\\u2009\\u2013\\u200911/10/2007",
532 
533 
534         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "My", "10/2007\\u2009\\u2013\\u200911/2007",
535 
536         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EdM", "Wed, 10/10\\u2009\\u2013\\u2009Sat, 11/10",
537 
538         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "d", "10/10\\u2009\\u2013\\u200911/10",
539 
540         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "Ed", "10 Wed\\u2009\\u2013\\u200910 Sat",
541 
542         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "y", "2007",
543 
544         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "M", "10\\u2009\\u2013\\u200911",
545 
546         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "MMM", "Oct\\u2009\\u2013\\u2009Nov",
547 
548         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "MMMM", "October\\u2009\\u2013\\u2009November",
549 
550         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "hm", "10/10/2007, 10:10\\u202FAM\\u2009\\u2013\\u200911/10/2007, 10:10\\u202FAM",
551         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "Hm", "10/10/2007, 10:10\\u2009\\u2013\\u200911/10/2007, 10:10",
552         "en", "CE 2007 10 10 20:10:10", "CE 2007 11 10 20:10:10", "Hm", "10/10/2007, 20:10\\u2009\\u2013\\u200911/10/2007, 20:10",
553 
554         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "hmv", "10/10/2007, 10:10\\u202FAM PT\\u2009\\u2013\\u200911/10/2007, 10:10\\u202FAM PT",
555 
556         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "hmz", "10/10/2007, 10:10\\u202FAM PDT\\u2009\\u2013\\u200911/10/2007, 10:10\\u202FAM PST",
557 
558         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "h", "10/10/2007, 10\\u202FAM\\u2009\\u2013\\u200911/10/2007, 10\\u202FAM",
559 
560         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "hv", "10/10/2007, 10\\u202FAM PT\\u2009\\u2013\\u200911/10/2007, 10\\u202FAM PT",
561 
562         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "hz", "10/10/2007, 10\\u202FAM PDT\\u2009\\u2013\\u200911/10/2007, 10\\u202FAM PST",
563 
564         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EEddMMyyyy", "Wed, 10/10/2007\\u2009\\u2013\\u2009Sat, 11/10/2007",
565 
566         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EddMMy", "Wed, 10/10/2007\\u2009\\u2013\\u2009Sat, 11/10/2007",
567 
568 
569         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "hhmmzz", "10/10/2007, 10:10\\u202FAM PDT\\u2009\\u2013\\u200911/10/2007, 10:10\\u202FAM PST",
570 
571         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "hms", "10/10/2007, 10:10:10\\u202FAM\\u2009\\u2013\\u200911/10/2007, 10:10:10\\u202FAM",
572 
573         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "dMMMMMy", "O 10\\u2009\\u2013\\u2009N 10, 2007",
574 
575         "en", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EEEEEdM", "W, 10/10\\u2009\\u2013\\u2009S, 11/10",
576 
577         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EEEEdMMMMy", "Saturday, November 10\\u2009\\u2013\\u2009Tuesday, November 20, 2007",
578 
579         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dMMMMy", "November 10\\u2009\\u2013\\u200920, 2007",
580 
581         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dMMMM", "November 10\\u2009\\u2013\\u200920",
582 
583 
584         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EEEEdMMMM", "Saturday, November 10\\u2009\\u2013\\u2009Tuesday, November 20",
585 
586         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EdMMMy", "Sat, Nov 10\\u2009\\u2013\\u2009Tue, Nov 20, 2007",
587 
588         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dMMMy", "Nov 10\\u2009\\u2013\\u200920, 2007",
589 
590         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dMMM", "Nov 10\\u2009\\u2013\\u200920",
591 
592         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "MMMy", "Nov 2007",
593 
594         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EdMMM", "Sat, Nov 10\\u2009\\u2013\\u2009Tue, Nov 20",
595 
596         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EdMy", "Sat, 11/10/2007\\u2009\\u2013\\u2009Tue, 11/20/2007",
597 
598         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dMy", "11/10/2007\\u2009\\u2013\\u200911/20/2007",
599 
600         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dM", "11/10\\u2009\\u2013\\u200911/20",
601 
602         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "My", "11/2007",
603 
604         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EdM", "Sat, 11/10\\u2009\\u2013\\u2009Tue, 11/20",
605 
606         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "d", "10\\u2009\\u2013\\u200920",
607 
608         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "Ed", "10 Sat\\u2009\\u2013\\u200920 Tue",
609 
610         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "y", "2007",
611 
612         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "M", "11",
613 
614         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "MMM", "Nov",
615 
616         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "MMMM", "November",
617 
618         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "hm", "11/10/2007, 10:10\\u202FAM\\u2009\\u2013\\u200911/20/2007, 10:10\\u202FAM",
619         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "Hm", "11/10/2007, 10:10\\u2009\\u2013\\u200911/20/2007, 10:10",
620         "en", "CE 2007 11 10 20:10:10", "CE 2007 11 20 20:10:10", "Hm", "11/10/2007, 20:10\\u2009\\u2013\\u200911/20/2007, 20:10",
621 
622         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "hmv", "11/10/2007, 10:10\\u202FAM PT\\u2009\\u2013\\u200911/20/2007, 10:10\\u202FAM PT",
623 
624         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "hmz", "11/10/2007, 10:10\\u202FAM PST\\u2009\\u2013\\u200911/20/2007, 10:10\\u202FAM PST",
625 
626         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "h", "11/10/2007, 10\\u202FAM\\u2009\\u2013\\u200911/20/2007, 10\\u202FAM",
627 
628         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "hv", "11/10/2007, 10\\u202FAM PT\\u2009\\u2013\\u200911/20/2007, 10\\u202FAM PT",
629 
630         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "hz", "11/10/2007, 10\\u202FAM PST\\u2009\\u2013\\u200911/20/2007, 10\\u202FAM PST",
631 
632         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EEddMMyyyy", "Sat, 11/10/2007\\u2009\\u2013\\u2009Tue, 11/20/2007",
633 
634         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EddMMy", "Sat, 11/10/2007\\u2009\\u2013\\u2009Tue, 11/20/2007",
635 
636         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "hhmm", "11/10/2007, 10:10\\u202FAM\\u2009\\u2013\\u200911/20/2007, 10:10\\u202FAM",
637 
638         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "hhmmzz", "11/10/2007, 10:10\\u202FAM PST\\u2009\\u2013\\u200911/20/2007, 10:10\\u202FAM PST",
639 
640         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "hms", "11/10/2007, 10:10:10\\u202FAM\\u2009\\u2013\\u200911/20/2007, 10:10:10\\u202FAM",
641         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "Hms", "11/10/2007, 10:10:10\\u2009\\u2013\\u200911/20/2007, 10:10:10",
642         "en", "CE 2007 11 10 20:10:10", "CE 2007 11 20 20:10:10", "Hms", "11/10/2007, 20:10:10\\u2009\\u2013\\u200911/20/2007, 20:10:10",
643 
644         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dMMMMMy", "N 10\\u2009\\u2013\\u200920, 2007",
645 
646         "en", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EEEEEdM", "S, 11/10\\u2009\\u2013\\u2009T, 11/20",
647 
648         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "EEEEdMMMMy", "Wednesday, January 10, 2007",
649 
650         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "dMMMMy", "January 10, 2007",
651 
652         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "dMMMM", "January 10",
653 
654         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "MMMMy", "January 2007",
655 
656         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "EEEEdMMMM", "Wednesday, January 10",
657 
658         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "EdMMMy", "Wed, Jan 10, 2007",
659 
660         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "dMMMy", "Jan 10, 2007",
661 
662         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "dMMM", "Jan 10",
663 
664         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "MMMy", "Jan 2007",
665 
666         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "EdMMM", "Wed, Jan 10",
667 
668 
669         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "dMy", "1/10/2007",
670 
671         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "dM", "1/10",
672 
673         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "My", "1/2007",
674 
675         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "EdM", "Wed, 1/10",
676 
677         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "d", "10",
678 
679         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "Ed", "10 Wed",
680 
681         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "y", "2007",
682 
683         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "M", "1",
684 
685         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "MMM", "Jan",
686 
687         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "MMMM", "January",
688 
689         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "hm", "10:00\\u202FAM\\u2009\\u2013\\u20092:10\\u202FPM",
690         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "Hm", "10:00\\u2009\\u2013\\u200914:10",
691 
692         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "hmv", "10:00\\u202FAM\\u2009\\u2013\\u20092:10\\u202FPM PT",
693 
694         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "hmz", "10:00\\u202FAM\\u2009\\u2013\\u20092:10\\u202FPM PST",
695 
696         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "h", "10\\u202FAM\\u2009\\u2013\\u20092\\u202FPM",
697         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "H", "10\\u2009\\u2013\\u200914",
698 
699 
700         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "hz", "10\\u202FAM\\u2009\\u2013\\u20092\\u202FPM PST",
701 
702         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "EEddMMyyyy", "Wed, 01/10/2007",
703 
704         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "EddMMy", "Wed, 01/10/2007",
705 
706         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "hhmm", "10:00\\u202FAM\\u2009\\u2013\\u20092:10\\u202FPM",
707         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "HHmm", "10:00\\u2009\\u2013\\u200914:10",
708 
709         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "hhmmzz", "10:00\\u202FAM\\u2009\\u2013\\u20092:10\\u202FPM PST",
710 
711         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "hms", "10:00:10\\u202FAM\\u2009\\u2013\\u20092:10:10\\u202FPM",
712         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "Hms", "10:00:10\\u2009\\u2013\\u200914:10:10",
713 
714         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "dMMMMMy", "J 10, 2007",
715 
716         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "EEEEEdM", "W, 1/10",
717         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "dMMMMy", "January 10, 2007",
718 
719         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "dMMMM", "January 10",
720 
721         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "MMMMy", "January 2007",
722 
723         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "EEEEdMMMM", "Wednesday, January 10",
724 
725         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "EdMMMy", "Wed, Jan 10, 2007",
726 
727         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "dMMMy", "Jan 10, 2007",
728 
729         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "dMMM", "Jan 10",
730 
731 
732         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "EdMMM", "Wed, Jan 10",
733 
734         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "EdMy", "Wed, 1/10/2007",
735 
736         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "dMy", "1/10/2007",
737 
738 
739         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "My", "1/2007",
740 
741         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "EdM", "Wed, 1/10",
742 
743         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "d", "10",
744 
745 
746         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "y", "2007",
747 
748         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "M", "1",
749 
750 
751 
752         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hm", "10:00\\u2009\\u2013\\u200910:20\\u202FAM",
753         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "Hm", "10:00\\u2009\\u2013\\u200910:20",
754 
755 
756         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hmz", "10:00\\u2009\\u2013\\u200910:20\\u202FAM PST",
757 
758 
759         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hv", "10\\u202FAM PT",
760 
761 
762 
763         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "EddMMy", "Wed, 01/10/2007",
764 
765         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hhmm", "10:00\\u2009\\u2013\\u200910:20\\u202FAM",
766         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "HHmm", "10:00\\u2009\\u2013\\u200910:20",
767 
768         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hhmmzz", "10:00\\u2009\\u2013\\u200910:20\\u202FAM PST",
769 
770 
771         "en", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "dMMMMMy", "J 10, 2007",
772 
773 
774         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "EEEEdMMMMy", "Wednesday, January 10, 2007",
775 
776         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "dMMMMy", "January 10, 2007",
777 
778 
779         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "MMMMy", "January 2007",
780 
781         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "EEEEdMMMM", "Wednesday, January 10",
782 
783 
784         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "dMMMy", "Jan 10, 2007",
785 
786         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "dMMM", "Jan 10",
787 
788 
789         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "EdMMM", "Wed, Jan 10",
790 
791         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "EdMy", "Wed, 1/10/2007",
792 
793         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "dMy", "1/10/2007",
794 
795 
796         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "My", "1/2007",
797 
798         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "EdM", "Wed, 1/10",
799 
800         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "d", "10",
801 
802 
803         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "y", "2007",
804 
805         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "M", "1",
806 
807 
808         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "MMMM", "January",
809 
810         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hm", "10:10\\u202FAM",
811         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "Hm", "10:10",
812 
813 
814         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hmz", "10:10\\u202FAM PST",
815 
816         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "h", "10\\u202FAM",
817 
818         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hv", "10\\u202FAM PT",
819 
820 
821         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "EEddMMyyyy", "Wed, 01/10/2007",
822 
823 
824         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hhmm", "10:10\\u202FAM",
825         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "HHmm", "10:10",
826 
827         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hhmmzz", "10:10\\u202FAM PST",
828 
829 
830         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "dMMMMMy", "J 10, 2007",
831 
832         "en", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "EEEEEdM", "W, 1/10",
833 
834         "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",
835 
836 
837         "zh", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "dMMMMy", "2007\\u5e7410\\u670810\\u65e5\\u81f311\\u670810\\u65e5",
838 
839 
840         "zh", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "MMMMy", "2007\\u5e7410\\u6708\\u81f311\\u6708",
841 
842 
843         "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",
844 
845         "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",
846 
847 
848         "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dMMMM", "11\\u670810\\u65e5\\u81f320\\u65e5",
849 
850         "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:)
851 
852         "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",
853 
854 
855         "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",
856 
857 
858         "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dM", "11/10 \\u2013 11/20",
859 
860         "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "My", "2007/11",
861 
862         "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EdM", "11/10\\u5468\\u516d\\u81f311/20\\u5468\\u4e8c",
863 
864 
865         "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "y", "2007\\u5E74", // (fixed expected result per ticket:6626:)
866 
867         "zh", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "M", "11\\u6708",
868 
869         "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)
870 
871 
872         "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",
873 
874         "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",
875 
876         "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:)
877 
878         "zh", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "hm", "\\u4e0a\\u534810:00\\u81f3\\u4e0b\\u53482:10",
879 
880 
881         "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",
882 
883         "zh", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "h", "\\u4e0a\\u534810\\u65F6\\u81f3\\u4e0b\\u53482\\u65f6",
884 
885         "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",
886 
887         "zh", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hm", "\\u4e0a\\u534810:00\\u81f310:20",
888 
889         "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",
890 
891         "zh", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hz", "GMT-8\\u4e0a\\u534810\\u65f6",
892 
893         "zh", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hm", "\\u4e0a\\u534810:10",
894 
895         "zh", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "h", "\\u4e0a\\u534810\\u65f6",
896 
897         "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EEEEdMMMy", "Mittwoch, 10. Okt. 2007\\u2009\\u2013\\u2009Freitag, 10. Okt. 2008",
898 
899 
900         "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "dMMM", "10. Okt. 2007\\u2009\\u2013\\u200910. Okt. 2008",
901 
902         "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "MMMy", "Okt. 2007\\u2009\\u2013\\u2009Okt. 2008",
903 
904 
905         "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EdMy", "Mi., 10.10.2007\\u2009\\u2013\\u2009Fr., 10.10.2008",
906 
907         "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "dMy", "10.10.2007\\u2009\\u2013\\u200910.10.2008",
908 
909 
910         "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "My", "10/2007\\u2009\\u2013\\u200910/2008",
911 
912         "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "EdM", "Mi., 10.10.2007\\u2009\\u2013\\u2009Fr., 10.10.2008",
913 
914 
915         "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "y", "2007\\u20132008",
916 
917         "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "M", "10/2007\\u2009\\u2013\\u200910/2008",
918 
919 
920         "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "hm", "10.10.2007, 10:10\\u202FAM\\u2009\\u2013\\u200910.10.2008, 10:10\\u202FAM",
921         "de", "CE 2007 10 10 10:10:10", "CE 2008 10 10 10:10:10", "Hm", "10.10.2007, 10:10\\u2009\\u2013\\u200910.10.2008, 10:10",
922 
923         "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EEEEdMMMy", "Mittwoch, 10. Okt.\\u2009\\u2013\\u2009Samstag, 10. Nov. 2007",
924 
925 
926         "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "dMMM", "10. Okt.\\u2009\\u2013\\u200910. Nov.",
927 
928         "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "MMMy", "Okt.\\u2013Nov. 2007",
929 
930         "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "EEEEdMMM", "Mittwoch, 10. Okt.\\u2009\\u2013\\u2009Samstag, 10. Nov.",
931 
932 
933         "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "dM", "10.10.\\u2009\\u2013\\u200910.11.",
934 
935         "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "My", "10/2007\\u2009\\u2013\\u200911/2007",
936 
937 
938         "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "d", "10.10.\\u2009\\u2013\\u200910.11.",
939 
940         "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "y", "2007",
941 
942 
943         "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "MMM", "Okt.\\u2013Nov.",
944 
945 
946         "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "hms", "10.10.2007, 10:10:10\\u202FAM\\u2009\\u2013\\u200910.11.2007, 10:10:10\\u202FAM",
947         "de", "CE 2007 10 10 10:10:10", "CE 2007 11 10 10:10:10", "Hms", "10.10.2007, 10:10:10\\u2009\\u2013\\u200910.11.2007, 10:10:10",
948 
949         "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EEEEdMMMy", "Samstag, 10.\\u2009\\u2013\\u2009Dienstag, 20. Nov. 2007",
950 
951         "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dMMMy", "10.\\u201320. Nov. 2007",
952 
953 
954         "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "MMMy", "Nov. 2007",
955 
956         "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EEEEdMMM", "Samstag, 10.\\u2009\\u2013\\u2009Dienstag, 20. Nov.",
957 
958         "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "EdMy", "Sa., 10.\\u2009\\u2013\\u2009Di., 20.11.2007",
959 
960 
961         "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "dM", "10.\\u201320.11.",
962 
963         "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "My", "11/2007",
964 
965 
966         "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "d", "10.\\u201320.",
967 
968         "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "y", "2007",
969 
970 
971         "de", "CE 2007 11 10 10:10:10", "CE 2007 11 20 10:10:10", "hmv", "10.11.2007, 10:10\\u202FAM Los Angeles (Ortszeit)\\u2009\\u2013\\u200920.11.2007, 10:10\\u202FAM Los Angeles (Ortszeit)",
972 
973         "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "EEEEdMMMy", "Mittwoch, 10. Jan. 2007",
974 
975 
976         "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "dMMM", "10. Jan.",
977 
978         "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "MMMy", "Jan. 2007",
979 
980         "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "EEEEdMMM", "Mittwoch, 10. Jan.",
981 
982         /* Following is an important test, because the 'h' in 'Uhr' is interpreted as a pattern
983            if not escaped properly. */
984         "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "h", "10 Uhr AM\\u2009\\u2013\\u20092 Uhr PM",
985         "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 14:10:10", "H", "10\\u201314 Uhr",
986 
987         "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "EEEEdMMM", "Mittwoch, 10. Jan.",
988 
989 
990         "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hmv", "10:00\\u201310:20\\u202FAM Los Angeles (Ortszeit)",
991 
992         "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hmz", "10:00\\u201310:20\\u202FAM GMT-8",
993 
994         "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "h", "10 Uhr AM",
995         "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "H", "10 Uhr",
996 
997 
998         "de", "CE 2007 01 10 10:00:10", "CE 2007 01 10 10:20:10", "hz", "10 Uhr AM GMT-8",
999 
1000         "de", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "EEEEdMMMy", "Mittwoch, 10. Jan. 2007",
1001 
1002 
1003         "de", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hmv", "10:10\\u202FAM Los Angeles (Ortszeit)",
1004 
1005         "de", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hmz", "10:10\\u202FAM GMT-8",
1006 
1007 
1008         "de", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hv", "10 Uhr AM Los Angeles (Ortszeit)",
1009 
1010         "de", "CE 2007 01 10 10:10:10", "CE 2007 01 10 10:10:20", "hz", "10 Uhr AM GMT-8",
1011 
1012         // Thai (default calendar buddhist)
1013 
1014         // BEGIN ANDROID-changed.  Default calendar in Android is Gregorian for th locale.
1015         // "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",
1016 
1017 
1018         // "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",
1019 
1020         // "th", "BE 2550 10 10 10:10:10", "BE 2551 10 10 10:10:10", "MMMy", "\\u0E15.\\u0E04. 2550 \\u2013 \\u0E15.\\u0E04. 2551",
1021 
1022 
1023         // "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",
1024 
1025         // "th", "BE 2550 10 10 10:10:10", "BE 2551 10 10 10:10:10", "dMy", "10/10/2550 \\u2013 10/10/2551",
1026 
1027 
1028         // "th", "BE 2550 10 10 10:10:10", "BE 2551 10 10 10:10:10", "My", "10/2550 \\u2013 10/2551",
1029 
1030         // "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",
1031 
1032 
1033         // "th", "BE 2550 10 10 10:10:10", "BE 2551 10 10 10:10:10", "y", "2550\\u20132551",
1034 
1035         // "th", "BE 2550 10 10 10:10:10", "BE 2551 10 10 10:10:10", "M", "10/2550 \\u2013 10/2551",
1036 
1037 
1038         // "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",
1039 
1040 
1041         // "th", "BE 2550 10 10 10:10:10", "BE 2550 11 10 10:10:10", "dMMM", "10 \\u0E15.\\u0E04. \\u2013 10 \\u0E1E.\\u0E22.",
1042 
1043         // "th", "BE 2550 10 10 10:10:10", "BE 2550 11 10 10:10:10", "MMMy", "\\u0E15.\\u0E04.\\u2013\\u0E1E.\\u0E22. 2550",
1044 
1045         // "th", "2550 10 10 10:10:10", "2550 11 10 10:10:10", "dM", "10/10 \\u2013 10/11",
1046 
1047         // "th", "BE 2550 10 10 10:10:10", "BE 2550 11 10 10:10:10", "My", "10/2550 \\u2013 11/2550",
1048 
1049 
1050         // "th", "BE 2550 10 10 10:10:10", "BE 2550 11 10 10:10:10", "d", "10/10 \\u2013 10/11",
1051 
1052         // "th", "BE 2550 10 10 10:10:10", "BE 2550 11 10 10:10:10", "y", "\\u0E1E.\\u0E28. 2550",
1053 
1054 
1055         // "th", "BE 2550 10 10 10:10:10", "BE 2550 11 10 10:10:10", "MMM", "\\u0E15.\\u0E04.\\u2013\\u0E1E.\\u0E22.",
1056 
1057         // "th", "2550 10 10 10:10:10", "2550 11 10 10:10:10", "y", "\\u0E1E.\\u0E28. 2550",
1058 
1059         // "th", "2550 10 10 10:10:10", "2550 11 10 10:10:10", "MMM", "\\u0E15.\\u0E04.\\u2013\\u0E1E.\\u0E22.",
1060 
1061         // Tests for Japanese calendar with eras, including new era in 2019 (Heisei 31 through April 30, then new era)
1062 
1063         "en-u-ca-japanese", "H 31 03 15 09:00:00", "H 31 04 15 09:00:00", "GyMMMd", "Mar 15\\u2009\\u2013\\u2009Apr 15, 31 Heisei",
1064 
1065         "en-u-ca-japanese", "H 31 03 15 09:00:00", "H 31 04 15 09:00:00", "GGGGGyMd", "3/15/31\\u2009\\u2013\\u20094/15/31 H",
1066 
1067         "en-u-ca-japanese", "S 64 01 05 09:00:00", "H 1 01 15 09:00:00",  "GyMMMd", "Jan 5, 64 Sh\\u014Dwa\\u2009\\u2013\\u2009Jan 15, 1 Heisei",
1068 
1069         "en-u-ca-japanese", "S 64 01 05 09:00:00", "H 1 01 15 09:00:00",  "GGGGGyMd", "1/5/64 S\\u2009\\u2013\\u20091/15/1 H",
1070 
1071         "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\\u2009\\u2013\\u2009May 15, 1 " JP_ERA_2019_ROOT,
1072 
1073         "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\\u2009\\u2013\\u20095/15/1 " JP_ERA_2019_NARROW,
1074 
1075 
1076         "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",
1077 
1078         "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",
1079 
1080         "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",
1081 
1082         "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",
1083 
1084         "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",
1085 
1086         // END ANDROID-changed
1087     };
1088     expect(DATA, UPRV_LENGTHOF(DATA));
1089 }
1090 
1091 
1092 /**
1093  * Test handling of hour and day period metacharacters
1094  */
testHourMetacharacters()1095 void DateIntervalFormatTest::testHourMetacharacters() {
1096     // first item is date pattern
1097     // followed by a group of locale/from_data/to_data/skeleton/interval_data
1098     // Note that from_data/to_data are specified using era names from root, for the calendar specified by locale.
1099     const char* DATA[] = {
1100         "GGGGG y MM dd HH:mm:ss", // pattern for from_data/to_data
1101 
1102         // This test is for tickets ICU-21154, ICU-21155, and ICU-21156 and is intended to verify
1103         // that all of the special skeleton characters for hours and day periods work as expected
1104         // with date intervals:
1105         // - If a, b, or B is included in the skeleton, it correctly sets the length of the day-period field
1106         // - If k or K is included, it behaves the same as H or h, except for the difference in the actual
1107         //   number used for the hour.
1108         // - If j is included, it behaves the same as either h or H as appropriate, and multiple j's have the
1109         //   intended effect on the length of the day period field (if there is one)
1110         // - If J is included, it correctly suppresses the day period field if j would include it
1111         // - If C is included, it behaves the same as j and brings up the correct day period field
1112         // - In all cases, if the day period of both ends of the range is the same, you only see it once
1113 
1114         // baseline (h and H)
1115         "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hh", "12\\u2009\\u2013\\u20091\\u202FAM",
1116         "de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "HH", "00\\u201301 Uhr",
1117 
1118         // k and K (ICU-21154 and ICU-21156)
1119         // (should behave the same as h and H if not overridden in locale ID)
1120         "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "KK", "12\\u2009\\u2013\\u20091\\u202FAM",
1121         "de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "kk", "00\\u201301 Uhr",
1122         // (overriding hour cycle in locale ID should affect both h and K [or both H and k])
1123         "en-u-hc-h11", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hh", "0\\u2009\\u2013\\u20091\\u202FAM",
1124         "en-u-hc-h11", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "KK", "0\\u2009\\u2013\\u20091\\u202FAM",
1125         "de-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "HH", "24\\u201301 Uhr",
1126         "de-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "kk", "24\\u201301 Uhr",
1127         // (overriding hour cycle to h11 should NOT affect H and k; overriding to h24 should NOT affect h and K)
1128         "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "HH", "00\\u2009\\u2013\\u200901",
1129         "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "kk", "00\\u2009\\u2013\\u200901",
1130         "en-u-hc-h11", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "HH", "00\\u2009\\u2013\\u200901",
1131         "en-u-hc-h11", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "kk", "00\\u2009\\u2013\\u200901",
1132         "de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hh", "12\\u2009\\u2013\\u20091 Uhr AM",
1133         "de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "KK", "12\\u2009\\u2013\\u20091 Uhr AM",
1134         "de-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hh", "12\\u2009\\u2013\\u20091 Uhr AM",
1135         "de-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "KK", "12\\u2009\\u2013\\u20091 Uhr AM",
1136 
1137         // different lengths of the 'a' field
1138         "en", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "ha", "10\\u202FAM\\u2009\\u2013\\u20091\\u202FPM",
1139         "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "ha", "12\\u2009\\u2013\\u20091\\u202FAM",
1140         "en", "CE 2010 09 27 10:00:00", "CE 2010 09 27 12:00:00", "haaaaa", "10\\u202Fa\\u2009\\u2013\\u200912\\u202Fp",
1141         "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "haaaaa", "12\\u2009\\u2013\\u20091\\u202Fa",
1142 
1143         // j (ICU-21155)
1144         "en", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "jj", "10\\u202FAM\\u2009\\u2013\\u20091\\u202FPM",
1145         "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "jj", "12\\u2009\\u2013\\u20091\\u202FAM",
1146         "en", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "jjjjj", "10\\u202Fa\\u2009\\u2013\\u20091\\u202Fp",
1147         "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "jjjjj", "12\\u2009\\u2013\\u20091\\u202Fa",
1148         "de", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "jj", "10\\u201313 Uhr",
1149         "de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "jj", "00\\u201301 Uhr",
1150         "de", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "jjjjj", "10\\u201313 Uhr",
1151         "de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "jjjjj", "00\\u201301 Uhr",
1152 
1153         // b and B
1154         "en", "CE 2010 09 27 10:00:00", "CE 2010 09 27 12:00:00", "hb", "10\\u202FAM\\u2009\\u2013\\u200912\\u202Fnoon",
1155         "en", "CE 2010 09 27 10:00:00", "CE 2010 09 27 12:00:00", "hbbbbb", "10\\u202Fa\\u2009\\u2013\\u200912\\u202Fn",
1156         "en", "CE 2010 09 27 13:00:00", "CE 2010 09 27 14:00:00", "hb", "1\\u2009\\u2013\\u20092\\u202FPM",
1157         "en", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "hB", "10 in the morning\\u2009\\u2013\\u20091 in the afternoon",
1158         "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hB", "12\\u2009\\u2013\\u20091 at night",
1159 
1160         // J
1161         "en", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "J", "10\\u2009\\u2013\\u20091",
1162         "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "J", "12\\u2009\\u2013\\u20091",
1163         "de", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "J", "10\\u201313 Uhr",
1164         "de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "J", "00\\u201301 Uhr",
1165 
1166         // C
1167         // (for English and German, C should do the same thing as j)
1168         "en", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "CC", "10\\u202FAM\\u2009\\u2013\\u20091\\u202FPM",
1169         "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "CC", "12\\u2009\\u2013\\u20091\\u202FAM",
1170         "en", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "CCCCC", "10\\u202Fa\\u2009\\u2013\\u20091\\u202Fp",
1171         "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "CCCCC", "12\\u2009\\u2013\\u20091\\u202Fa",
1172         "de", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "CC", "10\\u201313 Uhr",
1173         "de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "CC", "00\\u201301 Uhr",
1174         "de", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "CCCCC", "10\\u201313 Uhr",
1175         "de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "CCCCC", "00\\u201301 Uhr",
1176         // (for zh_HK and hi_IN, j maps to ha, but C maps to hB)
1177         "zh_HK", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "jj", "\\u4E0A\\u534810\\u6642\\u81F3\\u4E0B\\u53481\\u6642",
1178         "zh_HK", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "jj", "\\u4E0A\\u534812\\u6642\\u81F31\\u6642",
1179         "zh_HK", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "hB", "\\u4E0A\\u534810\\u6642 \\u2013 \\u4E0B\\u53481\\u6642",
1180         "zh_HK", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hB", "\\u51CC\\u666812\\u20131\\u6642",
1181         "zh_HK", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "CC", "\\u4E0A\\u534810\\u6642\\u81F3\\u4E0B\\u53481\\u6642",
1182         "zh_HK", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "CC", "\\u4E0A\\u534812\\u6642\\u81F31\\u6642",
1183         "hi_IN", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "jj", "10 am \\u2013 1 pm",
1184         "hi_IN", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "jj", "12\\u20131 am",
1185         "hi_IN", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "hB", "\\u0938\\u0941\\u092C\\u0939 10 \\u2013 \\u0926\\u094B\\u092A\\u0939\\u0930 1",
1186         "hi_IN", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hB", "\\u0930\\u093E\\u0924 12\\u20131",
1187         "hi_IN", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "CC", "\\u0938\\u0941\\u092C\\u0939 10 \\u2013 \\u0926\\u094B\\u092A\\u0939\\u0930 1",
1188         "hi_IN", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "CC", "\\u0930\\u093E\\u0924 12\\u20131",
1189 
1190         // regression test for ICU-21342
1191         "en-gb-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 10:00:00", "kk", "24\\u201310",
1192         "en-gb-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 11:00:00", "kk", "24\\u201311",
1193         "en-gb-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 12:00:00", "kk", "24\\u201312",
1194         "en-gb-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 13:00:00", "kk", "24\\u201313",
1195 
1196         // regression test for ICU-21343
1197         "de", "CE 2010 09 27 01:00:00", "CE 2010 09 27 10:00:00", "KK", "1\\u2009\\u2013\\u200910 Uhr AM",
1198 
1199         // regression test for ICU-21154 (single-date ranges should use the same hour cycle as multi-date ranges)
1200         "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 00:00:00", "hh", "12\\u202FAM",
1201         "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hh", "12\\u2009\\u2013\\u20091\\u202FAM",
1202         "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 00:00:00", "KK", "12\\u202FAM",
1203         "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "KK", "12\\u2009\\u2013\\u20091\\u202FAM", // (this was producing "0 - 1\\u202FAM" before)
1204         "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 00:00:00", "jj", "12\\u202FAM",
1205         "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "jj", "12\\u2009\\u2013\\u20091\\u202FAM",
1206 
1207         // regression test for ICU-21984 (multiple day-period characters in date-interval patterns)
1208         "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "MMMdhhmma", "Sep 27, 12:00\\u2009\\u2013\\u20091:00\\u202FAM",
1209         "sq", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "Bhm", "12:00\\u2009\\u2013\\u20091:00 e nat\\u00EBs",
1210     };
1211     expect(DATA, UPRV_LENGTHOF(DATA));
1212 }
1213 
1214 
expect(const char ** data,int32_t data_length)1215 void DateIntervalFormatTest::expect(const char** data, int32_t data_length) {
1216     int32_t i = 0;
1217     UErrorCode ec = U_ZERO_ERROR;
1218     UnicodeString str, str2;
1219     const char* pattern = data[i++];
1220 
1221     while (i<data_length) {
1222         const char* locName = data[i++];
1223         const char* datestr = data[i++];
1224         const char* datestr_2 = data[i++];
1225 
1226         Locale loc(locName);
1227         LocalPointer<Calendar> defCal(Calendar::createInstance(loc, ec));
1228         if (U_FAILURE(ec)) {
1229             dataerrln("Calendar::createInstance fails for loc %s with: %s", locName, u_errorName(ec));
1230             return;
1231         }
1232         const char* calType = defCal->getType();
1233 
1234         Locale refLoc("root");
1235         if (calType) {
1236             refLoc.setKeywordValue("calendar", calType, ec);
1237         }
1238         SimpleDateFormat ref(pattern, refLoc, ec);
1239         logln( "case %d, locale: %s\n", (i-1)/5, locName);
1240         if (U_FAILURE(ec)) {
1241             dataerrln("contruct SimpleDateFormat in expect failed: %s", u_errorName(ec));
1242             return;
1243         }
1244 
1245         // 'f'
1246         logln("original date: %s - %s\n", datestr, datestr_2);
1247         UDate date = ref.parse(ctou(datestr), ec);
1248         if (!assertSuccess("parse 1st data in expect", ec)) return;
1249         UDate date_2 = ref.parse(ctou(datestr_2), ec);
1250         if (!assertSuccess("parse 2nd data in expect", ec)) return;
1251         DateInterval dtitv(date, date_2);
1252 
1253         const UnicodeString& oneSkeleton(ctou(data[i++]));
1254 
1255         DateIntervalFormat* dtitvfmt = DateIntervalFormat::createInstance(oneSkeleton, loc, ec);
1256         if (!assertSuccess("createInstance(skeleton) in expect", ec)) return;
1257         FieldPosition pos(FieldPosition::DONT_CARE);
1258         dtitvfmt->format(&dtitv, str.remove(), pos, ec);
1259         if (!assertSuccess("format in expect", ec)) return;
1260         assertEquals((UnicodeString)"\"" + locName + "\\" + oneSkeleton + "\\" + ctou(datestr) + "\\" + ctou(datestr_2) + "\"", ctou(data[i++]), str);
1261 
1262         logln("interval date:" + str + "\"" + locName + "\", "
1263                  + "\"" + datestr + "\", "
1264               + "\"" + datestr_2 + "\", " + oneSkeleton);
1265         delete dtitvfmt;
1266     }
1267 }
1268 
1269 
1270 /*
1271  * Test format using user defined DateIntervalInfo
1272  */
testFormatUserDII()1273 void DateIntervalFormatTest::testFormatUserDII() {
1274     // first item is date pattern
1275     const char* DATA[] = {
1276         "yyyy MM dd HH:mm:ss",
1277         "en", "2007 10 10 10:10:10", "2008 10 10 10:10:10", "Oct 10, 2007 --- Oct 10, 2008",
1278 
1279         "en", "2007 10 10 10:10:10", "2007 11 10 10:10:10", "2007 Oct 10 - Nov 2007",
1280 
1281         "en", "2007 11 10 10:10:10", "2007 11 20 10:10:10", "Nov 10, 2007 --- Nov 20, 2007",
1282 
1283         "en", "2007 01 10 10:00:10", "2007 01 10 14:10:10", "Jan 10, 2007",
1284 
1285         "en", "2007 01 10 10:00:10", "2007 01 10 10:20:10", "Jan 10, 2007",
1286 
1287         "en", "2007 01 10 10:10:10", "2007 01 10 10:10:20", "Jan 10, 2007",
1288 
1289         "zh", "2007 10 10 10:10:10", "2008 10 10 10:10:10", "2007\\u5e7410\\u670810\\u65e5 --- 2008\\u5e7410\\u670810\\u65e5",
1290 
1291         "zh", "2007 10 10 10:10:10", "2007 11 10 10:10:10", "2007 10\\u6708 10 - 11\\u6708 2007",
1292 
1293         "zh", "2007 11 10 10:10:10", "2007 11 20 10:10:10", "2007\\u5e7411\\u670810\\u65e5 --- 2007\\u5e7411\\u670820\\u65e5",
1294 
1295         "zh", "2007 01 10 10:00:10", "2007 01 10 14:10:10", "2007\\u5e741\\u670810\\u65e5", // (fixed expected result per ticket:6626:)
1296 
1297         "zh", "2007 01 10 10:00:10", "2007 01 10 10:20:10", "2007\\u5e741\\u670810\\u65e5", // (fixed expected result per ticket:6626:)
1298 
1299         "zh", "2007 01 10 10:10:10", "2007 01 10 10:10:20", "2007\\u5e741\\u670810\\u65e5", // (fixed expected result per ticket:6626:)
1300 
1301         "de", "2007 10 10 10:10:10", "2008 10 10 10:10:10", "10. Okt. 2007 --- 10. Okt. 2008",
1302 
1303 
1304         "de", "2007 11 10 10:10:10", "2007 11 20 10:10:10", "10. Nov. 2007 --- 20. Nov. 2007",
1305 
1306         "de", "2007 01 10 10:00:10", "2007 01 10 14:10:10", "10. Jan. 2007",
1307 
1308         "de", "2007 01 10 10:00:10", "2007 01 10 10:20:10", "10. Jan. 2007",
1309 
1310 
1311         "es", "2007 10 10 10:10:10", "2008 10 10 10:10:10", "10 oct 2007 --- 10 oct 2008",
1312 
1313         "es", "2007 10 10 10:10:10", "2007 11 10 10:10:10", "2007 oct 10 - nov 2007",
1314 
1315         "es", "2007 11 10 10:10:10", "2007 11 20 10:10:10", "10 nov 2007 --- 20 nov 2007",
1316 
1317         "es", "2007 01 10 10:00:10", "2007 01 10 14:10:10", "10 ene 2007",
1318 
1319         "es", "2007 01 10 10:00:10", "2007 01 10 10:20:10", "10 ene 2007",
1320 
1321         "es", "2007 01 10 10:10:10", "2007 01 10 10:10:20", "10 ene 2007",
1322     };
1323     expectUserDII(DATA, UPRV_LENGTHOF(DATA));
1324 }
1325 
1326 /*
1327  * Test format using UDisplayContext
1328  */
1329 #define CAP_NONE  UDISPCTX_CAPITALIZATION_NONE
1330 #define CAP_BEGIN UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE
1331 #define CAP_LIST  UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU
1332 #define CAP_ALONE UDISPCTX_CAPITALIZATION_FOR_STANDALONE
1333 #define _DAY    (24.0*60.0*60.0*1000.0)
1334 
testContext()1335 void DateIntervalFormatTest::testContext() {
1336     static const UDate startDate = 1285599629000.0; // 2010-Sep-27 0800 in America/Los_Angeles
1337     typedef struct {
1338         const char * locale;
1339         const char * skeleton;
1340         UDisplayContext context;
1341         const UDate  deltaDate;
1342         const char16_t* expectResult;
1343     } DateIntervalContextItem;
1344     static const DateIntervalContextItem testItems[] = {
1345         { "cs",    "MMMEd",    CAP_NONE,  60.0*_DAY,  u"po 27. 9.\u2009–\u2009pá 26. 11." },
1346         { "cs",    "yMMMM",    CAP_NONE,  60.0*_DAY,  u"září–listopad 2010" },
1347         { "cs",    "yMMMM",    CAP_NONE,  1.0*_DAY,   u"září 2010" },
1348 #if !UCONFIG_NO_BREAK_ITERATION
1349         { "cs",    "MMMEd",    CAP_BEGIN, 60.0*_DAY,  u"Po 27. 9.\u2009–\u2009pá 26. 11." },
1350         { "cs",    "yMMMM",    CAP_BEGIN, 60.0*_DAY,  u"Září–listopad 2010" },
1351         { "cs",    "yMMMM",    CAP_BEGIN, 1.0*_DAY,   u"Září 2010" },
1352         { "cs",    "MMMEd",    CAP_LIST,  60.0*_DAY,  u"Po 27. 9.\u2009–\u2009pá 26. 11." },
1353         { "cs",    "yMMMM",    CAP_LIST,  60.0*_DAY,  u"Září–listopad 2010" },
1354         { "cs",    "yMMMM",    CAP_LIST,  1.0*_DAY,   u"Září 2010" },
1355 #endif
1356         { "cs",    "MMMEd",    CAP_ALONE, 60.0*_DAY,  u"po 27. 9.\u2009–\u2009pá 26. 11." },
1357         { "cs",    "yMMMM",    CAP_ALONE, 60.0*_DAY,  u"září–listopad 2010" },
1358         { "cs",    "yMMMM",    CAP_ALONE, 1.0*_DAY,   u"září 2010" },
1359         { nullptr, nullptr,    CAP_NONE,  0,          nullptr }
1360     };
1361     const DateIntervalContextItem* testItemPtr;
1362     for ( testItemPtr = testItems; testItemPtr->locale != nullptr; ++testItemPtr ) {
1363         UErrorCode status = U_ZERO_ERROR;
1364         Locale locale(testItemPtr->locale);
1365         UnicodeString skeleton(testItemPtr->skeleton, -1, US_INV);
1366         LocalPointer<DateIntervalFormat> fmt(DateIntervalFormat::createInstance(skeleton, locale, status));
1367         if (U_FAILURE(status)) {
1368             errln("createInstance failed for locale %s skeleton %s: %s",
1369                     testItemPtr->locale, testItemPtr->skeleton, u_errorName(status));
1370             continue;
1371         }
1372         fmt->adoptTimeZone(TimeZone::createTimeZone("America/Los_Angeles"));
1373 
1374         fmt->setContext(testItemPtr->context, status);
1375         if (U_FAILURE(status)) {
1376             errln("setContext failed for locale %s skeleton %s context %04X: %s",
1377                     testItemPtr->locale, testItemPtr->skeleton, (unsigned)testItemPtr->context, u_errorName(status));
1378         } else {
1379             UDisplayContext getContext = fmt->getContext(UDISPCTX_TYPE_CAPITALIZATION, status);
1380             if (U_FAILURE(status)) {
1381                 errln("getContext failed for locale %s skeleton %s context %04X: %s",
1382                         testItemPtr->locale, testItemPtr->skeleton, (unsigned)testItemPtr->context, u_errorName(status));
1383             } else if (getContext != testItemPtr->context) {
1384                 errln("getContext failed for locale %s skeleton %s context %04X: got context %04X",
1385                         testItemPtr->locale, testItemPtr->skeleton, (unsigned)testItemPtr->context, (unsigned)getContext);
1386             }
1387         }
1388 
1389         status = U_ZERO_ERROR;
1390         DateInterval interval(startDate, startDate + testItemPtr->deltaDate);
1391         UnicodeString getResult;
1392         FieldPosition pos(FieldPosition::DONT_CARE);
1393         fmt->format(&interval, getResult, pos, status);
1394         if (U_FAILURE(status)) {
1395             errln("format failed for locale %s skeleton %s context %04X: %s",
1396                     testItemPtr->locale, testItemPtr->skeleton, (unsigned)testItemPtr->context, u_errorName(status));
1397             continue;
1398         }
1399         UnicodeString expectResult(true, testItemPtr->expectResult, -1);
1400         if (getResult != expectResult) {
1401             errln(UnicodeString("format expected ") + expectResult + UnicodeString(" but got ") + getResult);
1402         }
1403     }
1404 }
1405 
testSetIntervalPatternNoSideEffect()1406 void DateIntervalFormatTest::testSetIntervalPatternNoSideEffect() {
1407     UErrorCode ec = U_ZERO_ERROR;
1408     LocalPointer<DateIntervalInfo> dtitvinf(new DateIntervalInfo(ec), ec);
1409     if (U_FAILURE(ec)) {
1410         errln("Failure encountered: %s", u_errorName(ec));
1411         return;
1412     }
1413     UnicodeString expected;
1414     dtitvinf->getIntervalPattern(ctou("yMd"), UCAL_DATE, expected, ec);
1415     dtitvinf->setIntervalPattern(ctou("yMd"), UCAL_DATE, ctou("M/d/y\\u2009\\u2013\\u2009d"), ec);
1416     if (U_FAILURE(ec)) {
1417         errln("Failure encountered: %s", u_errorName(ec));
1418         return;
1419     }
1420     dtitvinf.adoptInsteadAndCheckErrorCode(new DateIntervalInfo(ec), ec);
1421     if (U_FAILURE(ec)) {
1422         errln("Failure encountered: %s", u_errorName(ec));
1423         return;
1424     }
1425     UnicodeString actual;
1426     dtitvinf->getIntervalPattern(ctou("yMd"), UCAL_DATE, actual, ec);
1427     if (U_FAILURE(ec)) {
1428         errln("Failure encountered: %s", u_errorName(ec));
1429         return;
1430     }
1431     if (expected != actual) {
1432         errln("DateIntervalInfo.setIntervalPattern should have no side effects.");
1433     }
1434 }
1435 
testYearFormats()1436 void DateIntervalFormatTest::testYearFormats() {
1437     const Locale &enLocale = Locale::getEnglish();
1438     UErrorCode status = U_ZERO_ERROR;
1439     LocalPointer<Calendar> fromTime(Calendar::createInstance(enLocale, status));
1440     LocalPointer<Calendar> toTime(Calendar::createInstance(enLocale, status));
1441     if (U_FAILURE(status)) {
1442         errln("Failure encountered: %s", u_errorName(status));
1443         return;
1444     }
1445     // April 26, 113. Three digit year so that we can test 2 digit years;
1446     // 4 digit years with padded 0's and full years.
1447     fromTime->set(113, 3, 26);
1448     // April 28, 113.
1449     toTime->set(113, 3, 28);
1450     {
1451         LocalPointer<DateIntervalFormat> dif(DateIntervalFormat::createInstance("yyyyMd", enLocale, status));
1452         if (U_FAILURE(status)) {
1453             dataerrln("Failure encountered: %s", u_errorName(status));
1454             return;
1455         }
1456         UnicodeString actual;
1457         UnicodeString expected(ctou("4/26/0113\\u2009\\u2013\\u20094/28/0113"));
1458         FieldPosition pos;
1459         dif->format(*fromTime, *toTime, actual, pos, status);
1460         if (U_FAILURE(status)) {
1461             errln("Failure encountered: %s", u_errorName(status));
1462             return;
1463         }
1464         if (actual != expected) {
1465             errln("Expected " + expected + ", got: " + actual);
1466         }
1467     }
1468     {
1469         LocalPointer<DateIntervalFormat> dif(DateIntervalFormat::createInstance("yyMd", enLocale, status));
1470         if (U_FAILURE(status)) {
1471             errln("Failure encountered: %s", u_errorName(status));
1472             return;
1473         }
1474         UnicodeString actual;
1475         UnicodeString expected(ctou("4/26/13\\u2009\\u2013\\u20094/28/13"));
1476         FieldPosition pos(FieldPosition::DONT_CARE);
1477         dif->format(*fromTime, *toTime, actual, pos, status);
1478         if (U_FAILURE(status)) {
1479             errln("Failure encountered: %s", u_errorName(status));
1480             return;
1481         }
1482         if (actual != expected) {
1483             errln("Expected " + expected + ", got: " + actual);
1484         }
1485     }
1486     {
1487         LocalPointer<DateIntervalFormat> dif(DateIntervalFormat::createInstance("yMd", enLocale, status));
1488         if (U_FAILURE(status)) {
1489             errln("Failure encountered: %s", u_errorName(status));
1490             return;
1491         }
1492         UnicodeString actual;
1493         UnicodeString expected(ctou("4/26/113\\u2009\\u2013\\u20094/28/113"));
1494         FieldPosition pos(FieldPosition::DONT_CARE);
1495         dif->format(*fromTime, *toTime, actual, pos, status);
1496         if (U_FAILURE(status)) {
1497             errln("Failure encountered: %s", u_errorName(status));
1498             return;
1499         }
1500         if (actual != expected) {
1501             errln("Expected " + expected + ", got: " + actual);
1502         }
1503     }
1504 }
1505 
expectUserDII(const char ** data,int32_t data_length)1506 void DateIntervalFormatTest::expectUserDII(const char** data,
1507                                            int32_t data_length) {
1508     int32_t i = 0;
1509     UnicodeString str;
1510     UErrorCode ec = U_ZERO_ERROR;
1511     const char* pattern = data[0];
1512     i++;
1513 
1514     while ( i < data_length ) {
1515         const char* locName = data[i++];
1516         Locale loc(locName);
1517         SimpleDateFormat ref(pattern, loc, ec);
1518         if (U_FAILURE(ec)) {
1519             dataerrln("contruct SimpleDateFormat in expectUserDII failed: %s", u_errorName(ec));
1520             return;
1521         }
1522         const char* datestr = data[i++];
1523         const char* datestr_2 = data[i++];
1524         UDate date = ref.parse(ctou(datestr), ec);
1525         if (!assertSuccess("parse in expectUserDII", ec)) return;
1526         UDate date_2 = ref.parse(ctou(datestr_2), ec);
1527         if (!assertSuccess("parse in expectUserDII", ec)) return;
1528         DateInterval dtitv(date, date_2);
1529 
1530         ec = U_ZERO_ERROR;
1531         // test user created DateIntervalInfo
1532         DateIntervalInfo* dtitvinf = new DateIntervalInfo(ec);
1533         dtitvinf->setFallbackIntervalPattern("{0} --- {1}", ec);
1534         dtitvinf->setIntervalPattern(UDAT_YEAR_ABBR_MONTH_DAY, UCAL_MONTH, "yyyy MMM d - MMM y",ec);
1535         if (!assertSuccess("DateIntervalInfo::setIntervalPattern", ec)) return;
1536         dtitvinf->setIntervalPattern(UDAT_YEAR_ABBR_MONTH_DAY, UCAL_HOUR_OF_DAY, "yyyy MMM d HH:mm - HH:mm", ec);
1537         if (!assertSuccess("DateIntervalInfo::setIntervalPattern", ec)) return;
1538         DateIntervalFormat* dtitvfmt = DateIntervalFormat::createInstance(UDAT_YEAR_ABBR_MONTH_DAY, loc, *dtitvinf, ec);
1539         delete dtitvinf;
1540         if (!assertSuccess("createInstance(skeleton,dtitvinf) in expectUserDII", ec)) return;
1541         FieldPosition pos(FieldPosition::DONT_CARE);
1542         dtitvfmt->format(&dtitv, str.remove(), pos, ec);
1543         if (!assertSuccess("format in expectUserDII", ec)) return;
1544         assertEquals((UnicodeString)"\"" + locName + "\\" + datestr + "\\" + datestr_2 + "\"", ctou(data[i++]), str);
1545 #ifdef DTIFMTTS_DEBUG
1546         char result[1000];
1547         char mesg[1000];
1548         PRINTMESG("interval format using user defined DateIntervalInfo\n");
1549         str.extract(0,  str.length(), result, "UTF-8");
1550         snprintf(mesg, sizeof(mesg), "interval date: %s\n", result);
1551         PRINTMESG(mesg);
1552 #endif
1553         delete dtitvfmt;
1554     }
1555 }
1556 
1557 
testStress()1558 void DateIntervalFormatTest::testStress() {
1559     if(quick){
1560     	logln("Quick mode: Skipping test");
1561     	return;
1562     }
1563 	const char* DATA[] = {
1564         "yyyy MM dd HH:mm:ss",
1565         "2007 10 10 10:10:10", "2008 10 10 10:10:10",
1566         "2007 10 10 10:10:10", "2007 11 10 10:10:10",
1567         "2007 11 10 10:10:10", "2007 11 20 10:10:10",
1568         "2007 01 10 10:00:10", "2007 01 10 14:10:10",
1569         "2007 01 10 10:00:10", "2007 01 10 10:20:10",
1570         "2007 01 10 10:10:10", "2007 01 10 10:10:20",
1571     };
1572 
1573     const char* testLocale[][3] = {
1574         //{"th", "", ""},
1575         {"en", "", ""},
1576         {"zh", "", ""},
1577         {"de", "", ""},
1578         {"ar", "", ""},
1579         {"en", "GB",  ""},
1580         {"fr", "", ""},
1581         {"it", "", ""},
1582         {"nl", "", ""},
1583         {"zh", "TW",  ""},
1584         {"ja", "", ""},
1585         {"pt", "BR", ""},
1586         {"ru", "", ""},
1587         {"pl", "", ""},
1588         {"tr", "", ""},
1589         {"es", "", ""},
1590         {"ko", "", ""},
1591         {"sv", "", ""},
1592         {"fi", "", ""},
1593         {"da", "", ""},
1594         {"pt", "PT", ""},
1595         {"ro", "", ""},
1596         {"hu", "", ""},
1597         {"he", "", ""},
1598         {"in", "", ""},
1599         {"cs", "", ""},
1600         {"el", "", ""},
1601         {"no", "", ""},
1602         {"vi", "", ""},
1603         {"bg", "", ""},
1604         {"hr", "", ""},
1605         {"lt", "", ""},
1606         {"sk", "", ""},
1607         {"sl", "", ""},
1608         {"sr", "", ""},
1609         {"ca", "", ""},
1610         {"lv", "", ""},
1611         {"uk", "", ""},
1612         {"hi", "", ""},
1613     };
1614 
1615     uint32_t localeIndex;
1616     for ( localeIndex = 0; localeIndex < UPRV_LENGTHOF(testLocale); ++localeIndex ) {
1617         char locName[32];
1618         uprv_strcpy(locName, testLocale[localeIndex][0]);
1619         uprv_strcat(locName, testLocale[localeIndex][1]);
1620         stress(DATA, UPRV_LENGTHOF(DATA), Locale(testLocale[localeIndex][0], testLocale[localeIndex][1], testLocale[localeIndex][2]), locName);
1621     }
1622 }
1623 
1624 
stress(const char ** data,int32_t data_length,const Locale & loc,const char * locName)1625 void DateIntervalFormatTest::stress(const char** data, int32_t data_length,
1626                                     const Locale& loc, const char* locName) {
1627     UnicodeString skeleton[] = {
1628         "EEEEdMMMMy",
1629         "dMMMMy",
1630         "dMMMM",
1631         "MMMMy",
1632         "EEEEdMMMM",
1633         "EdMMMy",
1634         "dMMMy",
1635         "dMMM",
1636         "MMMy",
1637         "EdMMM",
1638         "EdMy",
1639         "dMy",
1640         "dM",
1641         "My",
1642         "EdM",
1643         "d",
1644         "Ed",
1645         "y",
1646         "M",
1647         "MMM",
1648         "MMMM",
1649         "hm",
1650         "hmv",
1651         "hmz",
1652         "h",
1653         "hv",
1654         "hz",
1655         "EEddMMyyyy", // following could be normalized
1656         "EddMMy",
1657         "hhmm",
1658         "hhmmzz",
1659         "hms",  // following could not be normalized
1660         "dMMMMMy",
1661         "EEEEEdM",
1662     };
1663 
1664     int32_t i = 0;
1665     UErrorCode ec = U_ZERO_ERROR;
1666     UnicodeString str, str2;
1667     SimpleDateFormat ref(data[i++], loc, ec);
1668     if (!assertSuccess("construct SimpleDateFormat", ec)) return;
1669 
1670 #ifdef DTIFMTTS_DEBUG
1671     char result[1000];
1672     char mesg[1000];
1673     snprintf(mesg, sizeof(mesg), "locale: %s\n", locName);
1674     PRINTMESG(mesg);
1675 #endif
1676 
1677     while (i<data_length) {
1678 
1679         // 'f'
1680         const char* datestr = data[i++];
1681         const char* datestr_2 = data[i++];
1682 #ifdef DTIFMTTS_DEBUG
1683         snprintf(mesg, sizeof(mesg), "original date: %s - %s\n", datestr, datestr_2);
1684         PRINTMESG(mesg)
1685 #endif
1686         UDate date = ref.parse(ctou(datestr), ec);
1687         if (!assertSuccess("parse", ec)) return;
1688         UDate date_2 = ref.parse(ctou(datestr_2), ec);
1689         if (!assertSuccess("parse", ec)) return;
1690         DateInterval dtitv(date, date_2);
1691 
1692         for ( uint32_t skeletonIndex = 0;
1693               skeletonIndex < UPRV_LENGTHOF(skeleton);
1694               ++skeletonIndex ) {
1695             const UnicodeString& oneSkeleton = skeleton[skeletonIndex];
1696             DateIntervalFormat* dtitvfmt = DateIntervalFormat::createInstance(oneSkeleton, loc, ec);
1697             if (!assertSuccess("createInstance(skeleton)", ec)) return;
1698             /*
1699             // reset the calendar to be Gregorian calendar for "th"
1700             if ( uprv_strcmp(locName, "th") == 0 ) {
1701                 GregorianCalendar* gregCal = new GregorianCalendar(loc, ec);
1702                 if (!assertSuccess("GregorianCalendar()", ec)) return;
1703                 const DateFormat* dformat = dtitvfmt->getDateFormat();
1704                 DateFormat* newOne = dformat->clone();
1705                 newOne->adoptCalendar(gregCal);
1706                 //dtitvfmt->adoptDateFormat(newOne, ec);
1707                 dtitvfmt->setDateFormat(*newOne, ec);
1708                 delete newOne;
1709                 if (!assertSuccess("adoptDateFormat()", ec)) return;
1710             }
1711             */
1712             FieldPosition pos(FieldPosition::DONT_CARE);
1713             dtitvfmt->format(&dtitv, str.remove(), pos, ec);
1714             if (!assertSuccess("format", ec)) return;
1715 #ifdef DTIFMTTS_DEBUG
1716             oneSkeleton.extract(0,  oneSkeleton.length(), result, "UTF-8");
1717             snprintf(mesg, sizeof(mesg), "interval by skeleton: %s\n", result);
1718             PRINTMESG(mesg)
1719             str.extract(0,  str.length(), result, "UTF-8");
1720             snprintf(mesg, sizeof(mesg), "interval date: %s\n", result);
1721             PRINTMESG(mesg)
1722 #endif
1723             delete dtitvfmt;
1724         }
1725 
1726         // test user created DateIntervalInfo
1727         ec = U_ZERO_ERROR;
1728         DateIntervalInfo* dtitvinf = new DateIntervalInfo(ec);
1729         dtitvinf->setFallbackIntervalPattern("{0} --- {1}", ec);
1730         dtitvinf->setIntervalPattern(UDAT_YEAR_ABBR_MONTH_DAY, UCAL_MONTH, "yyyy MMM d - MMM y",ec);
1731         if (!assertSuccess("DateIntervalInfo::setIntervalPattern", ec)) return;
1732         dtitvinf->setIntervalPattern(UDAT_YEAR_ABBR_MONTH_DAY, UCAL_HOUR_OF_DAY, "yyyy MMM d HH:mm - HH:mm", ec);
1733         if (!assertSuccess("DateIntervalInfo::setIntervalPattern", ec)) return;
1734         DateIntervalFormat* dtitvfmt = DateIntervalFormat::createInstance(UDAT_YEAR_ABBR_MONTH_DAY, loc, *dtitvinf, ec);
1735         delete dtitvinf;
1736         if (!assertSuccess("createInstance(skeleton,dtitvinf)", ec)) return;
1737         FieldPosition pos(FieldPosition::DONT_CARE);
1738         dtitvfmt->format(&dtitv, str.remove(), pos, ec);
1739         if ( uprv_strcmp(locName, "th") ) {
1740             if (!assertSuccess("format", ec)) return;
1741 #ifdef DTIFMTTS_DEBUG
1742             PRINTMESG("interval format using user defined DateIntervalInfo\n");
1743             str.extract(0,  str.length(), result, "UTF-8");
1744             snprintf(mesg, sizeof(mesg), "interval date: %s\n", result);
1745             PRINTMESG(mesg)
1746 #endif
1747         } else {
1748             // for "th", the default calendar is Budhist,
1749             // not Gregorian.
1750             assertTrue("Default calendar for \"th\" is Budhist", ec == U_ILLEGAL_ARGUMENT_ERROR);
1751             ec = U_ZERO_ERROR;
1752         }
1753         delete dtitvfmt;
1754     }
1755 }
1756 
testTicket11583_2()1757 void DateIntervalFormatTest::testTicket11583_2() {
1758     UErrorCode status = U_ZERO_ERROR;
1759     LocalPointer<DateIntervalFormat> fmt(
1760             DateIntervalFormat::createInstance("yMMM", "es-US", status));
1761     if (!assertSuccess("Error create format object", status)) {
1762         return;
1763     }
1764     DateInterval interval((UDate) 1232364615000.0, (UDate) 1328787015000.0);
1765     UnicodeString appendTo;
1766     FieldPosition fpos(FieldPosition::DONT_CARE);
1767     UnicodeString expected("ene de 2009\\u2009\\u2013\\u2009feb de 2012");
1768     assertEquals(
1769             "",
1770             expected.unescape(),
1771             fmt->format(&interval, appendTo, fpos, status));
1772     if (!assertSuccess("Error formatting", status)) {
1773         return;
1774     }
1775 }
1776 
1777 
testTicket11985()1778 void DateIntervalFormatTest::testTicket11985() {
1779     UErrorCode status = U_ZERO_ERROR;
1780     LocalPointer<DateIntervalFormat> fmt(
1781             DateIntervalFormat::createInstance(UDAT_HOUR_MINUTE, Locale::getEnglish(), status));
1782     if (!assertSuccess("createInstance", status)) {
1783         return;
1784     }
1785     UnicodeString pattern;
1786     dynamic_cast<const SimpleDateFormat*>(fmt->getDateFormat())->toPattern(pattern);
1787     assertEquals("Format pattern", u"h:mm\u202Fa", pattern);
1788 }
1789 
1790 // Ticket 11669 - thread safety of DateIntervalFormat::format(). This test failed before
1791 //                the implementation was fixed.
1792 
1793 static const DateIntervalFormat *gIntervalFormatter = nullptr;      // The Formatter to be used concurrently by test threads.
1794 static const DateInterval *gInterval = nullptr;                     // The date interval to be formatted concurrently.
1795 static const UnicodeString *gExpectedResult = nullptr;
1796 
threadFunc11669(int32_t threadNum)1797 void DateIntervalFormatTest::threadFunc11669(int32_t threadNum) {
1798     (void)threadNum;
1799     for (int loop=0; loop<1000; ++loop) {
1800         UErrorCode status = U_ZERO_ERROR;
1801         FieldPosition pos(FieldPosition::DONT_CARE);
1802         UnicodeString result;
1803         gIntervalFormatter->format(gInterval, result, pos, status);
1804         if (U_FAILURE(status)) {
1805             errln("%s:%d %s", __FILE__, __LINE__, u_errorName(status));
1806             return;
1807         }
1808         if (result != *gExpectedResult) {
1809             errln("%s:%d Expected \"%s\", got \"%s\"", __FILE__, __LINE__, CStr(*gExpectedResult)(), CStr(result)());
1810             return;
1811         }
1812     }
1813 }
1814 
testTicket11669()1815 void DateIntervalFormatTest::testTicket11669() {
1816     UErrorCode status = U_ZERO_ERROR;
1817     LocalPointer<DateIntervalFormat> formatter(DateIntervalFormat::createInstance(UDAT_YEAR_MONTH_DAY, Locale::getEnglish(), status), status);
1818     LocalPointer<TimeZone> tz(TimeZone::createTimeZone("America/Los_Angleles"), status);
1819     LocalPointer<Calendar> intervalStart(Calendar::createInstance(*tz, Locale::getEnglish(), status), status);
1820     LocalPointer<Calendar> intervalEnd(Calendar::createInstance(*tz, Locale::getEnglish(), status), status);
1821     if (U_FAILURE(status)) {
1822         errcheckln(status, "%s:%d %s", __FILE__, __LINE__, u_errorName(status));
1823         return;
1824     }
1825 
1826     intervalStart->set(2009, 6, 1, 14, 0);
1827     intervalEnd->set(2009, 6, 2, 14, 0);
1828     DateInterval interval(intervalStart->getTime(status), intervalEnd->getTime(status));
1829     FieldPosition pos(FieldPosition::DONT_CARE);
1830     UnicodeString expectedResult;
1831     formatter->format(&interval, expectedResult, pos, status);
1832     if (U_FAILURE(status)) {
1833         errln("%s:%d %s", __FILE__, __LINE__, u_errorName(status));
1834         return;
1835     }
1836 
1837     gInterval = &interval;
1838     gIntervalFormatter = formatter.getAlias();
1839     gExpectedResult = &expectedResult;
1840 
1841     ThreadPool<DateIntervalFormatTest> threads(this, 4, &DateIntervalFormatTest::threadFunc11669);
1842     threads.start();
1843     threads.join();
1844 
1845     gInterval = nullptr;             // Don't leave dangling pointers lying around. Not strictly necessary.
1846     gIntervalFormatter = nullptr;
1847     gExpectedResult = nullptr;
1848 }
1849 
1850 
1851 // testTicket12065
1852 //    Using a DateIntervalFormat to format shouldn't change its state in any way
1853 //    that changes how the behavior of operator ==.
testTicket12065()1854 void DateIntervalFormatTest::testTicket12065() {
1855     UErrorCode status = U_ZERO_ERROR;
1856     LocalPointer<DateIntervalFormat> formatter(DateIntervalFormat::createInstance(UDAT_YEAR_MONTH_DAY, Locale::getEnglish(), status), status);
1857     if (formatter.isNull()) {
1858         dataerrln("FAIL: DateIntervalFormat::createInstance failed for Locale::getEnglish()");
1859         return;
1860     }
1861     LocalPointer<DateIntervalFormat> clone(formatter->clone());
1862     if (*formatter != *clone) {
1863         errln("%s:%d DateIntervalFormat and clone are not equal.", __FILE__, __LINE__);
1864         return;
1865     }
1866     DateInterval interval((UDate) 1232364615000.0, (UDate) 1328787015000.0);
1867     UnicodeString appendTo;
1868     FieldPosition fpos(FieldPosition::DONT_CARE);
1869     formatter->format(&interval, appendTo, fpos, status);
1870     if (*formatter != *clone) {
1871         errln("%s:%d DateIntervalFormat and clone are not equal after formatting.", __FILE__, __LINE__);
1872         return;
1873     }
1874     if (U_FAILURE(status)) {
1875         errln("%s:%d %s", __FILE__, __LINE__, u_errorName(status));
1876     }
1877 }
1878 
1879 
testFormattedDateInterval()1880 void DateIntervalFormatTest::testFormattedDateInterval() {
1881     IcuTestErrorCode status(*this, "testFormattedDateInterval");
1882     LocalPointer<DateIntervalFormat> fmt(DateIntervalFormat::createInstance(u"dMMMMy", "en-US", status), status);
1883 
1884     {
1885         const char16_t* message = u"FormattedDateInterval test 1";
1886         const char16_t* expectedString = u"July 20\u2009\u2013\u200925, 2018";
1887         LocalPointer<Calendar> input1(Calendar::createInstance("en-GB", status));
1888         if (status.errIfFailureAndReset()) { return; }
1889         LocalPointer<Calendar> input2(Calendar::createInstance("en-GB", status));
1890         if (status.errIfFailureAndReset()) { return; }
1891         input1->set(2018, 6, 20);
1892         input2->set(2018, 6, 25);
1893         FormattedDateInterval result = fmt->formatToValue(*input1, *input2, status);
1894         static const UFieldPositionWithCategory expectedFieldPositions[] = {
1895             // field, begin index, end index
1896             {UFIELD_CATEGORY_DATE, UDAT_MONTH_FIELD, 0, 4},
1897             {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 0, 5, 7},
1898             {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 5, 7},
1899             {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 1, 10, 12},
1900             {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 10, 12},
1901             {UFIELD_CATEGORY_DATE, UDAT_YEAR_FIELD, 14, 18}};
1902         checkMixedFormattedValue(
1903             message,
1904             result,
1905             expectedString,
1906             expectedFieldPositions,
1907             UPRV_LENGTHOF(expectedFieldPositions));
1908     }
1909 
1910     {
1911         const char16_t* message = u"FormattedDateInterval identical dates test: no span field";
1912         const char16_t* expectedString = u"July 20, 2018";
1913         LocalPointer<Calendar> input1(Calendar::createInstance("en-GB", status));
1914         input1->set(2018, 6, 20);
1915         FormattedDateInterval result = fmt->formatToValue(*input1, *input1, status);
1916         static const UFieldPositionWithCategory expectedFieldPositions[] = {
1917             // field, begin index, end index
1918             {UFIELD_CATEGORY_DATE, UDAT_MONTH_FIELD, 0, 4},
1919             {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 5, 7},
1920             {UFIELD_CATEGORY_DATE, UDAT_YEAR_FIELD, 9, 13}};
1921         checkMixedFormattedValue(
1922             message,
1923             result,
1924             expectedString,
1925             expectedFieldPositions,
1926             UPRV_LENGTHOF(expectedFieldPositions));
1927     }
1928 
1929     // Test sample code
1930     {
1931         LocalPointer<Calendar> input1(Calendar::createInstance("en-GB", status));
1932         LocalPointer<Calendar> input2(Calendar::createInstance("en-GB", status));
1933         input1->set(2018, 6, 20);
1934         input2->set(2018, 7, 3);
1935 
1936         // Let fmt be a DateIntervalFormat for locale en-US and skeleton dMMMMy
1937         // Let input1 be July 20, 2018 and input2 be August 3, 2018:
1938         FormattedDateInterval result = fmt->formatToValue(*input1, *input2, status);
1939         assertEquals("Expected output from format",
1940             u"July 20\u2009\u2013\u2009August 3, 2018", result.toString(status));
1941         ConstrainedFieldPosition cfpos;
1942         cfpos.constrainField(UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 0);
1943         if (result.nextPosition(cfpos, status)) {
1944             assertEquals("Expect start index", 0, cfpos.getStart());
1945             assertEquals("Expect end index", 7, cfpos.getLimit());
1946         } else {
1947             // No such span: can happen if input dates are equal.
1948         }
1949         assertFalse("No more than one occurrence of the field",
1950             result.nextPosition(cfpos, status));
1951     }
1952 
1953     // To test the fallback pattern behavior, make a custom DateIntervalInfo.
1954     DateIntervalInfo dtitvinf(status);
1955     dtitvinf.setFallbackIntervalPattern("<< {1} --- {0} >>", status);
1956     fmt.adoptInsteadAndCheckErrorCode(
1957         DateIntervalFormat::createInstance(u"dMMMMy", "en-US", dtitvinf, status),
1958         status);
1959 
1960     {
1961         const char16_t* message = u"FormattedDateInterval with fallback format test 1";
1962         const char16_t* expectedString = u"<< July 25, 2018 --- July 20, 2018 >>";
1963         LocalPointer<Calendar> input1(Calendar::createInstance("en-GB", status));
1964         if (status.errIfFailureAndReset()) { return; }
1965         LocalPointer<Calendar> input2(Calendar::createInstance("en-GB", status));
1966         if (status.errIfFailureAndReset()) { return; }
1967         input1->set(2018, 6, 20);
1968         input2->set(2018, 6, 25);
1969         FormattedDateInterval result = fmt->formatToValue(*input1, *input2, status);
1970         static const UFieldPositionWithCategory expectedFieldPositions[] = {
1971             // field, begin index, end index
1972             {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 1, 3, 16},
1973             {UFIELD_CATEGORY_DATE, UDAT_MONTH_FIELD, 3, 7},
1974             {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 8, 10},
1975             {UFIELD_CATEGORY_DATE, UDAT_YEAR_FIELD, 12, 16},
1976             {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 0, 21, 34},
1977             {UFIELD_CATEGORY_DATE, UDAT_MONTH_FIELD, 21, 25},
1978             {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 26, 28},
1979             {UFIELD_CATEGORY_DATE, UDAT_YEAR_FIELD, 30, 34}};
1980         checkMixedFormattedValue(
1981             message,
1982             result,
1983             expectedString,
1984             expectedFieldPositions,
1985             UPRV_LENGTHOF(expectedFieldPositions));
1986     }
1987 }
1988 
testCreateInstanceForAllLocales()1989 void DateIntervalFormatTest::testCreateInstanceForAllLocales() {
1990     IcuTestErrorCode status(*this, "testCreateInstanceForAllLocales");
1991     int32_t locale_count = 0;
1992     const Locale* locales = icu::Locale::getAvailableLocales(locale_count);
1993     // Iterate through all locales
1994     for (int32_t i = 0; i < locale_count; i++) {
1995         std::unique_ptr<icu::StringEnumeration> calendars(
1996             icu::Calendar::getKeywordValuesForLocale(
1997                 "calendar", locales[i], false, status));
1998         int32_t calendar_count = calendars->count(status);
1999         if (status.errIfFailureAndReset()) { break; }
2000         // In quick mode, only run 1/5 of locale combination
2001         // to make the test run faster.
2002         if (quick && (i % 5 != 0)) continue;
2003         LocalPointer<DateIntervalFormat> fmt(
2004             DateIntervalFormat::createInstance(u"dMMMMy", locales[i], status),
2005             status);
2006         if (status.errIfFailureAndReset(locales[i].getName())) {
2007             continue;
2008         }
2009         // Iterate through all calendars in this locale
2010         for (int32_t j = 0; j < calendar_count; j++) {
2011             // In quick mode, only run 1/7 of locale/calendar combination
2012             // to make the test run faster.
2013             if (quick && ((i * j) % 7 != 0)) continue;
2014             const char* calendar = calendars->next(nullptr, status);
2015             Locale locale(locales[i]);
2016             locale.setKeywordValue("calendar", calendar, status);
2017             fmt.adoptInsteadAndCheckErrorCode(
2018                 DateIntervalFormat::createInstance(u"dMMMMy", locale, status),
2019                 status);
2020             status.errIfFailureAndReset(locales[i].getName());
2021         }
2022     }
2023 }
2024 
testFormatMillisecond()2025 void DateIntervalFormatTest::testFormatMillisecond() {
2026     struct
2027     {
2028         int year;
2029         int month;
2030         int day;
2031         int from_hour;
2032         int from_miniute;
2033         int from_second;
2034         int from_millisecond;
2035         int to_hour;
2036         int to_miniute;
2037         int to_second;
2038         int to_millisecond;
2039         const char* skeleton;
2040         const char16_t* expected;
2041     }
2042     kTestCases [] =
2043     {
2044         //           From            To
2045         //   y  m  d   h  m   s   ms   h  m   s   ms   skeleton  expected
2046         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 321, "ms",     u"23:45"},
2047         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 321, "msS",    u"23:45.3"},
2048         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 321, "msSS",   u"23:45.32"},
2049         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 321, "msSSS",  u"23:45.321"},
2050         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 987, "ms",     u"23:45"},
2051         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 987, "msS",    u"23:45.3\u2009\u2013\u200923:45.9"},
2052         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 987, "msSS",   u"23:45.32\u2009\u2013\u200923:45.98"},
2053         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 987, "msSSS",  u"23:45.321\u2009\u2013\u200923:45.987"},
2054         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 987, "ms",     u"23:45\u2009\u2013\u200923:46"},
2055         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 987, "msS",    u"23:45.3\u2009\u2013\u200923:46.9"},
2056         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 987, "msSS",   u"23:45.32\u2009\u2013\u200923:46.98"},
2057         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 987, "msSSS",  u"23:45.321\u2009\u2013\u200923:46.987"},
2058         { 2019, 2, 10, 1, 23, 45, 321, 2, 24, 45, 987, "ms",     u"23:45\u2009\u2013\u200924:45"},
2059         { 2019, 2, 10, 1, 23, 45, 321, 2, 24, 45, 987, "msS",    u"23:45.3\u2009\u2013\u200924:45.9"},
2060         { 2019, 2, 10, 1, 23, 45, 321, 2, 24, 45, 987, "msSS",   u"23:45.32\u2009\u2013\u200924:45.98"},
2061         { 2019, 2, 10, 1, 23, 45, 321, 2, 24, 45, 987, "msSSS",  u"23:45.321\u2009\u2013\u200924:45.987"},
2062         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 321, "s",      u"45"},
2063         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 321, "sS",     u"45.3"},
2064         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 321, "sSS",    u"45.32"},
2065         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 321, "sSSS",   u"45.321"},
2066         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 987, "s",      u"45"},
2067         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 987, "sS",     u"45.3\u2009\u2013\u200945.9"},
2068         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 987, "sSS",    u"45.32\u2009\u2013\u200945.98"},
2069         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 987, "sSSS",   u"45.321\u2009\u2013\u200945.987"},
2070         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 987, "s",      u"45\u2009\u2013\u200946"},
2071         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 987, "sS",     u"45.3\u2009\u2013\u200946.9"},
2072         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 987, "sSS",    u"45.32\u2009\u2013\u200946.98"},
2073         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 987, "sSSS",   u"45.321\u2009\u2013\u200946.987"},
2074         { 2019, 2, 10, 1, 23, 45, 321, 2, 24, 45, 987, "s",      u"45\u2009\u2013\u200945"},
2075         { 2019, 2, 10, 1, 23, 45, 321, 2, 24, 45, 987, "sS",     u"45.3\u2009\u2013\u200945.9"},
2076         { 2019, 2, 10, 1, 23, 45, 321, 2, 24, 45, 987, "sSS",    u"45.32\u2009\u2013\u200945.98"},
2077         { 2019, 2, 10, 1, 23, 45, 321, 2, 24, 45, 987, "sSSS",   u"45.321\u2009\u2013\u200945.987"},
2078         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 321, "S",      u"3"},
2079         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 321, "SS",     u"32"},
2080         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 321, "SSS",    u"321"},
2081 
2082         // Same millisecond but in different second.
2083         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 321, "S",      u"3\u2009\u2013\u20093"},
2084         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 321, "SS",     u"32\u2009\u2013\u200932"},
2085         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 321, "SSS",    u"321\u2009\u2013\u2009321"},
2086 
2087         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 987, "S",      u"3\u2009\u2013\u20099"},
2088         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 987, "SS",     u"32\u2009\u2013\u200998"},
2089         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 987, "SSS",    u"321\u2009\u2013\u2009987"},
2090         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 987, "S",      u"3\u2009\u2013\u20099"},
2091         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 987, "SS",     u"32\u2009\u2013\u200998"},
2092         { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 987, "SSS",    u"321\u2009\u2013\u2009987"},
2093         { 2019, 2, 10, 1, 23, 45, 321, 2, 24, 45, 987, "S",      u"3\u2009\u2013\u20099"},
2094         { 2019, 2, 10, 1, 23, 45, 321, 2, 24, 45, 987, "SS",     u"32\u2009\u2013\u200998"},
2095         { 2019, 2, 10, 1, 23, 45, 321, 2, 24, 45, 987, "SSS",    u"321\u2009\u2013\u2009987"},
2096         { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr, nullptr},
2097     };
2098 
2099     const Locale &enLocale = Locale::getEnglish();
2100     IcuTestErrorCode status(*this, "testFormatMillisecond");
2101     LocalPointer<Calendar> calendar(Calendar::createInstance(enLocale, status));
2102     if (status.errIfFailureAndReset()) { return; }
2103 
2104     for (int32_t i = 0; kTestCases[i].year > 0; i++) {
2105         LocalPointer<DateIntervalFormat> fmt(DateIntervalFormat::createInstance(
2106             kTestCases[i].skeleton, enLocale, status));
2107         if (status.errIfFailureAndReset()) { continue; }
2108 
2109         calendar->clear();
2110         calendar->set(kTestCases[i].year, kTestCases[i].month, kTestCases[i].day,
2111                       kTestCases[i].from_hour, kTestCases[i].from_miniute, kTestCases[i].from_second);
2112         UDate from = calendar->getTime(status) + kTestCases[i].from_millisecond;
2113         if (status.errIfFailureAndReset()) { continue; }
2114 
2115         calendar->clear();
2116         calendar->set(kTestCases[i].year, kTestCases[i].month, kTestCases[i].day,
2117                       kTestCases[i].to_hour, kTestCases[i].to_miniute, kTestCases[i].to_second);
2118         UDate to = calendar->getTime(status) + kTestCases[i].to_millisecond;
2119         FormattedDateInterval  res = fmt->formatToValue(DateInterval(from, to), status);
2120         if (status.errIfFailureAndReset()) { continue; }
2121 
2122         UnicodeString formatted = res.toString(status);
2123         if (status.errIfFailureAndReset()) { continue; }
2124         if (formatted != kTestCases[i].expected) {
2125             std::string tmp1;
2126             std::string tmp2;
2127             errln("Case %d for skeleton %s : Got %s but expect %s",
2128                   i, kTestCases[i].skeleton, formatted.toUTF8String<std::string>(tmp1).c_str(),
2129                   UnicodeString(kTestCases[i].expected).toUTF8String<std::string>(tmp2).c_str());
2130         }
2131     }
2132 }
2133 
testTicket20707()2134 void DateIntervalFormatTest::testTicket20707() {
2135     IcuTestErrorCode status(*this, "testTicket20707");
2136 
2137     const char16_t timeZone[] = u"UTC";
2138     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"};
2139 
2140     // Clomuns: hh, HH, kk, KK, jj, JJs, CC
2141     UnicodeString expected[][7] = {
2142         // Hour-cycle: k
2143         {u"12\u202FAM", u"24", u"24", u"12\u202FAM", u"24", u"0 (hour: 24)", u"12\u202FAM"},
2144         // Hour-cycle: H
2145         {u"12\u202FAM", u"00", u"00", u"12\u202FAM", u"00", u"0 (hour: 00)", u"12\u202FAM"},
2146         // Hour-cycle: h
2147         {u"12\u202FAM", u"00", u"00", u"12\u202FAM", u"12\u202FAM", u"0 (hour: 12)", u"12\u202FAM"},
2148         // Hour-cycle: K
2149         {u"0\u202FAM", u"00", u"00", u"0\u202FAM", u"0\u202FAM", u"0 (hour: 00)", u"0\u202FAM"},
2150         {u"12\u202FAM", u"00", u"00", u"12\u202FAM", u"12\u202FAM", u"0 (hour: 12)", u"12\u202FAM"},
2151         {u"12\u202FAM", u"00", u"00", u"12\u202FAM", u"12\u202FAM", u"0 (hour: 12)", u"12\u202FAM"},
2152         // Hour-cycle: K
2153         {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"}
2154     };
2155 
2156     int32_t i = 0;
2157     for (Locale locale : locales) {
2158         int32_t j = 0;
2159         for (const UnicodeString skeleton : {u"hh", u"HH", u"kk", u"KK", u"jj", u"JJs", u"CC"}) {
2160             LocalPointer<DateIntervalFormat> dtifmt(DateIntervalFormat::createInstance(skeleton, locale, status));
2161             if (status.errDataIfFailureAndReset()) {
2162                 continue;
2163             }
2164             FieldPosition fposition;
2165             UnicodeString result;
2166             LocalPointer<Calendar> calendar(Calendar::createInstance(TimeZone::createTimeZone(timeZone), status));
2167             calendar->setTime(UDate(1563235200000), status);
2168             dtifmt->format(*calendar, *calendar, result, fposition, status);
2169 
2170             const char* localeID = locale.getName();
2171             assertEquals(localeID, expected[i][j++], result);
2172         }
2173         i++;
2174     }
2175 }
2176 
getCategoryAndField(const FormattedDateInterval & formatted,std::vector<int32_t> & categories,std::vector<int32_t> & fields,IcuTestErrorCode & status)2177 void DateIntervalFormatTest::getCategoryAndField(
2178         const FormattedDateInterval& formatted,
2179         std::vector<int32_t>& categories,
2180         std::vector<int32_t>& fields,
2181         IcuTestErrorCode& status) {
2182     categories.clear();
2183     fields.clear();
2184     ConstrainedFieldPosition cfpos;
2185     while (formatted.nextPosition(cfpos, status)) {
2186         categories.push_back(cfpos.getCategory());
2187         fields.push_back(cfpos.getField());
2188     }
2189 }
2190 
verifyCategoryAndField(const FormattedDateInterval & formatted,const std::vector<int32_t> & categories,const std::vector<int32_t> & fields,IcuTestErrorCode & status)2191 void DateIntervalFormatTest::verifyCategoryAndField(
2192         const FormattedDateInterval& formatted,
2193         const std::vector<int32_t>& categories,
2194         const std::vector<int32_t>& fields,
2195         IcuTestErrorCode& status) {
2196     ConstrainedFieldPosition cfpos;
2197     int32_t i = 0;
2198     while (formatted.nextPosition(cfpos, status)) {
2199         assertEquals("Category", cfpos.getCategory(), categories[i]);
2200         assertEquals("Field", cfpos.getField(), fields[i]);
2201         i++;
2202     }
2203 }
2204 
testTicket21222GregorianEraDiff()2205 void DateIntervalFormatTest::testTicket21222GregorianEraDiff() {
2206     IcuTestErrorCode status(*this, "   ");
2207 
2208     LocalPointer<Calendar> cal(Calendar::createInstance(*TimeZone::getGMT(), status));
2209     if (U_FAILURE(status)) {
2210         errln("Failure encountered: %s", u_errorName(status));
2211         return;
2212     }
2213     std::vector<int32_t> expectedCategory;
2214     std::vector<int32_t> expectedField;
2215 
2216     // Test Gregorian calendar
2217     LocalPointer<DateIntervalFormat> g(
2218         DateIntervalFormat::createInstance(
2219             u"h", Locale("en"), status));
2220     if (U_FAILURE(status)) {
2221         errln("Failure encountered: %s", u_errorName(status));
2222         return;
2223     }
2224     g->setTimeZone(*(TimeZone::getGMT()));
2225     cal->setTime(Calendar::getNow(), status);
2226     cal->set(123, UCAL_APRIL, 5, 6, 0);
2227     FormattedDateInterval formatted;
2228 
2229     UDate date0123Apr5AD = cal->getTime(status);
2230 
2231     cal->set(UCAL_YEAR, 124);
2232     UDate date0124Apr5AD = cal->getTime(status);
2233 
2234     cal->set(UCAL_ERA, 0);
2235     UDate date0124Apr5BC = cal->getTime(status);
2236 
2237     cal->set(UCAL_YEAR, 123);
2238     UDate date0123Apr5BC = cal->getTime(status);
2239 
2240     DateInterval bothAD(date0123Apr5AD, date0124Apr5AD);
2241     DateInterval bothBC(date0124Apr5BC, date0123Apr5BC);
2242     DateInterval BCtoAD(date0123Apr5BC, date0124Apr5AD);
2243 
2244     formatted = g->formatToValue(bothAD, status);
2245     assertEquals("Gregorian - calendar both dates in AD",
2246                  u"4/5/123, 6\u202FAM\u2009\u2013\u20094/5/124, 6\u202FAM",
2247                  formatted.toString(status));
2248 
2249     formatted = g->formatToValue(bothBC, status);
2250     assertEquals("Gregorian - calendar both dates in BC",
2251                  u"4/5/124, 6\u202FAM\u2009\u2013\u20094/5/123, 6\u202FAM",
2252                  formatted.toString(status));
2253 
2254     formatted = g->formatToValue(BCtoAD, status);
2255     assertEquals("Gregorian - BC to AD",
2256                  u"4/5/123 BC, 6\u202FAM\u2009\u2013\u20094/5/124 AD, 6\u202FAM",
2257                  formatted.toString(status));
2258 }
2259 
testTicket21222ROCEraDiff()2260 void DateIntervalFormatTest::testTicket21222ROCEraDiff() {
2261     IcuTestErrorCode status(*this, "testTicket21222ROCEraDiff");
2262 
2263     LocalPointer<Calendar> cal(Calendar::createInstance(*TimeZone::getGMT(), status));
2264     if (U_FAILURE(status)) {
2265         errln("Failure encountered: %s", u_errorName(status));
2266         return;
2267     }
2268     std::vector<int32_t> expectedCategory;
2269     std::vector<int32_t> expectedField;
2270 
2271     // Test roc calendar
2272     LocalPointer<DateIntervalFormat> roc(
2273         DateIntervalFormat::createInstance(
2274             u"h", Locale("zh-Hant-TW@calendar=roc"), status));
2275     if (U_FAILURE(status)) {
2276         errln("Failure encountered: %s", u_errorName(status));
2277         return;
2278     }
2279     roc->setTimeZone(*(TimeZone::getGMT()));
2280 
2281     FormattedDateInterval formatted;
2282     // set date1910Jan2 to 1910/1/2 AD which is prior to MG
2283     cal->set(1910, UCAL_JANUARY, 2, 6, 0);
2284     UDate date1910Jan2 = cal->getTime(status);
2285 
2286     // set date1911Jan2 to 1911/1/2 AD which is also prior to MG
2287     cal->set(UCAL_YEAR, 1911);
2288     UDate date1911Jan2 = cal->getTime(status);
2289 
2290     // set date1912Jan2 to 1912/1/2 AD which is after MG
2291     cal->set(UCAL_YEAR, 1912);
2292     UDate date1912Jan2 = cal->getTime(status);
2293 
2294     // set date1913Jan2 to 1913/1/2 AD which is also after MG
2295     cal->set(UCAL_YEAR, 1913);
2296     UDate date1913Jan2 = cal->getTime(status);
2297 
2298     DateInterval bothBeforeMG(date1910Jan2, date1911Jan2);
2299     DateInterval beforeAfterMG(date1911Jan2, date1913Jan2);
2300     DateInterval bothAfterMG(date1912Jan2, date1913Jan2);
2301 
2302     formatted = roc->formatToValue(bothAfterMG, status);
2303     assertEquals("roc calendar - both dates in MG Era",
2304                  u"民國1/1/2 上午6時\u2009\u2013\u2009民國2/1/2 上午6時",
2305                  formatted.toString(status));
2306     getCategoryAndField(formatted, expectedCategory,
2307                         expectedField, status);
2308 
2309     formatted = roc->formatToValue(beforeAfterMG, status);
2310     assertEquals("roc calendar - prior MG Era and in MG Era",
2311                  u"民國前1/1/2 上午6時\u2009\u2013\u2009民國2/1/2 上午6時",
2312                  formatted.toString(status));
2313     verifyCategoryAndField(formatted, expectedCategory, expectedField, status);
2314 
2315     formatted = roc->formatToValue(bothBeforeMG, status);
2316     assertEquals("roc calendar - both dates prior MG Era",
2317                  u"民國前2/1/2 上午6時\u2009\u2013\u2009民國前1/1/2 上午6時",
2318                  formatted.toString(status));
2319     verifyCategoryAndField(formatted, expectedCategory, expectedField, status);
2320 }
2321 
testTicket21222JapaneseEraDiff()2322 void DateIntervalFormatTest::testTicket21222JapaneseEraDiff() {
2323     IcuTestErrorCode status(*this, "testTicket21222JapaneseEraDiff");
2324 
2325     LocalPointer<Calendar> cal(Calendar::createInstance(*TimeZone::getGMT(), status));
2326     if (U_FAILURE(status)) {
2327         errln("Failure encountered: %s", u_errorName(status));
2328         return;
2329     }
2330     std::vector<int32_t> expectedCategory;
2331     std::vector<int32_t> expectedField;
2332 
2333     // Test roc calendar
2334     // Test Japanese calendar
2335     LocalPointer<DateIntervalFormat> japanese(
2336         DateIntervalFormat::createInstance(
2337             u"h", Locale("ja@calendar=japanese"), status));
2338     if (U_FAILURE(status)) {
2339         errln("Failure encountered: %s", u_errorName(status));
2340         return;
2341     }
2342     japanese->setTimeZone(*(TimeZone::getGMT()));
2343 
2344     FormattedDateInterval formatted;
2345 
2346     cal->set(2019, UCAL_MARCH, 2, 6, 0);
2347     UDate date2019Mar2 = cal->getTime(status);
2348 
2349     cal->set(UCAL_MONTH, UCAL_APRIL);
2350     cal->set(UCAL_DAY_OF_MONTH, 3);
2351     UDate date2019Apr3 = cal->getTime(status);
2352 
2353     cal->set(UCAL_MONTH, UCAL_MAY);
2354     cal->set(UCAL_DAY_OF_MONTH, 4);
2355     UDate date2019May4 = cal->getTime(status);
2356 
2357     cal->set(UCAL_MONTH, UCAL_JUNE);
2358     cal->set(UCAL_DAY_OF_MONTH, 5);
2359     UDate date2019Jun5 = cal->getTime(status);
2360 
2361     DateInterval bothBeforeReiwa(date2019Mar2, date2019Apr3);
2362     DateInterval beforeAfterReiwa(date2019Mar2, date2019May4);
2363     DateInterval bothAfterReiwa(date2019May4, date2019Jun5);
2364 
2365     formatted = japanese->formatToValue(bothAfterReiwa, status);
2366     assertEquals("japanese calendar - both dates in Reiwa",
2367                  u"R1/5/4 午前6時~R1/6/5 午前6時",
2368                  formatted.toString(status));
2369     getCategoryAndField(formatted, expectedCategory,
2370                         expectedField, status);
2371 
2372     formatted = japanese->formatToValue(bothBeforeReiwa, status);
2373     assertEquals("japanese calendar - both dates before Reiwa",
2374                  u"H31/3/2 午前6時~H31/4/3 午前6時",
2375                  formatted.toString(status));
2376     verifyCategoryAndField(formatted, expectedCategory, expectedField, status);
2377 
2378     formatted = japanese->formatToValue(beforeAfterReiwa, status);
2379     assertEquals("japanese calendar - date before and in Reiwa",
2380                  u"H31/3/2 午前6時~R1/5/4 午前6時",
2381                  formatted.toString(status));
2382     verifyCategoryAndField(formatted, expectedCategory, expectedField, status);
2383 }
2384 
testTicket21939()2385 void DateIntervalFormatTest::testTicket21939() {
2386     IcuTestErrorCode err(*this, "testTicket21939");
2387     LocalPointer<DateIntervalFormat> dif(DateIntervalFormat::createInstance(u"rMdhm", Locale::forLanguageTag("en-u-ca-chinese", err), err));
2388 
2389     if (assertSuccess("Error creating DateIntervalFormat", err)) {
2390         const DateFormat* df = dif->getDateFormat();
2391         const SimpleDateFormat* sdf = dynamic_cast<const SimpleDateFormat*>(df);
2392         UnicodeString pattern;
2393         assertEquals("Wrong pattern", u"M/d/r, h:mm\u202Fa", sdf->toPattern(pattern));
2394     }
2395 
2396     // additional tests for the related ICU-22202
2397     dif.adoptInstead(DateIntervalFormat::createInstance(u"Lh", Locale::getEnglish(), err));
2398     if (assertSuccess("Error creating DateIntervalFormat", err)) {
2399         const DateFormat* df = dif->getDateFormat();
2400         const SimpleDateFormat* sdf = dynamic_cast<const SimpleDateFormat*>(df);
2401         UnicodeString pattern;
2402         assertEquals("Wrong pattern", u"L, h\u202Fa", sdf->toPattern(pattern));
2403     }
2404     dif.adoptInstead(DateIntervalFormat::createInstance(u"UH", Locale::forLanguageTag("en-u-ca-chinese", err), err));
2405     if (assertSuccess("Error creating DateIntervalFormat", err)) {
2406         const DateFormat* df = dif->getDateFormat();
2407         const SimpleDateFormat* sdf = dynamic_cast<const SimpleDateFormat*>(df);
2408         UnicodeString pattern;
2409         assertEquals("Wrong pattern", u"r(U), HH", sdf->toPattern(pattern));
2410     }
2411 }
2412 
testTicket20710_FieldIdentity()2413 void DateIntervalFormatTest::testTicket20710_FieldIdentity() {
2414     IcuTestErrorCode status(*this, "testTicket20710_FieldIdentity");
2415     LocalPointer<DateIntervalFormat> dtifmt(DateIntervalFormat::createInstance("eeeeMMMddyyhhmma", "de-CH", status));
2416     LocalPointer<Calendar> calendar1(Calendar::createInstance(TimeZone::createTimeZone(u"CET"), status));
2417     calendar1->setTime(UDate(1563235200000), status);
2418     LocalPointer<Calendar> calendar2(Calendar::createInstance(TimeZone::createTimeZone(u"CET"), status));
2419     calendar2->setTime(UDate(1564235200000), status);
2420 
2421     {
2422         auto fv = dtifmt->formatToValue(*calendar1, *calendar2, status);
2423         ConstrainedFieldPosition cfp;
2424         cfp.constrainCategory(UFIELD_CATEGORY_DATE_INTERVAL_SPAN);
2425         assertTrue("Span field should be in non-identity formats", fv.nextPosition(cfp, status));
2426     }
2427     {
2428         auto fv = dtifmt->formatToValue(*calendar1, *calendar1, status);
2429         ConstrainedFieldPosition cfp;
2430         cfp.constrainCategory(UFIELD_CATEGORY_DATE_INTERVAL_SPAN);
2431         assertFalse("Span field should not be in identity formats", fv.nextPosition(cfp, status));
2432     }
2433 }
2434 
testTicket20710_IntervalIdentity()2435 void DateIntervalFormatTest::testTicket20710_IntervalIdentity() {
2436     IcuTestErrorCode status(*this, "testTicket20710_IntervalIdentity");
2437 
2438     const char16_t timeZone[] = u"PST";
2439     int32_t count = 0;
2440     const Locale* locales = Locale::getAvailableLocales(count);
2441     const UnicodeString skeletons[] = {
2442         u"EEEEMMMMdyhmmssazzzz",
2443         u"EEEEMMMMdyhhmmssazzzz",
2444         u"EEEEMMMMddyyyyhhmmssvvvva",
2445         u"EEEEMMMMddhmszza",
2446         u"EEMMMMddyyhhzza",
2447         u"eeeeMMMddyyhhmma",
2448         u"MMddyyyyhhmmazzzz",
2449         u"hhmmazzzz",
2450         u"hmmssazzzz",
2451         u"hhmmsszzzz",
2452         u"MMddyyyyhhmmzzzz"
2453     };
2454 
2455     Locale quickLocales[] = {
2456         {"en"}, {"es"}, {"sr"}, {"zh"}
2457     };
2458     if (quick) {
2459         locales = quickLocales;
2460         count = UPRV_LENGTHOF(quickLocales);
2461     }
2462 
2463     for (int32_t i = 0; i < count; i++) {
2464         const Locale locale = locales[i];
2465         LocalPointer<DateTimePatternGenerator> gen(DateTimePatternGenerator::createInstance(locale, status));
2466         LocalPointer<Calendar> calendar(Calendar::createInstance(TimeZone::createTimeZone(timeZone), status));
2467         calendar->setTime(UDate(1563235200000), status);
2468         for (auto skeleton : skeletons) {
2469             LocalPointer<DateIntervalFormat> dtifmt(DateIntervalFormat::createInstance(skeleton, locale, status));
2470 
2471             FieldPosition fposition;
2472             UnicodeString resultIntervalFormat;
2473             dtifmt->format(*calendar, *calendar, resultIntervalFormat, fposition, status);
2474 
2475             UnicodeString pattern = gen->getBestPattern(skeleton, status);
2476             SimpleDateFormat dateFormat(pattern, locale, status);
2477 
2478             FieldPositionIterator fpositer;
2479             UnicodeString resultDateFormat;
2480 
2481             dateFormat.format(*calendar, resultDateFormat, &fpositer, status);
2482             assertEquals("DateIntervalFormat should fall back to DateFormat in the identity format", resultDateFormat, resultIntervalFormat);
2483         }
2484     }
2485 
2486 }
2487 
2488 #endif /* #if !UCONFIG_NO_FORMATTING */
2489