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