blob: f2774433296a4b6dddf169fc9e14f29daa0fcb26 [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)
Frank Tangd2858cb2022-04-08 20:34:12 -07001110 // (should behave the same as h and H if not overridden in locale ID)
1111 "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "KK", "12 \\u2013 1 AM",
1112 "de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "kk", "00\\u201301 Uhr",
1113 // (overriding hour cycle in locale ID should affect both h and K [or both H and k])
1114 "en-u-hc-h11", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hh", "0 \\u2013 1 AM",
1115 "en-u-hc-h11", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "KK", "0 \\u2013 1 AM",
1116 "de-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "HH", "24\\u201301 Uhr",
1117 "de-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "kk", "24\\u201301 Uhr",
1118 // (overriding hour cycle to h11 should NOT affect H and k; overriding to h24 should NOT affect h and K)
1119 "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "HH", "00 \\u2013 01",
1120 "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "kk", "00 \\u2013 01",
1121 "en-u-hc-h11", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "HH", "00 \\u2013 01",
1122 "en-u-hc-h11", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "kk", "00 \\u2013 01",
1123 "de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hh", "12 \\u2013 1 Uhr AM",
1124 "de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "KK", "12 \\u2013 1 Uhr AM",
1125 "de-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hh", "12 \\u2013 1 Uhr AM",
1126 "de-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "KK", "12 \\u2013 1 Uhr AM",
Frank Tang3e05d9d2021-11-08 14:04:04 -08001127
1128 // different lengths of the 'a' field
1129 "en", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "ha", "10 AM \\u2013 1 PM",
1130 "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "ha", "12 \\u2013 1 AM",
1131 "en", "CE 2010 09 27 10:00:00", "CE 2010 09 27 12:00:00", "haaaaa", "10 a \\u2013 12 p",
1132 "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "haaaaa", "12 \\u2013 1 a",
1133
1134 // j (ICU-21155)
1135 "en", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "jj", "10 AM \\u2013 1 PM",
1136 "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "jj", "12 \\u2013 1 AM",
1137 "en", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "jjjjj", "10 a \\u2013 1 p",
1138 "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "jjjjj", "12 \\u2013 1 a",
1139 "de", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "jj", "10\\u201313 Uhr",
1140 "de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "jj", "00\\u201301 Uhr",
1141 "de", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "jjjjj", "10\\u201313 Uhr",
1142 "de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "jjjjj", "00\\u201301 Uhr",
1143
1144 // b and B
1145 "en", "CE 2010 09 27 10:00:00", "CE 2010 09 27 12:00:00", "hb", "10 AM \\u2013 12 noon",
1146 "en", "CE 2010 09 27 10:00:00", "CE 2010 09 27 12:00:00", "hbbbbb", "10 a \\u2013 12 n",
1147 "en", "CE 2010 09 27 13:00:00", "CE 2010 09 27 14:00:00", "hb", "1 \\u2013 2 PM",
1148 "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",
1149 "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hB", "12 \\u2013 1 at night",
1150
1151 // J
1152 "en", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "J", "10 \\u2013 1",
1153 "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "J", "12 \\u2013 1",
1154 "de", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "J", "10\\u201313 Uhr",
1155 "de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "J", "00\\u201301 Uhr",
1156
1157 // C
1158 // (for English and German, C should do the same thing as j)
1159 "en", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "CC", "10 AM \\u2013 1 PM",
1160 "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "CC", "12 \\u2013 1 AM",
1161 "en", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "CCCCC", "10 a \\u2013 1 p",
1162 "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "CCCCC", "12 \\u2013 1 a",
1163 "de", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "CC", "10\\u201313 Uhr",
1164 "de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "CC", "00\\u201301 Uhr",
1165 "de", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "CCCCC", "10\\u201313 Uhr",
1166 "de", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "CCCCC", "00\\u201301 Uhr",
1167 // (for zh_HK and hi_IN, j maps to ha, but C maps to hB)
1168 "zh_HK", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "jj", "\\u4E0A\\u534810\\u6642\\u81F3\\u4E0B\\u53481\\u6642",
1169 "zh_HK", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "jj", "\\u4E0A\\u534812\\u6642\\u81F31\\u6642",
1170 "zh_HK", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "hB", "\\u4E0A\\u534810\\u6642 \\u2013 \\u4E0B\\u53481\\u6642",
1171 "zh_HK", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hB", "\\u51CC\\u666812\\u20131\\u6642",
1172 "zh_HK", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "CC", "\\u4E0A\\u534810\\u6642\\u81F3\\u4E0B\\u53481\\u6642",
1173 "zh_HK", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "CC", "\\u4E0A\\u534812\\u6642\\u81F31\\u6642",
1174 "hi_IN", "CE 2010 09 27 10:00:00", "CE 2010 09 27 13:00:00", "jj", "10 am \\u2013 1 pm",
1175 "hi_IN", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "jj", "12\\u20131 am",
1176 "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",
1177 "hi_IN", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hB", "\\u0930\\u093E\\u0924 12\\u20131",
1178 "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",
1179 "hi_IN", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "CC", "\\u0930\\u093E\\u0924 12\\u20131",
1180
Frank Tangd2858cb2022-04-08 20:34:12 -07001181 // regression test for ICU-21342
1182 "en-gb-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 10:00:00", "kk", "24\\u201310",
1183 "en-gb-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 11:00:00", "kk", "24\\u201311",
1184 "en-gb-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 12:00:00", "kk", "24\\u201312",
1185 "en-gb-u-hc-h24", "CE 2010 09 27 00:00:00", "CE 2010 09 27 13:00:00", "kk", "24\\u201313",
Frank Tang3e05d9d2021-11-08 14:04:04 -08001186
Frank Tangd2858cb2022-04-08 20:34:12 -07001187 // regression test for ICU-21343
1188 "de", "CE 2010 09 27 01:00:00", "CE 2010 09 27 10:00:00", "KK", "1 \\u2013 10 Uhr AM",
1189
1190 // regression test for ICU-21154 (single-date ranges should use the same hour cycle as multi-date ranges)
1191 "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 00:00:00", "hh", "12 AM",
1192 "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "hh", "12 \\u2013 1 AM",
1193 "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 00:00:00", "KK", "12 AM",
1194 "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "KK", "12 \\u2013 1 AM", // (this was producing "0 - 1 AM" before)
1195 "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 00:00:00", "jj", "12 AM",
1196 "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "jj", "12 \\u2013 1 AM",
Frank Tange5b846b2022-04-15 11:06:33 -07001197
1198 // regression test for ICU-21984 (multiple day-period characters in date-interval patterns)
1199 "en", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "MMMdhhmma", "Sep 27, 12:00 \\u2013 1:00 AM",
1200 "sq", "CE 2010 09 27 00:00:00", "CE 2010 09 27 01:00:00", "Bhm", "12:00 \\u2013 1:00 e nat\\u00EBs",
Frank Tang3e05d9d2021-11-08 14:04:04 -08001201 };
1202 expect(DATA, UPRV_LENGTHOF(DATA));
1203}
1204
1205
1206void DateIntervalFormatTest::expect(const char** data, int32_t data_length) {
1207 int32_t i = 0;
1208 UErrorCode ec = U_ZERO_ERROR;
1209 UnicodeString str, str2;
1210 const char* pattern = data[i++];
1211
1212 while (i<data_length) {
1213 const char* locName = data[i++];
1214 const char* datestr = data[i++];
1215 const char* datestr_2 = data[i++];
1216
1217 Locale loc(locName);
1218 LocalPointer<Calendar> defCal(Calendar::createInstance(loc, ec));
1219 if (U_FAILURE(ec)) {
1220 dataerrln("Calendar::createInstance fails for loc %s with: %s", locName, u_errorName(ec));
1221 return;
1222 }
1223 const char* calType = defCal->getType();
1224
1225 Locale refLoc("root");
1226 if (calType) {
1227 refLoc.setKeywordValue("calendar", calType, ec);
1228 }
1229 SimpleDateFormat ref(pattern, refLoc, ec);
1230 logln( "case %d, locale: %s\n", (i-1)/5, locName);
1231 if (U_FAILURE(ec)) {
1232 dataerrln("contruct SimpleDateFormat in expect failed: %s", u_errorName(ec));
1233 return;
1234 }
1235
1236 // 'f'
1237 logln("original date: %s - %s\n", datestr, datestr_2);
1238 UDate date = ref.parse(ctou(datestr), ec);
1239 if (!assertSuccess("parse 1st data in expect", ec)) return;
1240 UDate date_2 = ref.parse(ctou(datestr_2), ec);
1241 if (!assertSuccess("parse 2nd data in expect", ec)) return;
1242 DateInterval dtitv(date, date_2);
1243
1244 const UnicodeString& oneSkeleton(ctou(data[i++]));
1245
1246 DateIntervalFormat* dtitvfmt = DateIntervalFormat::createInstance(oneSkeleton, loc, ec);
1247 if (!assertSuccess("createInstance(skeleton) in expect", ec)) return;
1248 FieldPosition pos(FieldPosition::DONT_CARE);
1249 dtitvfmt->format(&dtitv, str.remove(), pos, ec);
1250 if (!assertSuccess("format in expect", ec)) return;
1251 assertEquals((UnicodeString)"\"" + locName + "\\" + oneSkeleton + "\\" + ctou(datestr) + "\\" + ctou(datestr_2) + "\"", ctou(data[i++]), str);
1252
1253 logln("interval date:" + str + "\"" + locName + "\", "
1254 + "\"" + datestr + "\", "
1255 + "\"" + datestr_2 + "\", " + oneSkeleton);
1256 delete dtitvfmt;
1257 }
1258}
1259
1260
1261/*
1262 * Test format using user defined DateIntervalInfo
1263 */
1264void DateIntervalFormatTest::testFormatUserDII() {
1265 // first item is date pattern
1266 const char* DATA[] = {
1267 "yyyy MM dd HH:mm:ss",
1268 "en", "2007 10 10 10:10:10", "2008 10 10 10:10:10", "Oct 10, 2007 --- Oct 10, 2008",
1269
1270 "en", "2007 10 10 10:10:10", "2007 11 10 10:10:10", "2007 Oct 10 - Nov 2007",
1271
1272 "en", "2007 11 10 10:10:10", "2007 11 20 10:10:10", "Nov 10, 2007 --- Nov 20, 2007",
1273
1274 "en", "2007 01 10 10:00:10", "2007 01 10 14:10:10", "Jan 10, 2007",
1275
1276 "en", "2007 01 10 10:00:10", "2007 01 10 10:20:10", "Jan 10, 2007",
1277
1278 "en", "2007 01 10 10:10:10", "2007 01 10 10:10:20", "Jan 10, 2007",
1279
1280 "zh", "2007 10 10 10:10:10", "2008 10 10 10:10:10", "2007\\u5e7410\\u670810\\u65e5 --- 2008\\u5e7410\\u670810\\u65e5",
1281
1282 "zh", "2007 10 10 10:10:10", "2007 11 10 10:10:10", "2007 10\\u6708 10 - 11\\u6708 2007",
1283
1284 "zh", "2007 11 10 10:10:10", "2007 11 20 10:10:10", "2007\\u5e7411\\u670810\\u65e5 --- 2007\\u5e7411\\u670820\\u65e5",
1285
1286 "zh", "2007 01 10 10:00:10", "2007 01 10 14:10:10", "2007\\u5e741\\u670810\\u65e5", // (fixed expected result per ticket:6626:)
1287
1288 "zh", "2007 01 10 10:00:10", "2007 01 10 10:20:10", "2007\\u5e741\\u670810\\u65e5", // (fixed expected result per ticket:6626:)
1289
1290 "zh", "2007 01 10 10:10:10", "2007 01 10 10:10:20", "2007\\u5e741\\u670810\\u65e5", // (fixed expected result per ticket:6626:)
1291
1292 "de", "2007 10 10 10:10:10", "2008 10 10 10:10:10", "10. Okt. 2007 --- 10. Okt. 2008",
1293
1294
1295 "de", "2007 11 10 10:10:10", "2007 11 20 10:10:10", "10. Nov. 2007 --- 20. Nov. 2007",
1296
1297 "de", "2007 01 10 10:00:10", "2007 01 10 14:10:10", "10. Jan. 2007",
1298
1299 "de", "2007 01 10 10:00:10", "2007 01 10 10:20:10", "10. Jan. 2007",
1300
1301
1302 "es", "2007 10 10 10:10:10", "2008 10 10 10:10:10", "10 oct 2007 --- 10 oct 2008",
1303
1304 "es", "2007 10 10 10:10:10", "2007 11 10 10:10:10", "2007 oct 10 - nov 2007",
1305
1306 "es", "2007 11 10 10:10:10", "2007 11 20 10:10:10", "10 nov 2007 --- 20 nov 2007",
1307
1308 "es", "2007 01 10 10:00:10", "2007 01 10 14:10:10", "10 ene 2007",
1309
1310 "es", "2007 01 10 10:00:10", "2007 01 10 10:20:10", "10 ene 2007",
1311
1312 "es", "2007 01 10 10:10:10", "2007 01 10 10:10:20", "10 ene 2007",
1313 };
1314 expectUserDII(DATA, UPRV_LENGTHOF(DATA));
1315}
1316
1317/*
1318 * Test format using UDisplayContext
1319 */
1320#define CAP_NONE UDISPCTX_CAPITALIZATION_NONE
1321#define CAP_BEGIN UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE
1322#define CAP_LIST UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU
1323#define CAP_ALONE UDISPCTX_CAPITALIZATION_FOR_STANDALONE
1324#define _DAY (24.0*60.0*60.0*1000.0)
1325
1326void DateIntervalFormatTest::testContext() {
1327 static const UDate startDate = 1285599629000.0; // 2010-Sep-27 0800 in America/Los_Angeles
1328 typedef struct {
1329 const char * locale;
1330 const char * skeleton;
1331 UDisplayContext context;
1332 const UDate deltaDate;
1333 const UChar* expectResult;
1334 } DateIntervalContextItem;
1335 static const DateIntervalContextItem testItems[] = {
1336 { "cs", "MMMEd", CAP_NONE, 60.0*_DAY, u"po 27. 9. – pá 26. 11." },
1337 { "cs", "yMMMM", CAP_NONE, 60.0*_DAY, u"září–listopad 2010" },
1338 { "cs", "yMMMM", CAP_NONE, 1.0*_DAY, u"září 2010" },
1339#if !UCONFIG_NO_BREAK_ITERATION
1340 { "cs", "MMMEd", CAP_BEGIN, 60.0*_DAY, u"Po 27. 9. – pá 26. 11." },
1341 { "cs", "yMMMM", CAP_BEGIN, 60.0*_DAY, u"Září–listopad 2010" },
1342 { "cs", "yMMMM", CAP_BEGIN, 1.0*_DAY, u"Září 2010" },
1343 { "cs", "MMMEd", CAP_LIST, 60.0*_DAY, u"Po 27. 9. – pá 26. 11." },
1344 { "cs", "yMMMM", CAP_LIST, 60.0*_DAY, u"Září–listopad 2010" },
1345 { "cs", "yMMMM", CAP_LIST, 1.0*_DAY, u"Září 2010" },
1346#endif
1347 { "cs", "MMMEd", CAP_ALONE, 60.0*_DAY, u"po 27. 9. – pá 26. 11." },
1348 { "cs", "yMMMM", CAP_ALONE, 60.0*_DAY, u"září–listopad 2010" },
1349 { "cs", "yMMMM", CAP_ALONE, 1.0*_DAY, u"září 2010" },
1350 { nullptr, nullptr, CAP_NONE, 0, nullptr }
1351 };
1352 const DateIntervalContextItem* testItemPtr;
1353 for ( testItemPtr = testItems; testItemPtr->locale != nullptr; ++testItemPtr ) {
1354 UErrorCode status = U_ZERO_ERROR;
1355 Locale locale(testItemPtr->locale);
1356 UnicodeString skeleton(testItemPtr->skeleton, -1, US_INV);
1357 LocalPointer<DateIntervalFormat> fmt(DateIntervalFormat::createInstance(skeleton, locale, status));
1358 if (U_FAILURE(status)) {
1359 errln("createInstance failed for locale %s skeleton %s: %s",
1360 testItemPtr->locale, testItemPtr->skeleton, u_errorName(status));
1361 continue;
1362 }
1363 fmt->adoptTimeZone(TimeZone::createTimeZone("America/Los_Angeles"));
1364
1365 fmt->setContext(testItemPtr->context, status);
1366 if (U_FAILURE(status)) {
1367 errln("setContext failed for locale %s skeleton %s context %04X: %s",
1368 testItemPtr->locale, testItemPtr->skeleton, (unsigned)testItemPtr->context, u_errorName(status));
1369 } else {
1370 UDisplayContext getContext = fmt->getContext(UDISPCTX_TYPE_CAPITALIZATION, status);
1371 if (U_FAILURE(status)) {
1372 errln("getContext failed for locale %s skeleton %s context %04X: %s",
1373 testItemPtr->locale, testItemPtr->skeleton, (unsigned)testItemPtr->context, u_errorName(status));
1374 } else if (getContext != testItemPtr->context) {
1375 errln("getContext failed for locale %s skeleton %s context %04X: got context %04X",
1376 testItemPtr->locale, testItemPtr->skeleton, (unsigned)testItemPtr->context, (unsigned)getContext);
1377 }
1378 }
1379
1380 status = U_ZERO_ERROR;
1381 DateInterval interval(startDate, startDate + testItemPtr->deltaDate);
1382 UnicodeString getResult;
1383 FieldPosition pos(FieldPosition::DONT_CARE);
1384 fmt->format(&interval, getResult, pos, status);
1385 if (U_FAILURE(status)) {
1386 errln("format failed for locale %s skeleton %s context %04X: %s",
1387 testItemPtr->locale, testItemPtr->skeleton, (unsigned)testItemPtr->context, u_errorName(status));
1388 continue;
1389 }
1390 UnicodeString expectResult(true, testItemPtr->expectResult, -1);
1391 if (getResult != expectResult) {
1392 errln(UnicodeString("format expected ") + expectResult + UnicodeString(" but got ") + getResult);
1393 }
1394 }
1395}
1396
1397void DateIntervalFormatTest::testSetIntervalPatternNoSideEffect() {
1398 UErrorCode ec = U_ZERO_ERROR;
1399 LocalPointer<DateIntervalInfo> dtitvinf(new DateIntervalInfo(ec), ec);
1400 if (U_FAILURE(ec)) {
1401 errln("Failure encountered: %s", u_errorName(ec));
1402 return;
1403 }
1404 UnicodeString expected;
1405 dtitvinf->getIntervalPattern(ctou("yMd"), UCAL_DATE, expected, ec);
1406 dtitvinf->setIntervalPattern(ctou("yMd"), UCAL_DATE, ctou("M/d/y \\u2013 d"), ec);
1407 if (U_FAILURE(ec)) {
1408 errln("Failure encountered: %s", u_errorName(ec));
1409 return;
1410 }
1411 dtitvinf.adoptInsteadAndCheckErrorCode(new DateIntervalInfo(ec), ec);
1412 if (U_FAILURE(ec)) {
1413 errln("Failure encountered: %s", u_errorName(ec));
1414 return;
1415 }
1416 UnicodeString actual;
1417 dtitvinf->getIntervalPattern(ctou("yMd"), UCAL_DATE, actual, ec);
1418 if (U_FAILURE(ec)) {
1419 errln("Failure encountered: %s", u_errorName(ec));
1420 return;
1421 }
1422 if (expected != actual) {
1423 errln("DateIntervalInfo.setIntervalPattern should have no side effects.");
1424 }
1425}
1426
1427void DateIntervalFormatTest::testYearFormats() {
1428 const Locale &enLocale = Locale::getEnglish();
1429 UErrorCode status = U_ZERO_ERROR;
1430 LocalPointer<Calendar> fromTime(Calendar::createInstance(enLocale, status));
1431 LocalPointer<Calendar> toTime(Calendar::createInstance(enLocale, status));
1432 if (U_FAILURE(status)) {
1433 errln("Failure encountered: %s", u_errorName(status));
1434 return;
1435 }
1436 // April 26, 113. Three digit year so that we can test 2 digit years;
1437 // 4 digit years with padded 0's and full years.
1438 fromTime->set(113, 3, 26);
1439 // April 28, 113.
1440 toTime->set(113, 3, 28);
1441 {
1442 LocalPointer<DateIntervalFormat> dif(DateIntervalFormat::createInstance("yyyyMd", enLocale, status));
1443 if (U_FAILURE(status)) {
1444 dataerrln("Failure encountered: %s", u_errorName(status));
1445 return;
1446 }
1447 UnicodeString actual;
1448 UnicodeString expected(ctou("4/26/0113 \\u2013 4/28/0113"));
1449 FieldPosition pos;
1450 dif->format(*fromTime, *toTime, actual, pos, status);
1451 if (U_FAILURE(status)) {
1452 errln("Failure encountered: %s", u_errorName(status));
1453 return;
1454 }
1455 if (actual != expected) {
1456 errln("Expected " + expected + ", got: " + actual);
1457 }
1458 }
1459 {
1460 LocalPointer<DateIntervalFormat> dif(DateIntervalFormat::createInstance("yyMd", enLocale, status));
1461 if (U_FAILURE(status)) {
1462 errln("Failure encountered: %s", u_errorName(status));
1463 return;
1464 }
1465 UnicodeString actual;
1466 UnicodeString expected(ctou("4/26/13 \\u2013 4/28/13"));
1467 FieldPosition pos(FieldPosition::DONT_CARE);
1468 dif->format(*fromTime, *toTime, actual, pos, status);
1469 if (U_FAILURE(status)) {
1470 errln("Failure encountered: %s", u_errorName(status));
1471 return;
1472 }
1473 if (actual != expected) {
1474 errln("Expected " + expected + ", got: " + actual);
1475 }
1476 }
1477 {
1478 LocalPointer<DateIntervalFormat> dif(DateIntervalFormat::createInstance("yMd", enLocale, status));
1479 if (U_FAILURE(status)) {
1480 errln("Failure encountered: %s", u_errorName(status));
1481 return;
1482 }
1483 UnicodeString actual;
1484 UnicodeString expected(ctou("4/26/113 \\u2013 4/28/113"));
1485 FieldPosition pos(FieldPosition::DONT_CARE);
1486 dif->format(*fromTime, *toTime, actual, pos, status);
1487 if (U_FAILURE(status)) {
1488 errln("Failure encountered: %s", u_errorName(status));
1489 return;
1490 }
1491 if (actual != expected) {
1492 errln("Expected " + expected + ", got: " + actual);
1493 }
1494 }
1495}
1496
1497void DateIntervalFormatTest::expectUserDII(const char** data,
1498 int32_t data_length) {
1499 int32_t i = 0;
1500 UnicodeString str;
1501 UErrorCode ec = U_ZERO_ERROR;
1502 const char* pattern = data[0];
1503 i++;
1504
1505 while ( i < data_length ) {
1506 const char* locName = data[i++];
1507 Locale loc(locName);
1508 SimpleDateFormat ref(pattern, loc, ec);
1509 if (U_FAILURE(ec)) {
1510 dataerrln("contruct SimpleDateFormat in expectUserDII failed: %s", u_errorName(ec));
1511 return;
1512 }
1513 const char* datestr = data[i++];
1514 const char* datestr_2 = data[i++];
1515 UDate date = ref.parse(ctou(datestr), ec);
1516 if (!assertSuccess("parse in expectUserDII", ec)) return;
1517 UDate date_2 = ref.parse(ctou(datestr_2), ec);
1518 if (!assertSuccess("parse in expectUserDII", ec)) return;
1519 DateInterval dtitv(date, date_2);
1520
1521 ec = U_ZERO_ERROR;
1522 // test user created DateIntervalInfo
1523 DateIntervalInfo* dtitvinf = new DateIntervalInfo(ec);
1524 dtitvinf->setFallbackIntervalPattern("{0} --- {1}", ec);
1525 dtitvinf->setIntervalPattern(UDAT_YEAR_ABBR_MONTH_DAY, UCAL_MONTH, "yyyy MMM d - MMM y",ec);
1526 if (!assertSuccess("DateIntervalInfo::setIntervalPattern", ec)) return;
1527 dtitvinf->setIntervalPattern(UDAT_YEAR_ABBR_MONTH_DAY, UCAL_HOUR_OF_DAY, "yyyy MMM d HH:mm - HH:mm", ec);
1528 if (!assertSuccess("DateIntervalInfo::setIntervalPattern", ec)) return;
1529 DateIntervalFormat* dtitvfmt = DateIntervalFormat::createInstance(UDAT_YEAR_ABBR_MONTH_DAY, loc, *dtitvinf, ec);
1530 delete dtitvinf;
1531 if (!assertSuccess("createInstance(skeleton,dtitvinf) in expectUserDII", ec)) return;
1532 FieldPosition pos(FieldPosition::DONT_CARE);
1533 dtitvfmt->format(&dtitv, str.remove(), pos, ec);
1534 if (!assertSuccess("format in expectUserDII", ec)) return;
1535 assertEquals((UnicodeString)"\"" + locName + "\\" + datestr + "\\" + datestr_2 + "\"", ctou(data[i++]), str);
1536#ifdef DTIFMTTS_DEBUG
1537 char result[1000];
1538 char mesg[1000];
1539 PRINTMESG("interval format using user defined DateIntervalInfo\n");
1540 str.extract(0, str.length(), result, "UTF-8");
1541 sprintf(mesg, "interval date: %s\n", result);
1542 PRINTMESG(mesg);
1543#endif
1544 delete dtitvfmt;
1545 }
1546}
1547
1548
1549void DateIntervalFormatTest::testStress() {
1550 if(quick){
1551 logln("Quick mode: Skipping test");
1552 return;
1553 }
1554 const char* DATA[] = {
1555 "yyyy MM dd HH:mm:ss",
1556 "2007 10 10 10:10:10", "2008 10 10 10:10:10",
1557 "2007 10 10 10:10:10", "2007 11 10 10:10:10",
1558 "2007 11 10 10:10:10", "2007 11 20 10:10:10",
1559 "2007 01 10 10:00:10", "2007 01 10 14:10:10",
1560 "2007 01 10 10:00:10", "2007 01 10 10:20:10",
1561 "2007 01 10 10:10:10", "2007 01 10 10:10:20",
1562 };
1563
1564 const char* testLocale[][3] = {
1565 //{"th", "", ""},
1566 {"en", "", ""},
1567 {"zh", "", ""},
1568 {"de", "", ""},
1569 {"ar", "", ""},
1570 {"en", "GB", ""},
1571 {"fr", "", ""},
1572 {"it", "", ""},
1573 {"nl", "", ""},
1574 {"zh", "TW", ""},
1575 {"ja", "", ""},
1576 {"pt", "BR", ""},
1577 {"ru", "", ""},
1578 {"pl", "", ""},
1579 {"tr", "", ""},
1580 {"es", "", ""},
1581 {"ko", "", ""},
1582 {"sv", "", ""},
1583 {"fi", "", ""},
1584 {"da", "", ""},
1585 {"pt", "PT", ""},
1586 {"ro", "", ""},
1587 {"hu", "", ""},
1588 {"he", "", ""},
1589 {"in", "", ""},
1590 {"cs", "", ""},
1591 {"el", "", ""},
1592 {"no", "", ""},
1593 {"vi", "", ""},
1594 {"bg", "", ""},
1595 {"hr", "", ""},
1596 {"lt", "", ""},
1597 {"sk", "", ""},
1598 {"sl", "", ""},
1599 {"sr", "", ""},
1600 {"ca", "", ""},
1601 {"lv", "", ""},
1602 {"uk", "", ""},
1603 {"hi", "", ""},
1604 };
1605
1606 uint32_t localeIndex;
1607 for ( localeIndex = 0; localeIndex < UPRV_LENGTHOF(testLocale); ++localeIndex ) {
1608 char locName[32];
1609 uprv_strcpy(locName, testLocale[localeIndex][0]);
1610 uprv_strcat(locName, testLocale[localeIndex][1]);
1611 stress(DATA, UPRV_LENGTHOF(DATA), Locale(testLocale[localeIndex][0], testLocale[localeIndex][1], testLocale[localeIndex][2]), locName);
1612 }
1613}
1614
1615
1616void DateIntervalFormatTest::stress(const char** data, int32_t data_length,
1617 const Locale& loc, const char* locName) {
1618 UnicodeString skeleton[] = {
1619 "EEEEdMMMMy",
1620 "dMMMMy",
1621 "dMMMM",
1622 "MMMMy",
1623 "EEEEdMMMM",
1624 "EdMMMy",
1625 "dMMMy",
1626 "dMMM",
1627 "MMMy",
1628 "EdMMM",
1629 "EdMy",
1630 "dMy",
1631 "dM",
1632 "My",
1633 "EdM",
1634 "d",
1635 "Ed",
1636 "y",
1637 "M",
1638 "MMM",
1639 "MMMM",
1640 "hm",
1641 "hmv",
1642 "hmz",
1643 "h",
1644 "hv",
1645 "hz",
1646 "EEddMMyyyy", // following could be normalized
1647 "EddMMy",
1648 "hhmm",
1649 "hhmmzz",
1650 "hms", // following could not be normalized
1651 "dMMMMMy",
1652 "EEEEEdM",
1653 };
1654
1655 int32_t i = 0;
1656 UErrorCode ec = U_ZERO_ERROR;
1657 UnicodeString str, str2;
1658 SimpleDateFormat ref(data[i++], loc, ec);
1659 if (!assertSuccess("construct SimpleDateFormat", ec)) return;
1660
1661#ifdef DTIFMTTS_DEBUG
1662 char result[1000];
1663 char mesg[1000];
1664 sprintf(mesg, "locale: %s\n", locName);
1665 PRINTMESG(mesg);
1666#endif
1667
1668 while (i<data_length) {
1669
1670 // 'f'
1671 const char* datestr = data[i++];
1672 const char* datestr_2 = data[i++];
1673#ifdef DTIFMTTS_DEBUG
1674 sprintf(mesg, "original date: %s - %s\n", datestr, datestr_2);
1675 PRINTMESG(mesg)
1676#endif
1677 UDate date = ref.parse(ctou(datestr), ec);
1678 if (!assertSuccess("parse", ec)) return;
1679 UDate date_2 = ref.parse(ctou(datestr_2), ec);
1680 if (!assertSuccess("parse", ec)) return;
1681 DateInterval dtitv(date, date_2);
1682
1683 for ( uint32_t skeletonIndex = 0;
1684 skeletonIndex < UPRV_LENGTHOF(skeleton);
1685 ++skeletonIndex ) {
1686 const UnicodeString& oneSkeleton = skeleton[skeletonIndex];
1687 DateIntervalFormat* dtitvfmt = DateIntervalFormat::createInstance(oneSkeleton, loc, ec);
1688 if (!assertSuccess("createInstance(skeleton)", ec)) return;
1689 /*
1690 // reset the calendar to be Gregorian calendar for "th"
1691 if ( uprv_strcmp(locName, "th") == 0 ) {
1692 GregorianCalendar* gregCal = new GregorianCalendar(loc, ec);
1693 if (!assertSuccess("GregorianCalendar()", ec)) return;
1694 const DateFormat* dformat = dtitvfmt->getDateFormat();
1695 DateFormat* newOne = dformat->clone();
1696 newOne->adoptCalendar(gregCal);
1697 //dtitvfmt->adoptDateFormat(newOne, ec);
1698 dtitvfmt->setDateFormat(*newOne, ec);
1699 delete newOne;
1700 if (!assertSuccess("adoptDateFormat()", ec)) return;
1701 }
1702 */
1703 FieldPosition pos(FieldPosition::DONT_CARE);
1704 dtitvfmt->format(&dtitv, str.remove(), pos, ec);
1705 if (!assertSuccess("format", ec)) return;
1706#ifdef DTIFMTTS_DEBUG
1707 oneSkeleton.extract(0, oneSkeleton.length(), result, "UTF-8");
1708 sprintf(mesg, "interval by skeleton: %s\n", result);
1709 PRINTMESG(mesg)
1710 str.extract(0, str.length(), result, "UTF-8");
1711 sprintf(mesg, "interval date: %s\n", result);
1712 PRINTMESG(mesg)
1713#endif
1714 delete dtitvfmt;
1715 }
1716
1717 // test user created DateIntervalInfo
1718 ec = U_ZERO_ERROR;
1719 DateIntervalInfo* dtitvinf = new DateIntervalInfo(ec);
1720 dtitvinf->setFallbackIntervalPattern("{0} --- {1}", ec);
1721 dtitvinf->setIntervalPattern(UDAT_YEAR_ABBR_MONTH_DAY, UCAL_MONTH, "yyyy MMM d - MMM y",ec);
1722 if (!assertSuccess("DateIntervalInfo::setIntervalPattern", ec)) return;
1723 dtitvinf->setIntervalPattern(UDAT_YEAR_ABBR_MONTH_DAY, UCAL_HOUR_OF_DAY, "yyyy MMM d HH:mm - HH:mm", ec);
1724 if (!assertSuccess("DateIntervalInfo::setIntervalPattern", ec)) return;
1725 DateIntervalFormat* dtitvfmt = DateIntervalFormat::createInstance(UDAT_YEAR_ABBR_MONTH_DAY, loc, *dtitvinf, ec);
1726 delete dtitvinf;
1727 if (!assertSuccess("createInstance(skeleton,dtitvinf)", ec)) return;
1728 FieldPosition pos(FieldPosition::DONT_CARE);
1729 dtitvfmt->format(&dtitv, str.remove(), pos, ec);
1730 if ( uprv_strcmp(locName, "th") ) {
1731 if (!assertSuccess("format", ec)) return;
1732#ifdef DTIFMTTS_DEBUG
1733 PRINTMESG("interval format using user defined DateIntervalInfo\n");
1734 str.extract(0, str.length(), result, "UTF-8");
1735 sprintf(mesg, "interval date: %s\n", result);
1736 PRINTMESG(mesg)
1737#endif
1738 } else {
1739 // for "th", the default calendar is Budhist,
1740 // not Gregorian.
1741 assertTrue("Default calendar for \"th\" is Budhist", ec == U_ILLEGAL_ARGUMENT_ERROR);
1742 ec = U_ZERO_ERROR;
1743 }
1744 delete dtitvfmt;
1745 }
1746}
1747
1748void DateIntervalFormatTest::testTicket11583_2() {
1749 UErrorCode status = U_ZERO_ERROR;
1750 LocalPointer<DateIntervalFormat> fmt(
1751 DateIntervalFormat::createInstance("yMMM", "es-US", status));
1752 if (!assertSuccess("Error create format object", status)) {
1753 return;
1754 }
1755 DateInterval interval((UDate) 1232364615000.0, (UDate) 1328787015000.0);
1756 UnicodeString appendTo;
1757 FieldPosition fpos(FieldPosition::DONT_CARE);
1758 UnicodeString expected("ene de 2009 \\u2013 feb de 2012");
1759 assertEquals(
1760 "",
1761 expected.unescape(),
1762 fmt->format(&interval, appendTo, fpos, status));
1763 if (!assertSuccess("Error formatting", status)) {
1764 return;
1765 }
1766}
1767
1768
1769void DateIntervalFormatTest::testTicket11985() {
1770 UErrorCode status = U_ZERO_ERROR;
1771 LocalPointer<DateIntervalFormat> fmt(
1772 DateIntervalFormat::createInstance(UDAT_HOUR_MINUTE, Locale::getEnglish(), status));
1773 if (!assertSuccess("createInstance", status)) {
1774 return;
1775 }
1776 UnicodeString pattern;
1777 static_cast<const SimpleDateFormat*>(fmt->getDateFormat())->toPattern(pattern);
1778 assertEquals("Format pattern", "h:mm a", pattern);
1779}
1780
1781// Ticket 11669 - thread safety of DateIntervalFormat::format(). This test failed before
1782// the implementation was fixed.
1783
1784static const DateIntervalFormat *gIntervalFormatter = NULL; // The Formatter to be used concurrently by test threads.
1785static const DateInterval *gInterval = NULL; // The date interval to be formatted concurrently.
1786static const UnicodeString *gExpectedResult = NULL;
1787
1788void DateIntervalFormatTest::threadFunc11669(int32_t threadNum) {
1789 (void)threadNum;
1790 for (int loop=0; loop<1000; ++loop) {
1791 UErrorCode status = U_ZERO_ERROR;
1792 FieldPosition pos(FieldPosition::DONT_CARE);
1793 UnicodeString result;
1794 gIntervalFormatter->format(gInterval, result, pos, status);
1795 if (U_FAILURE(status)) {
1796 errln("%s:%d %s", __FILE__, __LINE__, u_errorName(status));
1797 return;
1798 }
1799 if (result != *gExpectedResult) {
1800 errln("%s:%d Expected \"%s\", got \"%s\"", __FILE__, __LINE__, CStr(*gExpectedResult)(), CStr(result)());
1801 return;
1802 }
1803 }
1804}
1805
1806void DateIntervalFormatTest::testTicket11669() {
1807 UErrorCode status = U_ZERO_ERROR;
1808 LocalPointer<DateIntervalFormat> formatter(DateIntervalFormat::createInstance(UDAT_YEAR_MONTH_DAY, Locale::getEnglish(), status), status);
1809 LocalPointer<TimeZone> tz(TimeZone::createTimeZone("America/Los_Angleles"), status);
1810 LocalPointer<Calendar> intervalStart(Calendar::createInstance(*tz, Locale::getEnglish(), status), status);
1811 LocalPointer<Calendar> intervalEnd(Calendar::createInstance(*tz, Locale::getEnglish(), status), status);
1812 if (U_FAILURE(status)) {
1813 errcheckln(status, "%s:%d %s", __FILE__, __LINE__, u_errorName(status));
1814 return;
1815 }
1816
1817 intervalStart->set(2009, 6, 1, 14, 0);
1818 intervalEnd->set(2009, 6, 2, 14, 0);
1819 DateInterval interval(intervalStart->getTime(status), intervalEnd->getTime(status));
1820 FieldPosition pos(FieldPosition::DONT_CARE);
1821 UnicodeString expectedResult;
1822 formatter->format(&interval, expectedResult, pos, status);
1823 if (U_FAILURE(status)) {
1824 errln("%s:%d %s", __FILE__, __LINE__, u_errorName(status));
1825 return;
1826 }
1827
1828 gInterval = &interval;
1829 gIntervalFormatter = formatter.getAlias();
1830 gExpectedResult = &expectedResult;
1831
1832 ThreadPool<DateIntervalFormatTest> threads(this, 4, &DateIntervalFormatTest::threadFunc11669);
1833 threads.start();
1834 threads.join();
1835
1836 gInterval = NULL; // Don't leave dangling pointers lying around. Not strictly necessary.
1837 gIntervalFormatter = NULL;
1838 gExpectedResult = NULL;
1839}
1840
1841
1842// testTicket12065
1843// Using a DateIntervalFormat to format shouldn't change its state in any way
1844// that changes how the behavior of operator ==.
1845void DateIntervalFormatTest::testTicket12065() {
1846 UErrorCode status = U_ZERO_ERROR;
1847 LocalPointer<DateIntervalFormat> formatter(DateIntervalFormat::createInstance(UDAT_YEAR_MONTH_DAY, Locale::getEnglish(), status), status);
1848 if (formatter.isNull()) {
1849 dataerrln("FAIL: DateIntervalFormat::createInstance failed for Locale::getEnglish()");
1850 return;
1851 }
1852 LocalPointer<DateIntervalFormat> clone(formatter->clone());
1853 if (*formatter != *clone) {
1854 errln("%s:%d DateIntervalFormat and clone are not equal.", __FILE__, __LINE__);
1855 return;
1856 }
1857 DateInterval interval((UDate) 1232364615000.0, (UDate) 1328787015000.0);
1858 UnicodeString appendTo;
1859 FieldPosition fpos(FieldPosition::DONT_CARE);
1860 formatter->format(&interval, appendTo, fpos, status);
1861 if (*formatter != *clone) {
1862 errln("%s:%d DateIntervalFormat and clone are not equal after formatting.", __FILE__, __LINE__);
1863 return;
1864 }
1865 if (U_FAILURE(status)) {
1866 errln("%s:%d %s", __FILE__, __LINE__, u_errorName(status));
1867 }
1868}
1869
1870
1871void DateIntervalFormatTest::testFormattedDateInterval() {
1872 IcuTestErrorCode status(*this, "testFormattedDateInterval");
1873 LocalPointer<DateIntervalFormat> fmt(DateIntervalFormat::createInstance(u"dMMMMy", "en-US", status), status);
1874
1875 {
1876 const char16_t* message = u"FormattedDateInterval test 1";
1877 const char16_t* expectedString = u"July 20 \u2013 25, 2018";
1878 LocalPointer<Calendar> input1(Calendar::createInstance("en-GB", status));
1879 if (status.errIfFailureAndReset()) { return; }
1880 LocalPointer<Calendar> input2(Calendar::createInstance("en-GB", status));
1881 if (status.errIfFailureAndReset()) { return; }
1882 input1->set(2018, 6, 20);
1883 input2->set(2018, 6, 25);
1884 FormattedDateInterval result = fmt->formatToValue(*input1, *input2, status);
1885 static const UFieldPositionWithCategory expectedFieldPositions[] = {
1886 // field, begin index, end index
1887 {UFIELD_CATEGORY_DATE, UDAT_MONTH_FIELD, 0, 4},
1888 {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 0, 5, 7},
1889 {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 5, 7},
1890 {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 1, 10, 12},
1891 {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 10, 12},
1892 {UFIELD_CATEGORY_DATE, UDAT_YEAR_FIELD, 14, 18}};
1893 checkMixedFormattedValue(
1894 message,
1895 result,
1896 expectedString,
1897 expectedFieldPositions,
1898 UPRV_LENGTHOF(expectedFieldPositions));
1899 }
1900
1901 {
1902 const char16_t* message = u"FormattedDateInterval identical dates test: no span field";
1903 const char16_t* expectedString = u"July 20, 2018";
1904 LocalPointer<Calendar> input1(Calendar::createInstance("en-GB", status));
1905 input1->set(2018, 6, 20);
1906 FormattedDateInterval result = fmt->formatToValue(*input1, *input1, status);
1907 static const UFieldPositionWithCategory expectedFieldPositions[] = {
1908 // field, begin index, end index
1909 {UFIELD_CATEGORY_DATE, UDAT_MONTH_FIELD, 0, 4},
1910 {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 5, 7},
1911 {UFIELD_CATEGORY_DATE, UDAT_YEAR_FIELD, 9, 13}};
1912 checkMixedFormattedValue(
1913 message,
1914 result,
1915 expectedString,
1916 expectedFieldPositions,
1917 UPRV_LENGTHOF(expectedFieldPositions));
1918 }
1919
1920 // Test sample code
1921 {
1922 LocalPointer<Calendar> input1(Calendar::createInstance("en-GB", status));
1923 LocalPointer<Calendar> input2(Calendar::createInstance("en-GB", status));
1924 input1->set(2018, 6, 20);
1925 input2->set(2018, 7, 3);
1926
1927 // Let fmt be a DateIntervalFormat for locale en-US and skeleton dMMMMy
1928 // Let input1 be July 20, 2018 and input2 be August 3, 2018:
1929 FormattedDateInterval result = fmt->formatToValue(*input1, *input2, status);
1930 assertEquals("Expected output from format",
1931 u"July 20 \u2013 August 3, 2018", result.toString(status));
1932 ConstrainedFieldPosition cfpos;
1933 cfpos.constrainField(UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 0);
1934 if (result.nextPosition(cfpos, status)) {
1935 assertEquals("Expect start index", 0, cfpos.getStart());
1936 assertEquals("Expect end index", 7, cfpos.getLimit());
1937 } else {
1938 // No such span: can happen if input dates are equal.
1939 }
1940 assertFalse("No more than one occurrence of the field",
1941 result.nextPosition(cfpos, status));
1942 }
1943
1944 // To test the fallback pattern behavior, make a custom DateIntervalInfo.
1945 DateIntervalInfo dtitvinf(status);
1946 dtitvinf.setFallbackIntervalPattern("<< {1} --- {0} >>", status);
1947 fmt.adoptInsteadAndCheckErrorCode(
1948 DateIntervalFormat::createInstance(u"dMMMMy", "en-US", dtitvinf, status),
1949 status);
1950
1951 {
1952 const char16_t* message = u"FormattedDateInterval with fallback format test 1";
1953 const char16_t* expectedString = u"<< July 25, 2018 --- July 20, 2018 >>";
1954 LocalPointer<Calendar> input1(Calendar::createInstance("en-GB", status));
1955 if (status.errIfFailureAndReset()) { return; }
1956 LocalPointer<Calendar> input2(Calendar::createInstance("en-GB", status));
1957 if (status.errIfFailureAndReset()) { return; }
1958 input1->set(2018, 6, 20);
1959 input2->set(2018, 6, 25);
1960 FormattedDateInterval result = fmt->formatToValue(*input1, *input2, status);
1961 static const UFieldPositionWithCategory expectedFieldPositions[] = {
1962 // field, begin index, end index
1963 {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 1, 3, 16},
1964 {UFIELD_CATEGORY_DATE, UDAT_MONTH_FIELD, 3, 7},
1965 {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 8, 10},
1966 {UFIELD_CATEGORY_DATE, UDAT_YEAR_FIELD, 12, 16},
1967 {UFIELD_CATEGORY_DATE_INTERVAL_SPAN, 0, 21, 34},
1968 {UFIELD_CATEGORY_DATE, UDAT_MONTH_FIELD, 21, 25},
1969 {UFIELD_CATEGORY_DATE, UDAT_DATE_FIELD, 26, 28},
1970 {UFIELD_CATEGORY_DATE, UDAT_YEAR_FIELD, 30, 34}};
1971 checkMixedFormattedValue(
1972 message,
1973 result,
1974 expectedString,
1975 expectedFieldPositions,
1976 UPRV_LENGTHOF(expectedFieldPositions));
1977 }
1978}
1979
1980void DateIntervalFormatTest::testCreateInstanceForAllLocales() {
1981 IcuTestErrorCode status(*this, "testCreateInstanceForAllLocales");
1982 int32_t locale_count = 0;
1983 const Locale* locales = icu::Locale::getAvailableLocales(locale_count);
1984 // Iterate through all locales
1985 for (int32_t i = 0; i < locale_count; i++) {
1986 std::unique_ptr<icu::StringEnumeration> calendars(
1987 icu::Calendar::getKeywordValuesForLocale(
1988 "calendar", locales[i], FALSE, status));
1989 int32_t calendar_count = calendars->count(status);
1990 if (status.errIfFailureAndReset()) { break; }
1991 // In quick mode, only run 1/5 of locale combination
1992 // to make the test run faster.
1993 if (quick && (i % 5 != 0)) continue;
1994 LocalPointer<DateIntervalFormat> fmt(
1995 DateIntervalFormat::createInstance(u"dMMMMy", locales[i], status),
1996 status);
1997 if (status.errIfFailureAndReset(locales[i].getName())) {
1998 continue;
1999 }
2000 // Iterate through all calendars in this locale
2001 for (int32_t j = 0; j < calendar_count; j++) {
2002 // In quick mode, only run 1/7 of locale/calendar combination
2003 // to make the test run faster.
2004 if (quick && ((i * j) % 7 != 0)) continue;
2005 const char* calendar = calendars->next(nullptr, status);
2006 Locale locale(locales[i]);
2007 locale.setKeywordValue("calendar", calendar, status);
2008 fmt.adoptInsteadAndCheckErrorCode(
2009 DateIntervalFormat::createInstance(u"dMMMMy", locale, status),
2010 status);
2011 status.errIfFailureAndReset(locales[i].getName());
2012 }
2013 }
2014}
2015
2016void DateIntervalFormatTest::testFormatMillisecond() {
2017 struct
2018 {
2019 int year;
2020 int month;
2021 int day;
2022 int from_hour;
2023 int from_miniute;
2024 int from_second;
2025 int from_millisecond;
2026 int to_hour;
2027 int to_miniute;
2028 int to_second;
2029 int to_millisecond;
2030 const char* skeleton;
2031 const char16_t* expected;
2032 }
2033 kTestCases [] =
2034 {
2035 // From To
2036 // y m d h m s ms h m s ms skeleton expected
2037 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 321, "ms", u"23:45"},
2038 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 321, "msS", u"23:45.3"},
2039 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 321, "msSS", u"23:45.32"},
2040 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 321, "msSSS", u"23:45.321"},
2041 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 987, "ms", u"23:45"},
2042 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 987, "msS", u"23:45.3 \u2013 23:45.9"},
2043 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 987, "msSS", u"23:45.32 \u2013 23:45.98"},
2044 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 987, "msSSS", u"23:45.321 \u2013 23:45.987"},
2045 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 987, "ms", u"23:45 \u2013 23:46"},
2046 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 987, "msS", u"23:45.3 \u2013 23:46.9"},
2047 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 987, "msSS", u"23:45.32 \u2013 23:46.98"},
2048 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 987, "msSSS", u"23:45.321 \u2013 23:46.987"},
2049 { 2019, 2, 10, 1, 23, 45, 321, 2, 24, 45, 987, "ms", u"23:45 \u2013 24:45"},
2050 { 2019, 2, 10, 1, 23, 45, 321, 2, 24, 45, 987, "msS", u"23:45.3 \u2013 24:45.9"},
2051 { 2019, 2, 10, 1, 23, 45, 321, 2, 24, 45, 987, "msSS", u"23:45.32 \u2013 24:45.98"},
2052 { 2019, 2, 10, 1, 23, 45, 321, 2, 24, 45, 987, "msSSS", u"23:45.321 \u2013 24:45.987"},
2053 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 321, "s", u"45"},
2054 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 321, "sS", u"45.3"},
2055 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 321, "sSS", u"45.32"},
2056 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 321, "sSSS", u"45.321"},
2057 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 987, "s", u"45"},
2058 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 987, "sS", u"45.3 \u2013 45.9"},
2059 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 987, "sSS", u"45.32 \u2013 45.98"},
2060 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 987, "sSSS", u"45.321 \u2013 45.987"},
2061 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 987, "s", u"45 \u2013 46"},
2062 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 987, "sS", u"45.3 \u2013 46.9"},
2063 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 987, "sSS", u"45.32 \u2013 46.98"},
2064 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 987, "sSSS", u"45.321 \u2013 46.987"},
2065 { 2019, 2, 10, 1, 23, 45, 321, 2, 24, 45, 987, "s", u"45 \u2013 45"},
2066 { 2019, 2, 10, 1, 23, 45, 321, 2, 24, 45, 987, "sS", u"45.3 \u2013 45.9"},
2067 { 2019, 2, 10, 1, 23, 45, 321, 2, 24, 45, 987, "sSS", u"45.32 \u2013 45.98"},
2068 { 2019, 2, 10, 1, 23, 45, 321, 2, 24, 45, 987, "sSSS", u"45.321 \u2013 45.987"},
2069 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 321, "S", u"3"},
2070 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 321, "SS", u"32"},
2071 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 321, "SSS", u"321"},
2072
2073 // Same millisecond but in different second.
2074 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 321, "S", u"3 \u2013 3"},
2075 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 321, "SS", u"32 \u2013 32"},
2076 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 321, "SSS", u"321 \u2013 321"},
2077
2078 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 987, "S", u"3 \u2013 9"},
2079 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 987, "SS", u"32 \u2013 98"},
2080 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 45, 987, "SSS", u"321 \u2013 987"},
2081 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 987, "S", u"3 \u2013 9"},
2082 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 987, "SS", u"32 \u2013 98"},
2083 { 2019, 2, 10, 1, 23, 45, 321, 1, 23, 46, 987, "SSS", u"321 \u2013 987"},
2084 { 2019, 2, 10, 1, 23, 45, 321, 2, 24, 45, 987, "S", u"3 \u2013 9"},
2085 { 2019, 2, 10, 1, 23, 45, 321, 2, 24, 45, 987, "SS", u"32 \u2013 98"},
2086 { 2019, 2, 10, 1, 23, 45, 321, 2, 24, 45, 987, "SSS", u"321 \u2013 987"},
2087 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, nullptr, nullptr},
2088 };
2089
2090 const Locale &enLocale = Locale::getEnglish();
2091 IcuTestErrorCode status(*this, "testFormatMillisecond");
2092 LocalPointer<Calendar> calendar(Calendar::createInstance(enLocale, status));
2093 if (status.errIfFailureAndReset()) { return; }
2094
2095 for (int32_t i = 0; kTestCases[i].year > 0; i++) {
2096 LocalPointer<DateIntervalFormat> fmt(DateIntervalFormat::createInstance(
2097 kTestCases[i].skeleton, enLocale, status));
2098 if (status.errIfFailureAndReset()) { continue; }
2099
2100 calendar->clear();
2101 calendar->set(kTestCases[i].year, kTestCases[i].month, kTestCases[i].day,
2102 kTestCases[i].from_hour, kTestCases[i].from_miniute, kTestCases[i].from_second);
2103 UDate from = calendar->getTime(status) + kTestCases[i].from_millisecond;
2104 if (status.errIfFailureAndReset()) { continue; }
2105
2106 calendar->clear();
2107 calendar->set(kTestCases[i].year, kTestCases[i].month, kTestCases[i].day,
2108 kTestCases[i].to_hour, kTestCases[i].to_miniute, kTestCases[i].to_second);
2109 UDate to = calendar->getTime(status) + kTestCases[i].to_millisecond;
2110 FormattedDateInterval res = fmt->formatToValue(DateInterval(from, to), status);
2111 if (status.errIfFailureAndReset()) { continue; }
2112
2113 UnicodeString formatted = res.toString(status);
2114 if (status.errIfFailureAndReset()) { continue; }
2115 if (formatted != kTestCases[i].expected) {
2116 std::string tmp1;
2117 std::string tmp2;
2118 errln("Case %d for skeleton %s : Got %s but expect %s",
2119 i, kTestCases[i].skeleton, formatted.toUTF8String<std::string>(tmp1).c_str(),
2120 UnicodeString(kTestCases[i].expected).toUTF8String<std::string>(tmp2).c_str());
2121 }
2122 }
2123}
2124
2125void DateIntervalFormatTest::testTicket20707() {
2126 IcuTestErrorCode status(*this, "testTicket20707");
2127
2128 const char16_t timeZone[] = u"UTC";
2129 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"};
2130
2131 // Clomuns: hh, HH, kk, KK, jj, JJs, CC
2132 UnicodeString expected[][7] = {
2133 // Hour-cycle: k
2134 {u"12 AM", u"24", u"24", u"12 AM", u"24", u"0 (hour: 24)", u"12 AM"},
2135 // Hour-cycle: H
2136 {u"12 AM", u"00", u"00", u"12 AM", u"00", u"0 (hour: 00)", u"12 AM"},
2137 // Hour-cycle: h
2138 {u"12 AM", u"00", u"00", u"12 AM", u"12 AM", u"0 (hour: 12)", u"12 AM"},
2139 // Hour-cycle: K
2140 {u"0 AM", u"00", u"00", u"0 AM", u"0 AM", u"0 (hour: 00)", u"0 AM"},
2141 {u"12 AM", u"00", u"00", u"12 AM", u"12 AM", u"0 (hour: 12)", u"12 AM"},
2142 {u"12 AM", u"00", u"00", u"12 AM", u"12 AM", u"0 (hour: 12)", u"12 AM"},
2143 // Hour-cycle: K
2144 {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"}
2145 };
2146
2147 int32_t i = 0;
2148 for (Locale locale : locales) {
2149 int32_t j = 0;
2150 for (const UnicodeString skeleton : {u"hh", u"HH", u"kk", u"KK", u"jj", u"JJs", u"CC"}) {
2151 LocalPointer<DateIntervalFormat> dtifmt(DateIntervalFormat::createInstance(skeleton, locale, status));
2152 if (status.errDataIfFailureAndReset()) {
2153 continue;
2154 }
2155 FieldPosition fposition;
2156 UnicodeString result;
2157 LocalPointer<Calendar> calendar(Calendar::createInstance(TimeZone::createTimeZone(timeZone), status));
2158 calendar->setTime(UDate(1563235200000), status);
2159 dtifmt->format(*calendar, *calendar, result, fposition, status);
2160
2161 assertEquals("Formatted result", expected[i][j++], result);
2162 }
2163 i++;
2164 }
2165}
2166
2167void DateIntervalFormatTest::getCategoryAndField(
2168 const FormattedDateInterval& formatted,
2169 std::vector<int32_t>& categories,
2170 std::vector<int32_t>& fields,
2171 IcuTestErrorCode& status) {
2172 categories.clear();
2173 fields.clear();
2174 ConstrainedFieldPosition cfpos;
2175 while (formatted.nextPosition(cfpos, status)) {
2176 categories.push_back(cfpos.getCategory());
2177 fields.push_back(cfpos.getField());
2178 }
2179}
2180
2181void DateIntervalFormatTest::verifyCategoryAndField(
2182 const FormattedDateInterval& formatted,
2183 const std::vector<int32_t>& categories,
2184 const std::vector<int32_t>& fields,
2185 IcuTestErrorCode& status) {
2186 ConstrainedFieldPosition cfpos;
2187 int32_t i = 0;
2188 while (formatted.nextPosition(cfpos, status)) {
2189 assertEquals("Category", cfpos.getCategory(), categories[i]);
2190 assertEquals("Field", cfpos.getField(), fields[i]);
2191 i++;
2192 }
2193}
2194
2195void DateIntervalFormatTest::testTicket21222GregorianEraDiff() {
2196 IcuTestErrorCode status(*this, "testTicket21222GregorianEraDiff");
2197
2198 LocalPointer<Calendar> cal(Calendar::createInstance(*TimeZone::getGMT(), status));
2199 if (U_FAILURE(status)) {
2200 errln("Failure encountered: %s", u_errorName(status));
2201 return;
2202 }
2203 std::vector<int32_t> expectedCategory;
2204 std::vector<int32_t> expectedField;
2205
2206 // Test Gregorian calendar
2207 LocalPointer<DateIntervalFormat> g(
2208 DateIntervalFormat::createInstance(
2209 u"h", Locale("en"), status));
2210 if (U_FAILURE(status)) {
2211 errln("Failure encountered: %s", u_errorName(status));
2212 return;
2213 }
2214 g->setTimeZone(*(TimeZone::getGMT()));
2215 cal->setTime(Calendar::getNow(), status);
2216 cal->set(123, UCAL_APRIL, 5, 6, 0);
2217 FormattedDateInterval formatted;
2218
2219 UDate date0123Apr5AD = cal->getTime(status);
2220
2221 cal->set(UCAL_YEAR, 124);
2222 UDate date0124Apr5AD = cal->getTime(status);
2223
2224 cal->set(UCAL_ERA, 0);
2225 UDate date0124Apr5BC = cal->getTime(status);
2226
2227 cal->set(UCAL_YEAR, 123);
2228 UDate date0123Apr5BC = cal->getTime(status);
2229
2230 DateInterval bothAD(date0123Apr5AD, date0124Apr5AD);
2231 DateInterval bothBC(date0124Apr5BC, date0123Apr5BC);
2232 DateInterval BCtoAD(date0123Apr5BC, date0124Apr5AD);
2233
2234 formatted = g->formatToValue(bothAD, status);
2235 assertEquals("Gregorian - calendar both dates in AD",
2236 u"4/5/123, 6 AM \u2013 4/5/124, 6 AM",
2237 formatted.toString(status));
2238
2239 formatted = g->formatToValue(bothBC, status);
2240 assertEquals("Gregorian - calendar both dates in BC",
2241 u"4/5/124, 6 AM \u2013 4/5/123, 6 AM",
2242 formatted.toString(status));
2243
2244 formatted = g->formatToValue(BCtoAD, status);
2245 assertEquals("Gregorian - BC to AD",
2246 u"4/5/123 B, 6 AM \u2013 4/5/124 A, 6 AM",
2247 formatted.toString(status));
2248}
2249
2250void DateIntervalFormatTest::testTicket21222ROCEraDiff() {
2251 IcuTestErrorCode status(*this, "testTicket21222ROCEraDiff");
2252
2253 LocalPointer<Calendar> cal(Calendar::createInstance(*TimeZone::getGMT(), status));
2254 if (U_FAILURE(status)) {
2255 errln("Failure encountered: %s", u_errorName(status));
2256 return;
2257 }
2258 std::vector<int32_t> expectedCategory;
2259 std::vector<int32_t> expectedField;
2260
2261 // Test roc calendar
2262 LocalPointer<DateIntervalFormat> roc(
2263 DateIntervalFormat::createInstance(
2264 u"h", Locale("zh-Hant-TW@calendar=roc"), status));
2265 if (U_FAILURE(status)) {
2266 errln("Failure encountered: %s", u_errorName(status));
2267 return;
2268 }
2269 roc->setTimeZone(*(TimeZone::getGMT()));
2270
2271 FormattedDateInterval formatted;
2272 // set date1910Jan2 to 1910/1/2 AD which is prior to MG
2273 cal->set(1910, UCAL_JANUARY, 2, 6, 0);
2274 UDate date1910Jan2 = cal->getTime(status);
2275
2276 // set date1911Jan2 to 1911/1/2 AD which is also prior to MG
2277 cal->set(UCAL_YEAR, 1911);
2278 UDate date1911Jan2 = cal->getTime(status);
2279
2280 // set date1912Jan2 to 1912/1/2 AD which is after MG
2281 cal->set(UCAL_YEAR, 1912);
2282 UDate date1912Jan2 = cal->getTime(status);
2283
2284 // set date1913Jan2 to 1913/1/2 AD which is also after MG
2285 cal->set(UCAL_YEAR, 1913);
2286 UDate date1913Jan2 = cal->getTime(status);
2287
2288 DateInterval bothBeforeMG(date1910Jan2, date1911Jan2);
2289 DateInterval beforeAfterMG(date1911Jan2, date1913Jan2);
2290 DateInterval bothAfterMG(date1912Jan2, date1913Jan2);
2291
2292 formatted = roc->formatToValue(bothAfterMG, status);
2293 assertEquals("roc calendar - both dates in MG Era",
2294 u"民國1/1/2 上午6時 – 民國2/1/2 上午6時",
2295 formatted.toString(status));
2296 getCategoryAndField(formatted, expectedCategory,
2297 expectedField, status);
2298
2299 formatted = roc->formatToValue(beforeAfterMG, status);
2300 assertEquals("roc calendar - prior MG Era and in MG Era",
2301 u"民國前1/1/2 上午6時 – 民國2/1/2 上午6時",
2302 formatted.toString(status));
2303 verifyCategoryAndField(formatted, expectedCategory, expectedField, status);
2304
2305 formatted = roc->formatToValue(bothBeforeMG, status);
2306 assertEquals("roc calendar - both dates prior MG Era",
2307 u"民國前2/1/2 上午6時 – 民國前1/1/2 上午6時",
2308 formatted.toString(status));
2309 verifyCategoryAndField(formatted, expectedCategory, expectedField, status);
2310}
2311
2312void DateIntervalFormatTest::testTicket21222JapaneseEraDiff() {
2313 IcuTestErrorCode status(*this, "testTicket21222JapaneseEraDiff");
2314
2315 LocalPointer<Calendar> cal(Calendar::createInstance(*TimeZone::getGMT(), status));
2316 if (U_FAILURE(status)) {
2317 errln("Failure encountered: %s", u_errorName(status));
2318 return;
2319 }
2320 std::vector<int32_t> expectedCategory;
2321 std::vector<int32_t> expectedField;
2322
2323 // Test roc calendar
2324 // Test Japanese calendar
2325 LocalPointer<DateIntervalFormat> japanese(
2326 DateIntervalFormat::createInstance(
2327 u"h", Locale("ja@calendar=japanese"), status));
2328 if (U_FAILURE(status)) {
2329 errln("Failure encountered: %s", u_errorName(status));
2330 return;
2331 }
2332 japanese->setTimeZone(*(TimeZone::getGMT()));
2333
2334 FormattedDateInterval formatted;
2335
2336 cal->set(2019, UCAL_MARCH, 2, 6, 0);
2337 UDate date2019Mar2 = cal->getTime(status);
2338
2339 cal->set(UCAL_MONTH, UCAL_APRIL);
2340 cal->set(UCAL_DAY_OF_MONTH, 3);
2341 UDate date2019Apr3 = cal->getTime(status);
2342
2343 cal->set(UCAL_MONTH, UCAL_MAY);
2344 cal->set(UCAL_DAY_OF_MONTH, 4);
2345 UDate date2019May4 = cal->getTime(status);
2346
2347 cal->set(UCAL_MONTH, UCAL_JUNE);
2348 cal->set(UCAL_DAY_OF_MONTH, 5);
2349 UDate date2019Jun5 = cal->getTime(status);
2350
2351 DateInterval bothBeforeReiwa(date2019Mar2, date2019Apr3);
2352 DateInterval beforeAfterReiwa(date2019Mar2, date2019May4);
2353 DateInterval bothAfterReiwa(date2019May4, date2019Jun5);
2354
2355 formatted = japanese->formatToValue(bothAfterReiwa, status);
2356 assertEquals("japanese calendar - both dates in Reiwa",
2357 u"R1/5/4 午前6時~R1/6/5 午前6時",
2358 formatted.toString(status));
2359 getCategoryAndField(formatted, expectedCategory,
2360 expectedField, status);
2361
2362 formatted = japanese->formatToValue(bothBeforeReiwa, status);
2363 assertEquals("japanese calendar - both dates before Reiwa",
2364 u"H31/3/2 午前6時~H31/4/3 午前6時",
2365 formatted.toString(status));
2366 verifyCategoryAndField(formatted, expectedCategory, expectedField, status);
2367
2368 formatted = japanese->formatToValue(beforeAfterReiwa, status);
2369 assertEquals("japanese calendar - date before and in Reiwa",
2370 u"H31/3/2 午前6時~R1/5/4 午前6時",
2371 formatted.toString(status));
2372 verifyCategoryAndField(formatted, expectedCategory, expectedField, status);
2373}
2374
2375#endif /* #if !UCONFIG_NO_FORMATTING */