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