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