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