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