]> git.saurik.com Git - apple/icu.git/blob - icuSources/test/cintltst/cdattst.c
e94c2132993d3f1ea3ba664c0029c8017dcb25b4
[apple/icu.git] / icuSources / test / cintltst / cdattst.c
1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
4 * COPYRIGHT:
5 * Copyright (c) 1997-2016, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 ********************************************************************/
8 /********************************************************************************
9 *
10 * File CDATTST.C
11 *
12 * Modification History:
13 * Name Description
14 * Madhu Katragadda Creation
15 *********************************************************************************
16 */
17
18 /* C API TEST FOR DATE FORMAT */
19
20 #include "unicode/utypes.h"
21
22 #if !UCONFIG_NO_FORMATTING
23
24 #include "unicode/uloc.h"
25 #include "unicode/udat.h"
26 #include "unicode/udatpg.h"
27 #include "unicode/ucal.h"
28 #include "unicode/unum.h"
29 #include "unicode/ustring.h"
30 #include "unicode/ufieldpositer.h"
31 #include "cintltst.h"
32 #include "cdattst.h"
33 #include "cformtst.h"
34 #include "cmemory.h"
35 #include "unicode/uatimeunitformat.h" /* Apple-specific */
36
37 #include <math.h>
38
39 static void TestExtremeDates(void);
40 static void TestAllLocales(void);
41 static void TestRelativeCrash(void);
42 static void TestContext(void);
43 static void TestCalendarDateParse(void);
44 static void TestParseErrorReturnValue(void);
45 static void TestFormatForFields(void);
46 static void TestStandardPatterns(void);
47 static void TestApplyPatnOverridesTimeSep(void);
48 static void Test12HrFormats(void);
49 static void TestTimeUnitFormat(void); /* Apple-specific */
50 static void TestRemapPatternWithOpts(void); /* Apple-specific */
51
52 void addDateForTest(TestNode** root);
53
54 #define TESTCASE(x) addTest(root, &x, "tsformat/cdattst/" #x)
55
56 void addDateForTest(TestNode** root)
57 {
58 TESTCASE(TestDateFormat);
59 TESTCASE(TestRelativeDateFormat);
60 TESTCASE(TestSymbols);
61 TESTCASE(TestDateFormatCalendar);
62 TESTCASE(TestExtremeDates);
63 TESTCASE(TestAllLocales);
64 TESTCASE(TestRelativeCrash);
65 TESTCASE(TestContext);
66 TESTCASE(TestCalendarDateParse);
67 TESTCASE(TestOverrideNumberFormat);
68 TESTCASE(TestParseErrorReturnValue);
69 TESTCASE(TestFormatForFields);
70 TESTCASE(TestStandardPatterns);
71 TESTCASE(TestApplyPatnOverridesTimeSep);
72 TESTCASE(Test12HrFormats);
73 TESTCASE(TestTimeUnitFormat); /* Apple-specific */
74 TESTCASE(TestRemapPatternWithOpts); /* Apple-specific */
75 }
76 /* Testing the DateFormat API */
77 static void TestDateFormat()
78 {
79 UDateFormat *def, *fr, *it, *de, *def1, *fr_pat;
80 UDateFormat *any;
81 UDateFormat *copy;
82 UErrorCode status = U_ZERO_ERROR;
83 UChar* result = NULL;
84 const UCalendar *cal;
85 const UNumberFormat *numformat1, *numformat2;
86 UNumberFormat *adoptNF;
87 UChar temp[50];
88 int32_t numlocales;
89 UDate d1;
90 int i;
91 int32_t resultlength;
92 int32_t resultlengthneeded;
93 int32_t parsepos;
94 UDate d = 837039928046.0;
95 double num = -10456.37;
96 /*const char* str="yyyy.MM.dd G 'at' hh:mm:ss z";
97 const char t[]="2/3/76 2:50 AM";*/
98 /*Testing udat_open() to open a dateformat */
99
100 ctest_setTimeZone(NULL, &status);
101
102 log_verbose("\nTesting udat_open() with various parameters\n");
103 fr = udat_open(UDAT_FULL, UDAT_DEFAULT, "fr_FR", NULL,0, NULL, 0,&status);
104 if(U_FAILURE(status))
105 {
106 log_data_err("FAIL: error in creating the dateformat using full time style with french locale -> %s (Are you missing data?)\n",
107 myErrorName(status) );
108 return;
109 }
110 /* this is supposed to open default date format, but later on it treats it like it is "en_US"
111 - very bad if you try to run the tests on machine where default locale is NOT "en_US" */
112 /* def = udat_open(UDAT_SHORT, UDAT_SHORT, NULL, NULL, 0, &status); */
113 def = udat_open(UDAT_SHORT, UDAT_SHORT, "en_US", NULL, 0,NULL, 0, &status);
114 if(U_FAILURE(status))
115 {
116 log_err("FAIL: error in creating the dateformat using short date and time style\n %s\n",
117 myErrorName(status) );
118 return;
119 }
120 it = udat_open(UDAT_DEFAULT, UDAT_MEDIUM, "it_IT", NULL, 0, NULL, 0,&status);
121 if(U_FAILURE(status))
122 {
123 log_err("FAIL: error in creating the dateformat using medium date style with italian locale\n %s\n",
124 myErrorName(status) );
125 return;
126 }
127 de = udat_open(UDAT_LONG, UDAT_LONG, "de_DE", NULL, 0, NULL, 0,&status);
128 if(U_FAILURE(status))
129 {
130 log_err("FAIL: error in creating the dateformat using long time and date styles with german locale\n %s\n",
131 myErrorName(status));
132 return;
133 }
134 /*creating a default dateformat */
135 def1 = udat_open(UDAT_SHORT, UDAT_SHORT, NULL, NULL, 0,NULL, 0, &status);
136 if(U_FAILURE(status))
137 {
138 log_err("FAIL: error in creating the dateformat using short date and time style\n %s\n",
139 myErrorName(status) );
140 return;
141 }
142
143
144 /*Testing udat_getAvailable() and udat_countAvailable()*/
145 log_verbose("\nTesting getAvailableLocales and countAvailable()\n");
146 numlocales=udat_countAvailable();
147 /* use something sensible w/o hardcoding the count */
148 if(numlocales < 0)
149 log_data_err("FAIL: error in countAvailable\n");
150 log_verbose("The number of locales for which date/time formatting patterns are available is %d\n", numlocales);
151
152 for(i=0;i<numlocales;i++) {
153 UErrorCode subStatus = U_ZERO_ERROR;
154 log_verbose("Testing open of %s\n", udat_getAvailable(i));
155 any = udat_open(UDAT_SHORT, UDAT_SHORT, udat_getAvailable(i), NULL ,0, NULL, 0, &subStatus);
156 if(U_FAILURE(subStatus)) {
157 log_data_err("FAIL: date format %s (getAvailable(%d)) is not instantiable: %s\n", udat_getAvailable(i), i, u_errorName(subStatus));
158 }
159 udat_close(any);
160 }
161
162 /*Testing udat_clone()*/
163 log_verbose("\nTesting the udat_clone() function of date format\n");
164 copy=udat_clone(def, &status);
165 if(U_FAILURE(status)){
166 log_err("Error in creating the clone using udat_clone: %s\n", myErrorName(status) );
167 }
168 /*if(def != copy)
169 log_err("Error in udat_clone");*/ /*how should i check for equality???? */
170
171 /*Testing udat_format()*/
172 log_verbose("\nTesting the udat_format() function of date format\n");
173 u_uastrcpy(temp, "7/10/96, 4:05 PM");
174 /*format using def */
175 resultlength=0;
176 resultlengthneeded=udat_format(def, d, NULL, resultlength, NULL, &status);
177 if(status==U_BUFFER_OVERFLOW_ERROR)
178 {
179 status=U_ZERO_ERROR;
180 resultlength=resultlengthneeded+1;
181 if(result != NULL) {
182 free(result);
183 result = NULL;
184 }
185 result=(UChar*)malloc(sizeof(UChar) * resultlength);
186 udat_format(def, d, result, resultlength, NULL, &status);
187 }
188 if(U_FAILURE(status) || !result)
189 {
190 log_err("FAIL: Error in formatting using udat_format(.....) %s\n", myErrorName(status) );
191 return;
192 }
193 else
194 log_verbose("PASS: formatting successful\n");
195 if(u_strcmp(result, temp)==0)
196 log_verbose("PASS: Date Format for US locale successful using udat_format()\n");
197 else {
198 char xbuf[2048];
199 char gbuf[2048];
200 u_austrcpy(xbuf, temp);
201 u_austrcpy(gbuf, result);
202 log_err("FAIL: Date Format for US locale failed using udat_format() - expected %s got %s\n", xbuf, gbuf);
203 }
204 /*format using fr */
205
206 u_unescape("10 juil. 1996 \\u00E0 16:05:28 heure d\\u2019\\u00E9t\\u00E9 du Pacifique", temp, 50);
207 if(result != NULL) {
208 free(result);
209 result = NULL;
210 }
211 result=myDateFormat(fr, d);
212 if(u_strcmp(result, temp)==0)
213 log_verbose("PASS: Date Format for french locale successful using udat_format()\n");
214 else
215 log_data_err("FAIL: Date Format for french locale failed using udat_format().\n" );
216
217 /*format using it */
218 u_uastrcpy(temp, "10 lug 1996, 16:05:28");
219
220 {
221 UChar *fmtted;
222 char g[100];
223 char x[100];
224
225 fmtted = myDateFormat(it,d);
226 u_austrcpy(g, fmtted);
227 u_austrcpy(x, temp);
228 if(u_strcmp(fmtted, temp)==0) {
229 log_verbose("PASS: Date Format for italian locale successful uisng udat_format() - wanted %s, got %s\n", x, g);
230 } else {
231 log_data_err("FAIL: Date Format for italian locale failed using udat_format() - wanted %s, got %s\n", x, g);
232 }
233 }
234
235 /*Testing parsing using udat_parse()*/
236 log_verbose("\nTesting parsing using udat_parse()\n");
237 u_uastrcpy(temp,"2/3/76, 2:50 AM");
238 parsepos=0;
239 status=U_ZERO_ERROR;
240
241 d1=udat_parse(def, temp, u_strlen(temp), &parsepos, &status);
242 if(U_FAILURE(status))
243 {
244 log_err("FAIL: Error in parsing using udat_parse(.....) %s\n", myErrorName(status) );
245 }
246 else
247 log_verbose("PASS: parsing succesful\n");
248 /*format it back and check for equality */
249
250
251 if(u_strcmp(myDateFormat(def, d1),temp)!=0)
252 log_err("FAIL: error in parsing\n");
253
254 /*Testing parsing using udat_parse()*/
255 log_verbose("\nTesting parsing using udat_parse()\n");
256 u_uastrcpy(temp,"2/Don't parse this part");
257 status=U_ZERO_ERROR;
258
259 d1=udat_parse(def, temp, u_strlen(temp), NULL, &status);
260 if(status != U_PARSE_ERROR)
261 {
262 log_err("FAIL: udat_parse(\"bad string\") passed when it should have failed\n");
263 }
264 else
265 log_verbose("PASS: parsing succesful\n");
266
267
268
269 /*Testing udat_openPattern() */
270 status=U_ZERO_ERROR;
271 log_verbose("\nTesting the udat_openPattern with a specified pattern\n");
272 /*for french locale */
273 fr_pat=udat_open(UDAT_PATTERN, UDAT_PATTERN,"fr_FR",NULL,0,temp, u_strlen(temp), &status);
274 if(U_FAILURE(status))
275 {
276 log_err("FAIL: Error in creating a date format using udat_openPattern \n %s\n",
277 myErrorName(status) );
278 }
279 else
280 log_verbose("PASS: creating dateformat using udat_openPattern() succesful\n");
281
282
283 /*Testing applyPattern and toPattern */
284 log_verbose("\nTesting applyPattern and toPattern()\n");
285 udat_applyPattern(def1, FALSE, temp, u_strlen(temp));
286 log_verbose("Extracting the pattern\n");
287
288 resultlength=0;
289 resultlengthneeded=udat_toPattern(def1, FALSE, NULL, resultlength, &status);
290 if(status==U_BUFFER_OVERFLOW_ERROR)
291 {
292 status=U_ZERO_ERROR;
293 resultlength=resultlengthneeded + 1;
294 result=(UChar*)malloc(sizeof(UChar) * resultlength);
295 udat_toPattern(def1, FALSE, result, resultlength, &status);
296 }
297 if(U_FAILURE(status))
298 {
299 log_err("FAIL: error in extracting the pattern from UNumberFormat\n %s\n",
300 myErrorName(status) );
301 }
302 if(u_strcmp(result, temp)!=0)
303 log_err("FAIL: Error in extracting the pattern\n");
304 else
305 log_verbose("PASS: applyPattern and toPattern work fine\n");
306
307 if(result != NULL) {
308 free(result);
309 result = NULL;
310 }
311
312
313 /*Testing getter and setter functions*/
314 /*isLenient and setLenient()*/
315 log_verbose("\nTesting the isLenient and setLenient properties\n");
316 udat_setLenient(fr, udat_isLenient(it));
317 if(udat_isLenient(fr) != udat_isLenient(it))
318 log_err("ERROR: setLenient() failed\n");
319 else
320 log_verbose("PASS: setLenient() successful\n");
321
322
323 /*Test get2DigitYearStart set2DigitYearStart */
324 log_verbose("\nTesting the get and set 2DigitYearStart properties\n");
325 d1= udat_get2DigitYearStart(fr_pat,&status);
326 if(U_FAILURE(status)) {
327 log_err("ERROR: udat_get2DigitYearStart failed %s\n", myErrorName(status) );
328 }
329 status = U_ZERO_ERROR;
330 udat_set2DigitYearStart(def1 ,d1, &status);
331 if(U_FAILURE(status)) {
332 log_err("ERROR: udat_set2DigitYearStart failed %s\n", myErrorName(status) );
333 }
334 if(udat_get2DigitYearStart(fr_pat, &status) != udat_get2DigitYearStart(def1, &status))
335 log_err("FAIL: error in set2DigitYearStart\n");
336 else
337 log_verbose("PASS: set2DigitYearStart successful\n");
338 /*try setting it to another value */
339 udat_set2DigitYearStart(de, 2000.0, &status);
340 if(U_FAILURE(status)){
341 log_verbose("ERROR: udat_set2DigitYearStart failed %s\n", myErrorName(status) );
342 }
343 if(udat_get2DigitYearStart(de, &status) != 2000)
344 log_err("FAIL: error in set2DigitYearStart\n");
345 else
346 log_verbose("PASS: set2DigitYearStart successful\n");
347
348
349
350 /*Test getNumberFormat() and setNumberFormat() */
351 log_verbose("\nTesting the get and set NumberFormat properties of date format\n");
352 numformat1=udat_getNumberFormat(fr_pat);
353 udat_setNumberFormat(def1, numformat1);
354 numformat2=udat_getNumberFormat(def1);
355 if(u_strcmp(myNumformat(numformat1, num), myNumformat(numformat2, num)) !=0)
356 log_err("FAIL: error in setNumberFormat or getNumberFormat()\n");
357 else
358 log_verbose("PASS:setNumberFormat and getNumberFormat succesful\n");
359
360 /*Test getNumberFormat() and adoptNumberFormat() */
361 log_verbose("\nTesting the get and adopt NumberFormat properties of date format\n");
362 adoptNF= unum_open(UNUM_DEFAULT, NULL, 0, NULL, NULL, &status);
363 udat_adoptNumberFormat(def1, adoptNF);
364 numformat2=udat_getNumberFormat(def1);
365 if(u_strcmp(myNumformat(adoptNF, num), myNumformat(numformat2, num)) !=0)
366 log_err("FAIL: error in adoptNumberFormat or getNumberFormat()\n");
367 else
368 log_verbose("PASS:adoptNumberFormat and getNumberFormat succesful\n");
369
370 /*try setting the number format to another format */
371 numformat1=udat_getNumberFormat(def);
372 udat_setNumberFormat(def1, numformat1);
373 numformat2=udat_getNumberFormat(def1);
374 if(u_strcmp(myNumformat(numformat1, num), myNumformat(numformat2, num)) !=0)
375 log_err("FAIL: error in setNumberFormat or getNumberFormat()\n");
376 else
377 log_verbose("PASS: setNumberFormat and getNumberFormat succesful\n");
378
379
380
381 /*Test getCalendar and setCalendar*/
382 log_verbose("\nTesting the udat_getCalendar() and udat_setCalendar() properties\n");
383 cal=udat_getCalendar(fr_pat);
384
385
386 udat_setCalendar(def1, cal);
387 if(!ucal_equivalentTo(udat_getCalendar(fr_pat), udat_getCalendar(def1)))
388 log_err("FAIL: Error in setting and getting the calendar\n");
389 else
390 log_verbose("PASS: getting and setting calendar successful\n");
391
392 if(result!=NULL) {
393 free(result);
394 }
395
396 /*Closing the UDateForamt */
397 udat_close(def);
398 udat_close(fr);
399 udat_close(it);
400 udat_close(de);
401 udat_close(def1);
402 udat_close(fr_pat);
403 udat_close(copy);
404
405 ctest_resetTimeZone();
406 }
407
408 /*
409 Test combined relative date formatting (relative date + non-relative time).
410 This is a bit tricky since we can't have static test data for comparison, the
411 relative date formatting is relative to the time the tests are run. We generate
412 the data for comparison dynamically. However, the tests could fail if they are
413 run right at midnight Pacific time and the call to ucal_getNow() is before midnight
414 while the calls to udat_format are after midnight or span midnight.
415 */
416 static const UDate dayInterval = 24.0*60.0*60.0*1000.0;
417 static const UChar trdfZone[] = { 0x0055, 0x0053, 0x002F, 0x0050, 0x0061, 0x0063, 0x0069, 0x0066, 0x0069, 0x0063, 0 }; /* US/Pacific */
418 static const char trdfLocale[] = "en_US";
419 static const UChar minutesPatn[] = { 0x006D, 0x006D, 0 }; /* "mm" */
420 static const UChar monthLongPatn[] = { 0x004D, 0x004D, 0x004D, 0x004D, 0 }; /* "MMMM" */
421 static const UChar monthMediumPatn[] = { 0x004D, 0x004D, 0x004D, 0 }; /* "MMM" */
422 static const UChar monthShortPatn[] = { 0x004D, 0 }; /* "M" */
423 static const UDateFormatStyle dateStylesList[] = { UDAT_FULL, UDAT_LONG, UDAT_MEDIUM, UDAT_SHORT, UDAT_NONE };
424 static const UChar *monthPatnsList[] = { monthLongPatn, monthLongPatn, monthMediumPatn, monthShortPatn, NULL };
425 static const UChar newTimePatn[] = { 0x0048, 0x0048, 0x002C, 0x006D, 0x006D, 0 }; /* "HH,mm" */
426 static const UChar minutesStr[] = { 0x0034, 0x0039, 0 }; /* "49", minutes string to search for in output */
427 enum { kDateOrTimeOutMax = 96, kDateAndTimeOutMax = 192 };
428
429 static const UDate minutesTolerance = 2 * 60.0 * 1000.0;
430 static const UDate daysTolerance = 2 * 24.0 * 60.0 * 60.0 * 1000.0;
431
432 static void TestRelativeDateFormat()
433 {
434 UDate today = 0.0;
435 const UDateFormatStyle * stylePtr;
436 const UChar ** monthPtnPtr;
437 UErrorCode status = U_ZERO_ERROR;
438 UCalendar * ucal = ucal_open(trdfZone, -1, trdfLocale, UCAL_GREGORIAN, &status);
439 if ( U_SUCCESS(status) ) {
440 int32_t year, month, day;
441 ucal_setMillis(ucal, ucal_getNow(), &status);
442 year = ucal_get(ucal, UCAL_YEAR, &status);
443 month = ucal_get(ucal, UCAL_MONTH, &status);
444 day = ucal_get(ucal, UCAL_DATE, &status);
445 ucal_setDateTime(ucal, year, month, day, 18, 49, 0, &status); /* set to today at 18:49:00 */
446 today = ucal_getMillis(ucal, &status);
447 ucal_close(ucal);
448 }
449 if ( U_FAILURE(status) || today == 0.0 ) {
450 log_data_err("Generate UDate for a specified time today fails, error %s - (Are you missing data?)\n", myErrorName(status) );
451 return;
452 }
453 for (stylePtr = dateStylesList, monthPtnPtr = monthPatnsList; *stylePtr != UDAT_NONE; ++stylePtr, ++monthPtnPtr) {
454 UDateFormat* fmtRelDateTime;
455 UDateFormat* fmtRelDate;
456 UDateFormat* fmtTime;
457 int32_t dayOffset, limit;
458 UFieldPosition fp;
459 UChar strDateTime[kDateAndTimeOutMax];
460 UChar strDate[kDateOrTimeOutMax];
461 UChar strTime[kDateOrTimeOutMax];
462 UChar * strPtr;
463 int32_t dtpatLen;
464
465 fmtRelDateTime = udat_open(UDAT_SHORT, *stylePtr | UDAT_RELATIVE, trdfLocale, trdfZone, -1, NULL, 0, &status);
466 if ( U_FAILURE(status) ) {
467 log_data_err("udat_open timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s (Are you missing data?)\n", *stylePtr, myErrorName(status) );
468 continue;
469 }
470 fmtRelDate = udat_open(UDAT_NONE, *stylePtr | UDAT_RELATIVE, trdfLocale, trdfZone, -1, NULL, 0, &status);
471 if ( U_FAILURE(status) ) {
472 log_err("udat_open timeStyle NONE dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
473 udat_close(fmtRelDateTime);
474 continue;
475 }
476 fmtTime = udat_open(UDAT_SHORT, UDAT_NONE, trdfLocale, trdfZone, -1, NULL, 0, &status);
477 if ( U_FAILURE(status) ) {
478 log_err("udat_open timeStyle SHORT dateStyle NONE fails, error %s\n", myErrorName(status) );
479 udat_close(fmtRelDateTime);
480 udat_close(fmtRelDate);
481 continue;
482 }
483
484 dtpatLen = udat_toPatternRelativeDate(fmtRelDateTime, strDate, kDateAndTimeOutMax, &status);
485 if ( U_FAILURE(status) ) {
486 log_err("udat_toPatternRelativeDate timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
487 status = U_ZERO_ERROR;
488 } else if ( u_strstr(strDate, *monthPtnPtr) == NULL || dtpatLen != u_strlen(strDate) ) {
489 log_err("udat_toPatternRelativeDate timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) date pattern incorrect\n", *stylePtr );
490 }
491 dtpatLen = udat_toPatternRelativeTime(fmtRelDateTime, strTime, kDateAndTimeOutMax, &status);
492 if ( U_FAILURE(status) ) {
493 log_err("udat_toPatternRelativeTime timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
494 status = U_ZERO_ERROR;
495 } else if ( u_strstr(strTime, minutesPatn) == NULL || dtpatLen != u_strlen(strTime) ) {
496 log_err("udat_toPatternRelativeTime timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) time pattern incorrect\n", *stylePtr );
497 }
498 dtpatLen = udat_toPattern(fmtRelDateTime, FALSE, strDateTime, kDateAndTimeOutMax, &status);
499 if ( U_FAILURE(status) ) {
500 log_err("udat_toPattern timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
501 status = U_ZERO_ERROR;
502 } else if ( u_strstr(strDateTime, strDate) == NULL || u_strstr(strDateTime, strTime) == NULL || dtpatLen != u_strlen(strDateTime) ) {
503 log_err("udat_toPattern timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) dateTime pattern incorrect\n", *stylePtr );
504 }
505 udat_applyPatternRelative(fmtRelDateTime, strDate, u_strlen(strDate), newTimePatn, u_strlen(newTimePatn), &status);
506 if ( U_FAILURE(status) ) {
507 log_err("udat_applyPatternRelative timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
508 status = U_ZERO_ERROR;
509 } else {
510 udat_toPattern(fmtRelDateTime, FALSE, strDateTime, kDateAndTimeOutMax, &status);
511 if ( U_FAILURE(status) ) {
512 log_err("udat_toPattern timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
513 status = U_ZERO_ERROR;
514 } else if ( u_strstr(strDateTime, newTimePatn) == NULL ) {
515 log_err("udat_applyPatternRelative timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) didn't update time pattern\n", *stylePtr );
516 }
517 }
518 udat_applyPatternRelative(fmtRelDateTime, strDate, u_strlen(strDate), strTime, u_strlen(strTime), &status); /* restore original */
519
520 fp.field = UDAT_MINUTE_FIELD;
521 for (dayOffset = -2, limit = 2; dayOffset <= limit; ++dayOffset) {
522 UDate dateToUse = today + (float)dayOffset*dayInterval;
523
524 udat_format(fmtRelDateTime, dateToUse, strDateTime, kDateAndTimeOutMax, &fp, &status);
525 if ( U_FAILURE(status) ) {
526 log_err("udat_format timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
527 status = U_ZERO_ERROR;
528 } else {
529 int32_t parsePos = 0;
530 UDate dateResult = udat_parse(fmtRelDateTime, strDateTime, -1, &parsePos, &status);
531 UDate dateDiff = (dateResult >= dateToUse)? dateResult - dateToUse: dateToUse - dateResult;
532 if ( U_FAILURE(status) || dateDiff > minutesTolerance ) {
533 log_err("udat_parse timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s, expect approx %.1f, got %.1f, parsePos %d\n",
534 *stylePtr, myErrorName(status), dateToUse, dateResult, parsePos );
535 status = U_ZERO_ERROR;
536 }
537
538 udat_format(fmtRelDate, dateToUse, strDate, kDateOrTimeOutMax, NULL, &status);
539 if ( U_FAILURE(status) ) {
540 log_err("udat_format timeStyle NONE dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
541 status = U_ZERO_ERROR;
542 } else if ( u_strstr(strDateTime, strDate) == NULL ) {
543 log_err("relative date string not found in udat_format timeStyle SHORT dateStyle (%d | UDAT_RELATIVE)\n", *stylePtr );
544 } else {
545 parsePos = 0;
546 dateResult = udat_parse(fmtRelDate, strDate, -1, &parsePos, &status);
547 dateDiff = (dateResult >= dateToUse)? dateResult - dateToUse: dateToUse - dateResult;
548 if ( U_FAILURE(status) || dateDiff > daysTolerance ) {
549 log_err("udat_parse timeStyle NONE dateStyle (%d | UDAT_RELATIVE) fails, error %s, expect approx %.1f, got %.1f, parsePos %d\n",
550 *stylePtr, myErrorName(status), dateToUse, dateResult, parsePos );
551 status = U_ZERO_ERROR;
552 }
553 }
554
555 udat_format(fmtTime, dateToUse, strTime, kDateOrTimeOutMax, NULL, &status);
556 if ( U_FAILURE(status) ) {
557 log_err("udat_format timeStyle SHORT dateStyle NONE fails, error %s\n", myErrorName(status) );
558 status = U_ZERO_ERROR;
559 } else if ( u_strstr(strDateTime, strTime) == NULL ) {
560 log_err("time string not found in udat_format timeStyle SHORT dateStyle (%d | UDAT_RELATIVE)\n", *stylePtr );
561 }
562
563 strPtr = u_strstr(strDateTime, minutesStr);
564 if ( strPtr != NULL ) {
565 int32_t beginIndex = strPtr - strDateTime;
566 if ( fp.beginIndex != beginIndex ) {
567 log_err("UFieldPosition beginIndex %d, expected %d, in udat_format timeStyle SHORT dateStyle (%d | UDAT_RELATIVE)\n", fp.beginIndex, beginIndex, *stylePtr );
568 }
569 } else {
570 log_err("minutes string not found in udat_format timeStyle SHORT dateStyle (%d | UDAT_RELATIVE)\n", *stylePtr );
571 }
572 }
573 }
574
575 udat_close(fmtRelDateTime);
576 udat_close(fmtRelDate);
577 udat_close(fmtTime);
578 }
579 }
580
581 /*Testing udat_getSymbols() and udat_setSymbols() and udat_countSymbols()*/
582 static void TestSymbols()
583 {
584 UDateFormat *def, *fr, *zhChiCal;
585 UErrorCode status = U_ZERO_ERROR;
586 UChar *value=NULL;
587 UChar *result = NULL;
588 int32_t resultlength;
589 int32_t resultlengthout;
590 UChar *pattern;
591
592
593 /*creating a dateformat with french locale */
594 log_verbose("\ncreating a date format with french locale\n");
595 fr = udat_open(UDAT_FULL, UDAT_DEFAULT, "fr_FR", NULL, 0, NULL, 0, &status);
596 if(U_FAILURE(status))
597 {
598 log_data_err("error in creating the dateformat using full time style with french locale -> %s (Are you missing data?)\n",
599 myErrorName(status) );
600 return;
601 }
602 /*creating a default dateformat */
603 log_verbose("\ncreating a date format with default locale\n");
604 /* this is supposed to open default date format, but later on it treats it like it is "en_US"
605 - very bad if you try to run the tests on machine where default locale is NOT "en_US" */
606 /* def = udat_open(UDAT_DEFAULT,UDAT_DEFAULT ,NULL, NULL, 0, &status); */
607 def = udat_open(UDAT_DEFAULT,UDAT_DEFAULT ,"en_US", NULL, 0, NULL, 0, &status);
608 if(U_FAILURE(status))
609 {
610 log_err("error in creating the dateformat using short date and time style\n %s\n",
611 myErrorName(status) );
612 return;
613 }
614 /*creating a dateformat with zh locale */
615 log_verbose("\ncreating a date format with zh locale for chinese calendar\n");
616 zhChiCal = udat_open(UDAT_NONE, UDAT_FULL, "zh@calendar=chinese", NULL, 0, NULL, 0, &status);
617 if(U_FAILURE(status))
618 {
619 log_data_err("error in creating the dateformat using full date, no time, locale zh@calendar=chinese -> %s (Are you missing data?)\n",
620 myErrorName(status) );
621 return;
622 }
623
624
625 /*Testing countSymbols, getSymbols and setSymbols*/
626 log_verbose("\nTesting countSymbols\n");
627 /*since the month names has the last string empty and week names are 1 based 1.e first string in the weeknames array is empty */
628 if(udat_countSymbols(def, UDAT_ERAS)!=2 || udat_countSymbols(def, UDAT_MONTHS)!=12 ||
629 udat_countSymbols(def, UDAT_SHORT_MONTHS)!=12 || udat_countSymbols(def, UDAT_WEEKDAYS)!=8 ||
630 udat_countSymbols(def, UDAT_SHORT_WEEKDAYS)!=8 || udat_countSymbols(def, UDAT_AM_PMS)!=2 ||
631 udat_countSymbols(def, UDAT_QUARTERS) != 4 || udat_countSymbols(def, UDAT_SHORT_QUARTERS) != 4 ||
632 udat_countSymbols(def, UDAT_LOCALIZED_CHARS)!=1 || udat_countSymbols(def, UDAT_SHORTER_WEEKDAYS)!=8 ||
633 udat_countSymbols(zhChiCal, UDAT_CYCLIC_YEARS_NARROW)!=60 || udat_countSymbols(zhChiCal, UDAT_ZODIAC_NAMES_NARROW)!=12)
634 {
635 log_err("FAIL: error in udat_countSymbols\n");
636 }
637 else
638 log_verbose("PASS: udat_countSymbols() successful\n");
639
640 /*testing getSymbols*/
641 log_verbose("\nTesting getSymbols\n");
642 pattern=(UChar*)malloc(sizeof(UChar) * 10);
643 u_uastrcpy(pattern, "jeudi");
644 resultlength=0;
645 resultlengthout=udat_getSymbols(fr, UDAT_WEEKDAYS, 5 , NULL, resultlength, &status);
646 if(status==U_BUFFER_OVERFLOW_ERROR)
647 {
648 status=U_ZERO_ERROR;
649 resultlength=resultlengthout+1;
650 if(result != NULL) {
651 free(result);
652 result = NULL;
653 }
654 result=(UChar*)malloc(sizeof(UChar) * resultlength);
655 udat_getSymbols(fr, UDAT_WEEKDAYS, 5, result, resultlength, &status);
656
657 }
658 if(U_FAILURE(status))
659 {
660 log_err("FAIL: Error in udat_getSymbols().... %s\n", myErrorName(status) );
661 }
662 else
663 log_verbose("PASS: getSymbols succesful\n");
664
665 if(u_strcmp(result, pattern)==0)
666 log_verbose("PASS: getSymbols retrieved the right value\n");
667 else
668 log_data_err("FAIL: getSymbols retrieved the wrong value\n");
669
670 /*run series of tests to test getsymbols regressively*/
671 log_verbose("\nTesting getSymbols() regressively\n");
672 VerifygetSymbols(fr, UDAT_WEEKDAYS, 1, "dimanche");
673 VerifygetSymbols(def, UDAT_WEEKDAYS, 1, "Sunday");
674 VerifygetSymbols(fr, UDAT_SHORT_WEEKDAYS, 7, "sam.");
675 VerifygetSymbols(fr, UDAT_SHORTER_WEEKDAYS, 7, "sa");
676 VerifygetSymbols(def, UDAT_SHORT_WEEKDAYS, 7, "Sat");
677 VerifygetSymbols(def, UDAT_MONTHS, 11, "December");
678 VerifygetSymbols(def, UDAT_MONTHS, 0, "January");
679 VerifygetSymbols(fr, UDAT_ERAS, 0, "av. J.-C.");
680 VerifygetSymbols(def, UDAT_AM_PMS, 0, "AM");
681 VerifygetSymbols(def, UDAT_AM_PMS, 1, "PM");
682 VerifygetSymbols(fr, UDAT_SHORT_MONTHS, 0, "janv.");
683 VerifygetSymbols(def, UDAT_SHORT_MONTHS, 11, "Dec");
684 VerifygetSymbols(fr, UDAT_QUARTERS, 0, "1er trimestre");
685 VerifygetSymbols(def, UDAT_QUARTERS, 3, "4th quarter");
686 VerifygetSymbols(fr, UDAT_SHORT_QUARTERS, 1, "T2");
687 VerifygetSymbols(def, UDAT_SHORT_QUARTERS, 2, "Q3");
688 VerifygetSymbols(zhChiCal, UDAT_CYCLIC_YEARS_ABBREVIATED, 0, "\\u7532\\u5B50");
689 VerifygetSymbols(zhChiCal, UDAT_CYCLIC_YEARS_NARROW, 59, "\\u7678\\u4EA5");
690 VerifygetSymbols(zhChiCal, UDAT_ZODIAC_NAMES_ABBREVIATED, 0, "\\u9F20");
691 VerifygetSymbols(zhChiCal, UDAT_ZODIAC_NAMES_WIDE, 11, "\\u732A");
692 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
693 VerifygetSymbols(def,UDAT_LOCALIZED_CHARS, 0, "GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB:");
694 #else
695 VerifygetSymbols(def,UDAT_LOCALIZED_CHARS, 0, "GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB");
696 #endif
697
698
699 if(result != NULL) {
700 free(result);
701 result = NULL;
702 }
703 free(pattern);
704
705 log_verbose("\nTesting setSymbols\n");
706 /*applying the pattern so that setSymbolss works */
707 resultlength=0;
708 resultlengthout=udat_toPattern(fr, FALSE, NULL, resultlength, &status);
709 if(status==U_BUFFER_OVERFLOW_ERROR)
710 {
711 status=U_ZERO_ERROR;
712 resultlength=resultlengthout + 1;
713 pattern=(UChar*)malloc(sizeof(UChar) * resultlength);
714 udat_toPattern(fr, FALSE, pattern, resultlength, &status);
715 }
716 if(U_FAILURE(status))
717 {
718 log_err("FAIL: error in extracting the pattern from UNumberFormat\n %s\n",
719 myErrorName(status) );
720 }
721
722 udat_applyPattern(def, FALSE, pattern, u_strlen(pattern));
723 resultlength=0;
724 resultlengthout=udat_toPattern(def, FALSE, NULL, resultlength,&status);
725 if(status==U_BUFFER_OVERFLOW_ERROR)
726 {
727 status=U_ZERO_ERROR;
728 resultlength=resultlengthout + 1;
729 if(result != NULL) {
730 free(result);
731 result = NULL;
732 }
733 result=(UChar*)malloc(sizeof(UChar) * resultlength);
734 udat_toPattern(fr, FALSE,result, resultlength, &status);
735 }
736 if(U_FAILURE(status))
737 {
738 log_err("FAIL: error in extracting the pattern from UNumberFormat\n %s\n",
739 myErrorName(status) );
740 }
741 if(u_strcmp(result, pattern)==0)
742 log_verbose("Pattern applied properly\n");
743 else
744 log_err("pattern could not be applied properly\n");
745
746 free(pattern);
747 /*testing set symbols */
748 resultlength=0;
749 resultlengthout=udat_getSymbols(fr, UDAT_MONTHS, 11 , NULL, resultlength, &status);
750 if(status==U_BUFFER_OVERFLOW_ERROR){
751 status=U_ZERO_ERROR;
752 resultlength=resultlengthout+1;
753 if(result != NULL) {
754 free(result);
755 result = NULL;
756 }
757 result=(UChar*)malloc(sizeof(UChar) * resultlength);
758 udat_getSymbols(fr, UDAT_MONTHS, 11, result, resultlength, &status);
759
760 }
761 if(U_FAILURE(status))
762 log_err("FAIL: error in getSymbols() %s\n", myErrorName(status) );
763 resultlength=resultlengthout+1;
764
765 udat_setSymbols(def, UDAT_MONTHS, 11, result, resultlength, &status);
766 if(U_FAILURE(status))
767 {
768 log_err("FAIL: Error in udat_setSymbols() : %s\n", myErrorName(status) );
769 }
770 else
771 log_verbose("PASS: SetSymbols successful\n");
772
773 resultlength=0;
774 resultlengthout=udat_getSymbols(def, UDAT_MONTHS, 11, NULL, resultlength, &status);
775 if(status==U_BUFFER_OVERFLOW_ERROR){
776 status=U_ZERO_ERROR;
777 resultlength=resultlengthout+1;
778 value=(UChar*)malloc(sizeof(UChar) * resultlength);
779 udat_getSymbols(def, UDAT_MONTHS, 11, value, resultlength, &status);
780 }
781 if(U_FAILURE(status))
782 log_err("FAIL: error in retrieving the value using getSymbols i.e roundtrip\n");
783
784 if(u_strcmp(result, value)!=0)
785 log_data_err("FAIL: Error in settting and getting symbols\n");
786 else
787 log_verbose("PASS: setSymbols successful\n");
788
789
790 /*run series of tests to test setSymbols regressively*/
791 log_verbose("\nTesting setSymbols regressively\n");
792 VerifysetSymbols(def, UDAT_ERAS, 0, "BeforeChrist");
793 VerifysetSymbols(def, UDAT_ERA_NAMES, 1, "AnnoDomini");
794 VerifysetSymbols(def, UDAT_WEEKDAYS, 1, "Sundayweek");
795 VerifysetSymbols(def, UDAT_SHORT_WEEKDAYS, 7, "Satweek");
796 VerifysetSymbols(def, UDAT_NARROW_WEEKDAYS, 4, "M");
797 VerifysetSymbols(def, UDAT_STANDALONE_WEEKDAYS, 1, "Sonntagweek");
798 VerifysetSymbols(def, UDAT_STANDALONE_SHORT_WEEKDAYS, 7, "Sams");
799 VerifysetSymbols(def, UDAT_STANDALONE_NARROW_WEEKDAYS, 4, "V");
800 VerifysetSymbols(fr, UDAT_MONTHS, 11, "december");
801 VerifysetSymbols(fr, UDAT_SHORT_MONTHS, 0, "Jan");
802 VerifysetSymbols(fr, UDAT_NARROW_MONTHS, 1, "R");
803 VerifysetSymbols(fr, UDAT_STANDALONE_MONTHS, 11, "dezember");
804 VerifysetSymbols(fr, UDAT_STANDALONE_SHORT_MONTHS, 7, "Aug");
805 VerifysetSymbols(fr, UDAT_STANDALONE_NARROW_MONTHS, 2, "M");
806 VerifysetSymbols(fr, UDAT_QUARTERS, 0, "1. Quart");
807 VerifysetSymbols(fr, UDAT_SHORT_QUARTERS, 1, "QQ2");
808 VerifysetSymbols(fr, UDAT_STANDALONE_QUARTERS, 2, "3rd Quar.");
809 VerifysetSymbols(fr, UDAT_STANDALONE_SHORT_QUARTERS, 3, "4QQ");
810 VerifysetSymbols(zhChiCal, UDAT_CYCLIC_YEARS_ABBREVIATED, 1, "yi-chou");
811 VerifysetSymbols(zhChiCal, UDAT_ZODIAC_NAMES_ABBREVIATED, 1, "Ox");
812
813
814 /*run series of tests to test get and setSymbols regressively*/
815 log_verbose("\nTesting get and set symbols regressively\n");
816 VerifygetsetSymbols(fr, def, UDAT_WEEKDAYS, 1);
817 VerifygetsetSymbols(fr, def, UDAT_WEEKDAYS, 7);
818 VerifygetsetSymbols(fr, def, UDAT_SHORT_WEEKDAYS, 1);
819 VerifygetsetSymbols(fr, def, UDAT_SHORT_WEEKDAYS, 7);
820 VerifygetsetSymbols(fr, def, UDAT_MONTHS, 0);
821 VerifygetsetSymbols(fr, def, UDAT_SHORT_MONTHS, 0);
822 VerifygetsetSymbols(fr, def, UDAT_ERAS,1);
823 VerifygetsetSymbols(fr, def, UDAT_LOCALIZED_CHARS, 0);
824 VerifygetsetSymbols(fr, def, UDAT_AM_PMS, 1);
825
826
827 /*closing*/
828
829 udat_close(fr);
830 udat_close(def);
831 udat_close(zhChiCal);
832 if(result != NULL) {
833 free(result);
834 result = NULL;
835 }
836 free(value);
837
838 }
839
840 /**
841 * Test DateFormat(Calendar) API
842 */
843 static void TestDateFormatCalendar() {
844 UDateFormat *date=0, *time=0, *full=0;
845 UCalendar *cal=0;
846 UChar buf[256];
847 char cbuf[256];
848 int32_t pos;
849 UDate when;
850 UErrorCode ec = U_ZERO_ERROR;
851 UChar buf1[256];
852 int32_t len1;
853 const char *expected;
854 UChar uExpected[32];
855
856 ctest_setTimeZone(NULL, &ec);
857
858 /* Create a formatter for date fields. */
859 date = udat_open(UDAT_NONE, UDAT_SHORT, "en_US", NULL, 0, NULL, 0, &ec);
860 if (U_FAILURE(ec)) {
861 log_data_err("FAIL: udat_open(NONE, SHORT, en_US) failed with %s (Are you missing data?)\n",
862 u_errorName(ec));
863 goto FAIL;
864 }
865
866 /* Create a formatter for time fields. */
867 time = udat_open(UDAT_SHORT, UDAT_NONE, "en_US", NULL, 0, NULL, 0, &ec);
868 if (U_FAILURE(ec)) {
869 log_err("FAIL: udat_open(SHORT, NONE, en_US) failed with %s\n",
870 u_errorName(ec));
871 goto FAIL;
872 }
873
874 /* Create a full format for output */
875 full = udat_open(UDAT_FULL, UDAT_FULL, "en_US", NULL, 0, NULL, 0, &ec);
876 if (U_FAILURE(ec)) {
877 log_err("FAIL: udat_open(FULL, FULL, en_US) failed with %s\n",
878 u_errorName(ec));
879 goto FAIL;
880 }
881
882 /* Create a calendar */
883 cal = ucal_open(NULL, 0, "en_US", UCAL_GREGORIAN, &ec);
884 if (U_FAILURE(ec)) {
885 log_err("FAIL: ucal_open(en_US) failed with %s\n",
886 u_errorName(ec));
887 goto FAIL;
888 }
889
890 /* Parse the date */
891 ucal_clear(cal);
892 u_uastrcpy(buf, "4/5/2001");
893 pos = 0;
894 udat_parseCalendar(date, cal, buf, -1, &pos, &ec);
895 if (U_FAILURE(ec)) {
896 log_err("FAIL: udat_parseCalendar(4/5/2001) failed at %d with %s\n",
897 pos, u_errorName(ec));
898 goto FAIL;
899 }
900
901 /* Check if formatCalendar matches the original date */
902 len1 = udat_formatCalendar(date, cal, buf1, UPRV_LENGTHOF(buf1), NULL, &ec);
903 if (U_FAILURE(ec)) {
904 log_err("FAIL: udat_formatCalendar(4/5/2001) failed with %s\n",
905 u_errorName(ec));
906 goto FAIL;
907 }
908 expected = "4/5/01";
909 u_uastrcpy(uExpected, expected);
910 if (u_strlen(uExpected) != len1 || u_strncmp(uExpected, buf1, len1) != 0) {
911 log_err("FAIL: udat_formatCalendar(4/5/2001), expected: %s", expected);
912 }
913
914 /* Parse the time */
915 u_uastrcpy(buf, "5:45 PM");
916 pos = 0;
917 udat_parseCalendar(time, cal, buf, -1, &pos, &ec);
918 if (U_FAILURE(ec)) {
919 log_err("FAIL: udat_parseCalendar(17:45) failed at %d with %s\n",
920 pos, u_errorName(ec));
921 goto FAIL;
922 }
923
924 /* Check if formatCalendar matches the original time */
925 len1 = udat_formatCalendar(time, cal, buf1, UPRV_LENGTHOF(buf1), NULL, &ec);
926 if (U_FAILURE(ec)) {
927 log_err("FAIL: udat_formatCalendar(17:45) failed with %s\n",
928 u_errorName(ec));
929 goto FAIL;
930 }
931 expected = "5:45 PM";
932 u_uastrcpy(uExpected, expected);
933 if (u_strlen(uExpected) != len1 || u_strncmp(uExpected, buf1, len1) != 0) {
934 log_err("FAIL: udat_formatCalendar(17:45), expected: %s", expected);
935 }
936
937 /* Check result */
938 when = ucal_getMillis(cal, &ec);
939 if (U_FAILURE(ec)) {
940 log_err("FAIL: ucal_getMillis() failed with %s\n", u_errorName(ec));
941 goto FAIL;
942 }
943 udat_format(full, when, buf, sizeof(buf), NULL, &ec);
944 if (U_FAILURE(ec)) {
945 log_err("FAIL: udat_format() failed with %s\n", u_errorName(ec));
946 goto FAIL;
947 }
948 u_austrcpy(cbuf, buf);
949 /* Thursday, April 5, 2001 5:45:00 PM PDT 986517900000 */
950 if (when == 986517900000.0) {
951 log_verbose("Ok: Parsed result: %s\n", cbuf);
952 } else {
953 log_err("FAIL: Parsed result: %s, exp 4/5/2001 5:45 PM\n", cbuf);
954 }
955
956 FAIL:
957 udat_close(date);
958 udat_close(time);
959 udat_close(full);
960 ucal_close(cal);
961
962 ctest_resetTimeZone();
963 }
964
965
966
967 /**
968 * Test parsing two digit year against "YY" vs. "YYYY" patterns
969 */
970 static void TestCalendarDateParse() {
971
972 int32_t result;
973 UErrorCode ec = U_ZERO_ERROR;
974 UDateFormat* simpleDateFormat = 0;
975 int32_t parsePos = 0;
976 int32_t twoDigitCenturyStart = 75;
977 int32_t currentTwoDigitYear = 0;
978 int32_t startCentury = 0;
979 UCalendar* tempCal = 0;
980 UCalendar* calendar = 0;
981
982 U_STRING_DECL(pattern, "yyyy", 4);
983 U_STRING_DECL(pattern2, "yy", 2);
984 U_STRING_DECL(text, "75", 2);
985
986 U_STRING_INIT(pattern, "yyyy", 4);
987 U_STRING_INIT(pattern2, "yy", 2);
988 U_STRING_INIT(text, "75", 2);
989
990 simpleDateFormat = udat_open(UDAT_FULL, UDAT_FULL, "en-GB", 0, 0, 0, 0, &ec);
991 if (U_FAILURE(ec)) {
992 log_data_err("udat_open(UDAT_FULL, UDAT_FULL, \"en-GB\", 0, 0, 0, 0, &ec) failed: %s - (Are you missing data?)\n", u_errorName(ec));
993 return;
994 }
995 udat_applyPattern(simpleDateFormat, 0, pattern, u_strlen(pattern));
996 udat_setLenient(simpleDateFormat, 0);
997
998 currentTwoDigitYear = getCurrentYear() % 100;
999 startCentury = getCurrentYear() - currentTwoDigitYear;
1000 if (twoDigitCenturyStart > currentTwoDigitYear) {
1001 startCentury -= 100;
1002 }
1003 tempCal = ucal_open(NULL, -1, NULL, UCAL_GREGORIAN, &ec);
1004 ucal_setMillis(tempCal, 0, &ec);
1005 ucal_setDateTime(tempCal, startCentury + twoDigitCenturyStart, UCAL_JANUARY, 1, 0, 0, 0, &ec);
1006 udat_set2DigitYearStart(simpleDateFormat, ucal_getMillis(tempCal, &ec), &ec);
1007
1008 calendar = ucal_open(NULL, -1, NULL, UCAL_GREGORIAN, &ec);
1009 ucal_setMillis(calendar, 0, &ec);
1010 ucal_setDateTime(calendar, twoDigitCenturyStart, UCAL_JANUARY, 1, 0, 0, 0, &ec);
1011
1012 udat_parseCalendar(simpleDateFormat, calendar, text, u_strlen(text), &parsePos, &ec);
1013
1014 /* Check result */
1015 result = ucal_get(calendar, UCAL_YEAR, &ec);
1016 if (U_FAILURE(ec)) {
1017 log_err("FAIL: ucal_get(UCAL_YEAR) failed with %s\n", u_errorName(ec));
1018 goto FAIL;
1019 }
1020
1021 if (result != 75) {
1022 log_err("FAIL: parsed incorrect year: %d\n", result);
1023 goto FAIL;
1024 }
1025
1026 parsePos = 0;
1027 udat_applyPattern(simpleDateFormat, 0, pattern2, u_strlen(pattern2));
1028 udat_parseCalendar(simpleDateFormat, calendar, text, u_strlen(text), &parsePos, &ec);
1029
1030 /* Check result */
1031 result = ucal_get(calendar, UCAL_YEAR, &ec);
1032 if (U_FAILURE(ec)) {
1033 log_err("FAIL: ucal_get(UCAL_YEAR) failed with %s\n", u_errorName(ec));
1034 goto FAIL;
1035 }
1036
1037 if (result != 1975) {
1038 log_err("FAIL: parsed incorrect year: %d\n", result);
1039 goto FAIL;
1040 }
1041
1042 FAIL:
1043 udat_close(simpleDateFormat);
1044 udat_close(tempCal);
1045 udat_close(calendar);
1046 }
1047
1048
1049 /*INTERNAL FUNCTIONS USED*/
1050 static int getCurrentYear() {
1051 static int currentYear = 0;
1052 if (currentYear == 0) {
1053 UErrorCode status = U_ZERO_ERROR;
1054 UCalendar *cal = ucal_open(NULL, -1, NULL, UCAL_GREGORIAN, &status);
1055 if (!U_FAILURE(status)) {
1056 /* Get the current year from the default UCalendar */
1057 currentYear = ucal_get(cal, UCAL_YEAR, &status);
1058 ucal_close(cal);
1059 }
1060 }
1061
1062 return currentYear;
1063 }
1064
1065 /* N.B.: use idx instead of index to avoid 'shadow' warnings in strict mode. */
1066 static void VerifygetSymbols(UDateFormat* datfor, UDateFormatSymbolType type, int32_t idx, const char* expected)
1067 {
1068 UChar *pattern=NULL;
1069 UErrorCode status = U_ZERO_ERROR;
1070 UChar *result=NULL;
1071 int32_t resultlength, resultlengthout;
1072 int32_t patternSize = strlen(expected) + 1;
1073
1074 pattern=(UChar*)malloc(sizeof(UChar) * patternSize);
1075 u_unescape(expected, pattern, patternSize);
1076 resultlength=0;
1077 resultlengthout=udat_getSymbols(datfor, type, idx , NULL, resultlength, &status);
1078 if(status==U_BUFFER_OVERFLOW_ERROR)
1079 {
1080 status=U_ZERO_ERROR;
1081 resultlength=resultlengthout+1;
1082 result=(UChar*)malloc(sizeof(UChar) * resultlength);
1083 udat_getSymbols(datfor, type, idx, result, resultlength, &status);
1084
1085 }
1086 if(U_FAILURE(status))
1087 {
1088 log_err("FAIL: Error in udat_getSymbols()... %s\n", myErrorName(status) );
1089 return;
1090 }
1091 if(u_strcmp(result, pattern)==0)
1092 log_verbose("PASS: getSymbols retrieved the right value\n");
1093 else{
1094 log_data_err("FAIL: getSymbols retrieved the wrong value\n Expected %s Got %s\n", expected,
1095 aescstrdup(result,-1) );
1096 }
1097 free(result);
1098 free(pattern);
1099 }
1100
1101 static void VerifysetSymbols(UDateFormat* datfor, UDateFormatSymbolType type, int32_t idx, const char* expected)
1102 {
1103 UChar *result=NULL;
1104 UChar *value=NULL;
1105 int32_t resultlength, resultlengthout;
1106 UErrorCode status = U_ZERO_ERROR;
1107 int32_t valueLen, valueSize = strlen(expected) + 1;
1108
1109 value=(UChar*)malloc(sizeof(UChar) * valueSize);
1110 valueLen = u_unescape(expected, value, valueSize);
1111 udat_setSymbols(datfor, type, idx, value, valueLen, &status);
1112 if(U_FAILURE(status))
1113 {
1114 log_err("FAIL: Error in udat_setSymbols() %s\n", myErrorName(status) );
1115 return;
1116 }
1117
1118 resultlength=0;
1119 resultlengthout=udat_getSymbols(datfor, type, idx, NULL, resultlength, &status);
1120 if(status==U_BUFFER_OVERFLOW_ERROR){
1121 status=U_ZERO_ERROR;
1122 resultlength=resultlengthout+1;
1123 result=(UChar*)malloc(sizeof(UChar) * resultlength);
1124 udat_getSymbols(datfor, type, idx, result, resultlength, &status);
1125 }
1126 if(U_FAILURE(status)){
1127 log_err("FAIL: error in retrieving the value using getSymbols after setting it previously\n %s\n",
1128 myErrorName(status) );
1129 return;
1130 }
1131
1132 if(u_strcmp(result, value)!=0){
1133 log_err("FAIL:Error in setting and then getting symbols\n Expected %s Got %s\n", expected,
1134 aescstrdup(result,-1) );
1135 }
1136 else
1137 log_verbose("PASS: setSymbols successful\n");
1138
1139 free(value);
1140 free(result);
1141 }
1142
1143
1144 static void VerifygetsetSymbols(UDateFormat* from, UDateFormat* to, UDateFormatSymbolType type, int32_t idx)
1145 {
1146 UChar *result=NULL;
1147 UChar *value=NULL;
1148 int32_t resultlength, resultlengthout;
1149 UErrorCode status = U_ZERO_ERROR;
1150
1151 resultlength=0;
1152 resultlengthout=udat_getSymbols(from, type, idx , NULL, resultlength, &status);
1153 if(status==U_BUFFER_OVERFLOW_ERROR){
1154 status=U_ZERO_ERROR;
1155 resultlength=resultlengthout+1;
1156 result=(UChar*)malloc(sizeof(UChar) * resultlength);
1157 udat_getSymbols(from, type, idx, result, resultlength, &status);
1158 }
1159 if(U_FAILURE(status)){
1160 log_err("FAIL: error in getSymbols() %s\n", myErrorName(status) );
1161 return;
1162 }
1163
1164 resultlength=resultlengthout+1;
1165 udat_setSymbols(to, type, idx, result, resultlength, &status);
1166 if(U_FAILURE(status))
1167 {
1168 log_err("FAIL: Error in udat_setSymbols() : %s\n", myErrorName(status) );
1169 return;
1170 }
1171
1172 resultlength=0;
1173 resultlengthout=udat_getSymbols(to, type, idx, NULL, resultlength, &status);
1174 if(status==U_BUFFER_OVERFLOW_ERROR){
1175 status=U_ZERO_ERROR;
1176 resultlength=resultlengthout+1;
1177 value=(UChar*)malloc(sizeof(UChar) * resultlength);
1178 udat_getSymbols(to, type, idx, value, resultlength, &status);
1179 }
1180 if(U_FAILURE(status)){
1181 log_err("FAIL: error in retrieving the value using getSymbols i.e roundtrip\n %s\n",
1182 myErrorName(status) );
1183 return;
1184 }
1185
1186 if(u_strcmp(result, value)!=0){
1187 log_data_err("FAIL:Error in setting and then getting symbols\n Expected %s Got %s\n", austrdup(result),
1188 austrdup(value) );
1189 }
1190 else
1191 log_verbose("PASS: setSymbols successful\n");
1192
1193 free(value);
1194 free(result);
1195 }
1196
1197
1198 static UChar* myNumformat(const UNumberFormat* numfor, double d)
1199 {
1200 UChar *result2=NULL;
1201 int32_t resultlength, resultlengthneeded;
1202 UErrorCode status = U_ZERO_ERROR;
1203
1204 resultlength=0;
1205 resultlengthneeded=unum_formatDouble(numfor, d, NULL, resultlength, NULL, &status);
1206 if(status==U_BUFFER_OVERFLOW_ERROR)
1207 {
1208 status=U_ZERO_ERROR;
1209 resultlength=resultlengthneeded+1;
1210 /*result2=(UChar*)malloc(sizeof(UChar) * resultlength);*/ /* this leaks */
1211 result2=(UChar*)ctst_malloc(sizeof(UChar) * resultlength); /*this won't*/
1212 unum_formatDouble(numfor, d, result2, resultlength, NULL, &status);
1213 }
1214 if(U_FAILURE(status))
1215 {
1216 log_err("FAIL: Error in formatting using unum_format(.....) %s\n", myErrorName(status) );
1217 return 0;
1218 }
1219
1220 return result2;
1221 }
1222
1223 /**
1224 * The search depth for TestExtremeDates. The total number of
1225 * dates that will be tested is (2^EXTREME_DATES_DEPTH) - 1.
1226 */
1227 #define EXTREME_DATES_DEPTH 8
1228
1229 /**
1230 * Support for TestExtremeDates (below).
1231 *
1232 * Test a single date to see whether udat_format handles it properly.
1233 */
1234 static UBool _aux1ExtremeDates(UDateFormat* fmt, UDate date,
1235 UChar* buf, int32_t buflen, char* cbuf,
1236 UErrorCode* ec) {
1237 int32_t len = udat_format(fmt, date, buf, buflen, 0, ec);
1238 if (!assertSuccess("udat_format", ec)) return FALSE;
1239 u_austrncpy(cbuf, buf, buflen);
1240 if (len < 4) {
1241 log_err("FAIL: udat_format(%g) => \"%s\"\n", date, cbuf);
1242 } else {
1243 log_verbose("udat_format(%g) => \"%s\"\n", date, cbuf);
1244 }
1245 return TRUE;
1246 }
1247
1248 /**
1249 * Support for TestExtremeDates (below).
1250 *
1251 * Recursively test between 'small' and 'large', up to the depth
1252 * limit specified by EXTREME_DATES_DEPTH.
1253 */
1254 static UBool _aux2ExtremeDates(UDateFormat* fmt, UDate small, UDate large,
1255 UChar* buf, int32_t buflen, char* cbuf,
1256 int32_t count,
1257 UErrorCode* ec) {
1258 /* Logarithmic midpoint; see below */
1259 UDate mid = (UDate) exp((log(small) + log(large)) / 2);
1260 if (count == EXTREME_DATES_DEPTH) {
1261 return TRUE;
1262 }
1263 return
1264 _aux1ExtremeDates(fmt, mid, buf, buflen, cbuf, ec) &&
1265 _aux2ExtremeDates(fmt, small, mid, buf, buflen, cbuf, count+1, ec) &&
1266 _aux2ExtremeDates(fmt, mid, large, buf, buflen, cbuf, count+1, ec);
1267 }
1268
1269 /**
1270 * http://www.jtcsv.com/cgibin/icu-bugs?findid=3659
1271 *
1272 * For certain large dates, udat_format crashes on MacOS. This test
1273 * attempts to reproduce this problem by doing a recursive logarithmic*
1274 * binary search of a predefined interval (from 'small' to 'large').
1275 *
1276 * The limit of the search is given by EXTREME_DATES_DEPTH, above.
1277 *
1278 * *The search has to be logarithmic, not linear. A linear search of the
1279 * range 0..10^30, for example, will find 0.5*10^30, then 0.25*10^30 and
1280 * 0.75*10^30, etc. A logarithmic search will find 10^15, then 10^7.5
1281 * and 10^22.5, etc.
1282 */
1283 static void TestExtremeDates() {
1284 UDateFormat *fmt;
1285 UErrorCode ec;
1286 UChar buf[256];
1287 char cbuf[256];
1288 const double small = 1000; /* 1 sec */
1289 const double large = 1e+30; /* well beyond usable UDate range */
1290
1291 /* There is no need to test larger values from 1e+30 to 1e+300;
1292 the failures occur around 1e+27, and never above 1e+30. */
1293
1294 ec = U_ZERO_ERROR;
1295 fmt = udat_open(UDAT_LONG, UDAT_LONG, "en_US",
1296 0, 0, 0, 0, &ec);
1297 if (U_FAILURE(ec)) {
1298 log_data_err("FAIL: udat_open (%s) (Are you missing data?)\n", u_errorName(ec));
1299 return;
1300 }
1301
1302 _aux2ExtremeDates(fmt, small, large, buf, UPRV_LENGTHOF(buf), cbuf, 0, &ec);
1303
1304 udat_close(fmt);
1305 }
1306
1307 static void TestAllLocales(void) {
1308 int32_t idx, dateIdx, timeIdx, localeCount;
1309 static const UDateFormatStyle style[] = {
1310 UDAT_FULL, UDAT_LONG, UDAT_MEDIUM, UDAT_SHORT
1311 };
1312 localeCount = uloc_countAvailable();
1313 for (idx = 0; idx < localeCount; idx++) {
1314 for (dateIdx = 0; dateIdx < UPRV_LENGTHOF(style); dateIdx++) {
1315 for (timeIdx = 0; timeIdx < UPRV_LENGTHOF(style); timeIdx++) {
1316 UErrorCode status = U_ZERO_ERROR;
1317 udat_close(udat_open(style[dateIdx], style[timeIdx],
1318 uloc_getAvailable(idx), NULL, 0, NULL, 0, &status));
1319 if (U_FAILURE(status)) {
1320 log_err("FAIL: udat_open(%s) failed with (%s) dateIdx=%d, timeIdx=%d\n",
1321 uloc_getAvailable(idx), u_errorName(status), dateIdx, timeIdx);
1322 }
1323 }
1324 }
1325 }
1326 }
1327
1328 static void TestRelativeCrash(void) {
1329 static const UChar tzName[] = { 0x0055, 0x0053, 0x002F, 0x0050, 0x0061, 0x0063, 0x0069, 0x0066, 0x0069, 0x0063, 0 };
1330 static const UDate aDate = -631152000000.0;
1331
1332 UErrorCode status = U_ZERO_ERROR;
1333 UErrorCode expectStatus = U_ILLEGAL_ARGUMENT_ERROR;
1334 UDateFormat icudf;
1335
1336 icudf = udat_open(UDAT_NONE, UDAT_SHORT_RELATIVE, "en", tzName, -1, NULL, 0, &status);
1337 if ( U_SUCCESS(status) ) {
1338 const char *what = "???";
1339 {
1340 UErrorCode subStatus = U_ZERO_ERROR;
1341 what = "udat_set2DigitYearStart";
1342 log_verbose("Trying %s on a relative date..\n", what);
1343 udat_set2DigitYearStart(icudf, aDate, &subStatus);
1344 if(subStatus == expectStatus) {
1345 log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
1346 } else {
1347 log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
1348 }
1349 }
1350 {
1351 /* clone works polymorphically. try it anyways */
1352 UErrorCode subStatus = U_ZERO_ERROR;
1353 UDateFormat *oth;
1354 what = "clone";
1355 log_verbose("Trying %s on a relative date..\n", what);
1356 oth = udat_clone(icudf, &subStatus);
1357 if(subStatus == U_ZERO_ERROR) {
1358 log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
1359 udat_close(oth); /* ? */
1360 } else {
1361 log_err("FAIL: didn't crash on %s, but got %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
1362 }
1363 }
1364 {
1365 UErrorCode subStatus = U_ZERO_ERROR;
1366 what = "udat_get2DigitYearStart";
1367 log_verbose("Trying %s on a relative date..\n", what);
1368 udat_get2DigitYearStart(icudf, &subStatus);
1369 if(subStatus == expectStatus) {
1370 log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
1371 } else {
1372 log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
1373 }
1374 }
1375 {
1376 /* Now udat_toPattern works for relative date formatters, unless localized is TRUE */
1377 UErrorCode subStatus = U_ZERO_ERROR;
1378 what = "udat_toPattern";
1379 log_verbose("Trying %s on a relative date..\n", what);
1380 udat_toPattern(icudf, TRUE,NULL,0, &subStatus);
1381 if(subStatus == expectStatus) {
1382 log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
1383 } else {
1384 log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
1385 }
1386 }
1387 {
1388 UErrorCode subStatus = U_ZERO_ERROR;
1389 what = "udat_applyPattern";
1390 log_verbose("Trying %s on a relative date..\n", what);
1391 udat_applyPattern(icudf, FALSE,tzName,-1);
1392 subStatus = U_ILLEGAL_ARGUMENT_ERROR; /* what it should be, if this took an errorcode. */
1393 if(subStatus == expectStatus) {
1394 log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
1395 } else {
1396 log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
1397 }
1398 }
1399 {
1400 UChar erabuf[32];
1401 UErrorCode subStatus = U_ZERO_ERROR;
1402 what = "udat_getSymbols";
1403 log_verbose("Trying %s on a relative date..\n", what);
1404 udat_getSymbols(icudf, UDAT_ERAS,0,erabuf,UPRV_LENGTHOF(erabuf), &subStatus);
1405 if(subStatus == U_ZERO_ERROR) {
1406 log_verbose("Success: %s returned %s.\n", what, u_errorName(subStatus));
1407 } else {
1408 log_err("FAIL: didn't crash on %s, but got %s instead of U_ZERO_ERROR.\n", what, u_errorName(subStatus));
1409 }
1410 }
1411 {
1412 UErrorCode subStatus = U_ZERO_ERROR;
1413 UChar symbolValue = 0x0041;
1414 what = "udat_setSymbols";
1415 log_verbose("Trying %s on a relative date..\n", what);
1416 udat_setSymbols(icudf, UDAT_ERAS,0,&symbolValue,1, &subStatus); /* bogus values */
1417 if(subStatus == expectStatus) {
1418 log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
1419 } else {
1420 log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
1421 }
1422 }
1423 {
1424 UErrorCode subStatus = U_ZERO_ERROR;
1425 what = "udat_countSymbols";
1426 log_verbose("Trying %s on a relative date..\n", what);
1427 udat_countSymbols(icudf, UDAT_ERAS);
1428 subStatus = U_ILLEGAL_ARGUMENT_ERROR; /* should have an errorcode. */
1429 if(subStatus == expectStatus) {
1430 log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
1431 } else {
1432 log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
1433 }
1434 }
1435
1436 udat_close(icudf);
1437 } else {
1438 log_data_err("FAIL: err calling udat_open() ->%s (Are you missing data?)\n", u_errorName(status));
1439 }
1440 }
1441
1442 static const UChar skeleton_yMMMM[] = { 0x79,0x4D,0x4D,0x4D,0x4D,0 }; /* "yMMMM"; fr maps to "MMMM y", cs maps to "LLLL y" */
1443 static const UChar july2008_frDefault[] = { 0x6A,0x75,0x69,0x6C,0x6C,0x65,0x74,0x20,0x32,0x30,0x30,0x38,0 }; /* "juillet 2008" */
1444 static const UChar july2008_frTitle[] = { 0x4A,0x75,0x69,0x6C,0x6C,0x65,0x74,0x20,0x32,0x30,0x30,0x38,0 }; /* "Juillet 2008" sentence-begin, standalone */
1445 static const UChar july2008_csDefault[] = { 0x10D,0x65,0x72,0x76,0x65,0x6E,0x65,0x63,0x20,0x32,0x30,0x30,0x38,0 }; /* "c(hacek)ervenec 2008" */
1446 static const UChar july2008_csTitle[] = { 0x10C,0x65,0x72,0x76,0x65,0x6E,0x65,0x63,0x20,0x32,0x30,0x30,0x38,0 }; /* "C(hacek)ervenec 2008" sentence-begin, uiListOrMenu */
1447
1448 typedef struct {
1449 const char * locale;
1450 const UChar * skeleton;
1451 UDisplayContext capitalizationContext;
1452 const UChar * expectedFormat;
1453 } TestContextItem;
1454
1455 static const TestContextItem textContextItems[] = {
1456 { "fr", skeleton_yMMMM, UDISPCTX_CAPITALIZATION_NONE, july2008_frDefault },
1457 #if !UCONFIG_NO_BREAK_ITERATION
1458 { "fr", skeleton_yMMMM, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, july2008_frDefault },
1459 { "fr", skeleton_yMMMM, UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, july2008_frTitle },
1460 { "fr", skeleton_yMMMM, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, july2008_frDefault },
1461 { "fr", skeleton_yMMMM, UDISPCTX_CAPITALIZATION_FOR_STANDALONE, july2008_frTitle },
1462 #endif
1463 { "cs", skeleton_yMMMM, UDISPCTX_CAPITALIZATION_NONE, july2008_csDefault },
1464 #if !UCONFIG_NO_BREAK_ITERATION
1465 { "cs", skeleton_yMMMM, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, july2008_csDefault },
1466 { "cs", skeleton_yMMMM, UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, july2008_csTitle },
1467 { "cs", skeleton_yMMMM, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, july2008_csTitle },
1468 { "cs", skeleton_yMMMM, UDISPCTX_CAPITALIZATION_FOR_STANDALONE, july2008_csDefault },
1469 #endif
1470 { NULL, NULL, (UDisplayContext)0, NULL }
1471 };
1472
1473 static const UChar today_enDefault[] = { 0x74,0x6F,0x64,0x61,0x79,0 }; /* "today" */
1474 static const UChar today_enTitle[] = { 0x54,0x6F,0x64,0x61,0x79,0 }; /* "Today" sentence-begin, uiListOrMenu, standalone */
1475 static const UChar yesterday_enDefault[] = { 0x79,0x65,0x73,0x74,0x65,0x72,0x64,0x61,0x79,0 }; /* "yesterday" */
1476 static const UChar yesterday_enTitle[] = { 0x59,0x65,0x73,0x74,0x65,0x72,0x64,0x61,0x79,0 }; /* "Yesterday" sentence-begin, uiListOrMenu, standalone */
1477 static const UChar today_nbDefault[] = { 0x69,0x20,0x64,0x61,0x67,0 }; /* "i dag" */
1478 static const UChar today_nbTitle[] = { 0x49,0x20,0x64,0x61,0x67,0 }; /* "I dag" sentence-begin, standalone */
1479 static const UChar yesterday_nbDefault[] = { 0x69,0x20,0x67,0xE5,0x72,0 };
1480 static const UChar yesterday_nbTitle[] = { 0x49,0x20,0x67,0xE5,0x72,0 };
1481
1482 typedef struct {
1483 const char * locale;
1484 UDisplayContext capitalizationContext;
1485 const UChar * expectedFormatToday;
1486 const UChar * expectedFormatYesterday;
1487 } TestRelativeContextItem;
1488
1489 static const TestRelativeContextItem textContextRelativeItems[] = {
1490 { "en", UDISPCTX_CAPITALIZATION_NONE, today_enDefault, yesterday_enDefault },
1491 #if !UCONFIG_NO_BREAK_ITERATION
1492 { "en", UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, today_enDefault, yesterday_enDefault },
1493 { "en", UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, today_enTitle, yesterday_enTitle },
1494 { "en", UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, today_enTitle, yesterday_enTitle },
1495 { "en", UDISPCTX_CAPITALIZATION_FOR_STANDALONE, today_enTitle, yesterday_enTitle },
1496 #endif
1497 { "nb", UDISPCTX_CAPITALIZATION_NONE, today_nbDefault, yesterday_nbDefault },
1498 #if !UCONFIG_NO_BREAK_ITERATION
1499 { "nb", UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, today_nbDefault, yesterday_nbDefault },
1500 { "nb", UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, today_nbTitle, yesterday_nbTitle },
1501 { "nb", UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, today_nbDefault, yesterday_nbDefault },
1502 { "nb", UDISPCTX_CAPITALIZATION_FOR_STANDALONE, today_nbTitle, yesterday_nbTitle },
1503 #endif
1504 { NULL, (UDisplayContext)0, NULL, NULL }
1505 };
1506
1507 static const UChar january_esDefault[] = { 0x65,0x6E,0x65,0x72,0x6F,0 }; /* "enero" */
1508 static const UChar january_esTitle[] = { 0x45,0x6E,0x65,0x72,0x6F,0 }; /* "Enero */
1509 static const UChar monday_daDefault[] = { 0x6D,0x61,0x6E,0x64,0x61,0x67,0 }; /* "mandag" */
1510 static const UChar monday_daTitle[] = { 0x4D,0x61,0x6E,0x64,0x61,0x67,0 }; /* "Mandag */
1511
1512 typedef struct {
1513 const char * locale;
1514 UDateFormatSymbolType type;
1515 int32_t index;
1516 UDisplayContext capitalizationContext;
1517 const UChar * expectedFormat;
1518 } TestSymbolContextItem;
1519
1520 static const TestSymbolContextItem testContextSymbolItems[] = {
1521 { "es", UDAT_MONTHS, 0, UDISPCTX_CAPITALIZATION_NONE, january_esDefault },
1522 #if !UCONFIG_NO_BREAK_ITERATION
1523 { "es", UDAT_MONTHS, 0, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, january_esDefault },
1524 { "es", UDAT_MONTHS, 0, UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, january_esTitle },
1525 { "es", UDAT_MONTHS, 0, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, january_esTitle },
1526 { "es", UDAT_MONTHS, 0, UDISPCTX_CAPITALIZATION_FOR_STANDALONE, january_esTitle },
1527 #endif
1528 { "da", UDAT_WEEKDAYS, 2, UDISPCTX_CAPITALIZATION_NONE, monday_daDefault },
1529 #if !UCONFIG_NO_BREAK_ITERATION
1530 { "da", UDAT_WEEKDAYS, 2, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, monday_daDefault },
1531 { "da", UDAT_WEEKDAYS, 2, UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, monday_daTitle },
1532 { "da", UDAT_WEEKDAYS, 2, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, monday_daDefault },
1533 { "da", UDAT_WEEKDAYS, 2, UDISPCTX_CAPITALIZATION_FOR_STANDALONE, monday_daDefault },
1534 #endif
1535 { NULL, (UDateFormatSymbolType)0, 0, (UDisplayContext)0, NULL }
1536 };
1537
1538 static const UChar zoneGMT[] = { 0x47,0x4D,0x54,0 }; /* "GMT" */
1539 static const UDate july022008 = 1215000000000.0;
1540 enum { kUbufMax = 64, kBbufMax = 3*kUbufMax };
1541
1542 static void TestContext(void) {
1543 const TestContextItem* textContextItemPtr;
1544 const TestRelativeContextItem* textRelContextItemPtr;
1545 const TestSymbolContextItem* testSymContextItemPtr;
1546
1547 for (textContextItemPtr = textContextItems; textContextItemPtr->locale != NULL; ++textContextItemPtr) {
1548 UErrorCode status = U_ZERO_ERROR;
1549 UDateTimePatternGenerator* udtpg = udatpg_open(textContextItemPtr->locale, &status);
1550 if ( U_SUCCESS(status) ) {
1551 UChar ubuf[kUbufMax];
1552 int32_t len = udatpg_getBestPattern(udtpg, textContextItemPtr->skeleton, -1, ubuf, kUbufMax, &status);
1553 if ( U_SUCCESS(status) ) {
1554 UDateFormat* udfmt = udat_open(UDAT_PATTERN, UDAT_PATTERN, textContextItemPtr->locale, zoneGMT, -1, ubuf, len, &status);
1555 if ( U_SUCCESS(status) ) {
1556 udat_setContext(udfmt, textContextItemPtr->capitalizationContext, &status);
1557 if ( U_SUCCESS(status) ) {
1558 UDisplayContext getContext;
1559 len = udat_format(udfmt, july022008, ubuf, kUbufMax, NULL, &status);
1560 if ( U_FAILURE(status) ) {
1561 log_err("FAIL: udat_format for locale %s, capitalizationContext %d, status %s\n",
1562 textContextItemPtr->locale, (int)textContextItemPtr->capitalizationContext, u_errorName(status) );
1563 status = U_ZERO_ERROR;
1564 } else if (u_strncmp(ubuf, textContextItemPtr->expectedFormat, kUbufMax) != 0) {
1565 char bbuf1[kBbufMax];
1566 char bbuf2[kBbufMax];
1567 log_err("FAIL: udat_format for locale %s, capitalizationContext %d, expected %s, got %s\n",
1568 textContextItemPtr->locale, (int)textContextItemPtr->capitalizationContext,
1569 u_austrncpy(bbuf1,textContextItemPtr->expectedFormat,kUbufMax), u_austrncpy(bbuf2,ubuf,kUbufMax) );
1570 }
1571 getContext = udat_getContext(udfmt, UDISPCTX_TYPE_CAPITALIZATION, &status);
1572 if ( U_FAILURE(status) ) {
1573 log_err("FAIL: udat_getContext for locale %s, capitalizationContext %d, status %s\n",
1574 textContextItemPtr->locale, (int)textContextItemPtr->capitalizationContext, u_errorName(status) );
1575 } else if (getContext != textContextItemPtr->capitalizationContext) {
1576 log_err("FAIL: udat_getContext for locale %s, capitalizationContext %d, got context %d\n",
1577 textContextItemPtr->locale, (int)textContextItemPtr->capitalizationContext, (int)getContext );
1578 }
1579 } else {
1580 log_err("FAIL: udat_setContext for locale %s, capitalizationContext %d, status %s\n",
1581 textContextItemPtr->locale, (int)textContextItemPtr->capitalizationContext, u_errorName(status) );
1582 }
1583 udat_close(udfmt);
1584 } else {
1585 log_data_err("FAIL: udat_open for locale %s, status %s\n", textContextItemPtr->locale, u_errorName(status) );
1586 }
1587 } else {
1588 log_err("FAIL: udatpg_getBestPattern for locale %s, status %s\n", textContextItemPtr->locale, u_errorName(status) );
1589 }
1590 udatpg_close(udtpg);
1591 } else {
1592 log_data_err("FAIL: udatpg_open for locale %s, status %s\n", textContextItemPtr->locale, u_errorName(status) );
1593 }
1594 }
1595
1596 for (textRelContextItemPtr = textContextRelativeItems; textRelContextItemPtr->locale != NULL; ++textRelContextItemPtr) {
1597 UErrorCode status = U_ZERO_ERROR;
1598 UCalendar* ucal = ucal_open(zoneGMT, -1, "root", UCAL_GREGORIAN, &status);
1599 if ( U_SUCCESS(status) ) {
1600 UDateFormat* udfmt = udat_open(UDAT_NONE, UDAT_LONG_RELATIVE, textRelContextItemPtr->locale, zoneGMT, -1, NULL, 0, &status);
1601 if ( U_SUCCESS(status) ) {
1602 udat_setContext(udfmt, textRelContextItemPtr->capitalizationContext, &status);
1603 if ( U_SUCCESS(status) ) {
1604 UDate yesterday, today = ucal_getNow();
1605 UChar ubuf[kUbufMax];
1606 char bbuf1[kBbufMax];
1607 char bbuf2[kBbufMax];
1608 int32_t len = udat_format(udfmt, today, ubuf, kUbufMax, NULL, &status);
1609 (void)len;
1610 if ( U_FAILURE(status) ) {
1611 log_err("FAIL: udat_format today for locale %s, capitalizationContext %d, status %s\n",
1612 textRelContextItemPtr->locale, (int)textRelContextItemPtr->capitalizationContext, u_errorName(status) );
1613 } else if (u_strncmp(ubuf, textRelContextItemPtr->expectedFormatToday, kUbufMax) != 0) {
1614 log_err("FAIL: udat_format today for locale %s, capitalizationContext %d, expected %s, got %s\n",
1615 textRelContextItemPtr->locale, (int)textRelContextItemPtr->capitalizationContext,
1616 u_austrncpy(bbuf1,textRelContextItemPtr->expectedFormatToday,kUbufMax), u_austrncpy(bbuf2,ubuf,kUbufMax) );
1617 }
1618 status = U_ZERO_ERROR;
1619 ucal_setMillis(ucal, today, &status);
1620 ucal_add(ucal, UCAL_DATE, -1, &status);
1621 yesterday = ucal_getMillis(ucal, &status);
1622 if ( U_SUCCESS(status) ) {
1623 len = udat_format(udfmt, yesterday, ubuf, kUbufMax, NULL, &status);
1624 if ( U_FAILURE(status) ) {
1625 log_err("FAIL: udat_format yesterday for locale %s, capitalizationContext %d, status %s\n",
1626 textRelContextItemPtr->locale, (int)textRelContextItemPtr->capitalizationContext, u_errorName(status) );
1627 } else if (u_strncmp(ubuf, textRelContextItemPtr->expectedFormatYesterday, kUbufMax) != 0) {
1628 log_err("FAIL: udat_format yesterday for locale %s, capitalizationContext %d, expected %s, got %s\n",
1629 textRelContextItemPtr->locale, (int)textRelContextItemPtr->capitalizationContext,
1630 u_austrncpy(bbuf1,textRelContextItemPtr->expectedFormatYesterday,kUbufMax), u_austrncpy(bbuf2,ubuf,kUbufMax) );
1631 }
1632 }
1633 } else {
1634 log_err("FAIL: udat_setContext relative for locale %s, capitalizationContext %d, status %s\n",
1635 textRelContextItemPtr->locale, (int)textRelContextItemPtr->capitalizationContext, u_errorName(status) );
1636 }
1637 udat_close(udfmt);
1638 } else {
1639 log_data_err("FAIL: udat_open relative for locale %s, status %s\n", textRelContextItemPtr->locale, u_errorName(status) );
1640 }
1641 ucal_close(ucal);
1642 } else {
1643 log_data_err("FAIL: ucal_open for locale root, status %s\n", u_errorName(status) );
1644 }
1645 }
1646
1647 for (testSymContextItemPtr = testContextSymbolItems; testSymContextItemPtr->locale != NULL; ++testSymContextItemPtr) {
1648 UErrorCode status = U_ZERO_ERROR;
1649 UDateFormat* udfmt = udat_open(UDAT_MEDIUM, UDAT_FULL, testSymContextItemPtr->locale, zoneGMT, -1, NULL, 0, &status);
1650 if ( U_SUCCESS(status) ) {
1651 udat_setContext(udfmt, testSymContextItemPtr->capitalizationContext, &status);
1652 if ( U_SUCCESS(status) ) {
1653 UChar ubuf[kUbufMax];
1654 int32_t len = udat_getSymbols(udfmt, testSymContextItemPtr->type, testSymContextItemPtr->index, ubuf, kUbufMax, &status);
1655 if ( U_FAILURE(status) ) {
1656 log_err("FAIL: udat_getSymbols for locale %s, capitalizationContext %d, status %s\n",
1657 testSymContextItemPtr->locale, (int)testSymContextItemPtr->capitalizationContext, u_errorName(status) );
1658 } else if (u_strncmp(ubuf, testSymContextItemPtr->expectedFormat, kUbufMax) != 0) {
1659 char bbuf1[kBbufMax];
1660 char bbuf2[kBbufMax];
1661 log_err("FAIL: udat_getSymbols for locale %s, capitalizationContext %d, expected %s, got %s\n",
1662 testSymContextItemPtr->locale, (int)testSymContextItemPtr->capitalizationContext,
1663 u_austrncpy(bbuf1,testSymContextItemPtr->expectedFormat,kUbufMax), u_austrncpy(bbuf2,ubuf,kUbufMax) );
1664 }
1665 } else {
1666 log_err("FAIL: udat_setContext std for locale %s, capitalizationContext %d, status %s\n",
1667 testSymContextItemPtr->locale, (int)testSymContextItemPtr->capitalizationContext, u_errorName(status) );
1668 }
1669 udat_close(udfmt);
1670 } else {
1671 log_data_err("FAIL: udat_open std for locale %s, status %s\n", testSymContextItemPtr->locale, u_errorName(status) );
1672 }
1673 }
1674 }
1675
1676
1677 // overrideNumberFormat[i][0] is to tell which field to set,
1678 // overrideNumberFormat[i][1] is the expected result
1679 static const char * overrideNumberFormat[][2] = {
1680 {"", "\\u521D\\u4E03 \\u521D\\u4E8C"},
1681 {"d", "07 \\u521D\\u4E8C"},
1682 {"do", "07 \\u521D\\u4E8C"},
1683 {"Md", "\\u521D\\u4E03 \\u521D\\u4E8C"},
1684 {"MdMMd", "\\u521D\\u4E03 \\u521D\\u4E8C"},
1685 {"mixed", "\\u521D\\u4E03 \\u521D\\u4E8C"}
1686 };
1687
1688 static void TestOverrideNumberFormat(void) {
1689 UErrorCode status = U_ZERO_ERROR;
1690 UChar pattern[50];
1691 UChar expected[50];
1692 UChar fields[50];
1693 char bbuf1[kBbufMax];
1694 char bbuf2[kBbufMax];
1695 const char* localeString = "zh@numbers=hanidays";
1696 UDateFormat* fmt;
1697 const UNumberFormat* getter_result;
1698 int32_t i;
1699
1700 u_uastrcpy(fields, "d");
1701 u_uastrcpy(pattern,"MM d");
1702
1703 fmt=udat_open(UDAT_PATTERN, UDAT_PATTERN, "en_US", zoneGMT, -1, pattern, u_strlen(pattern), &status);
1704 if (!assertSuccess("udat_open()", &status)) {
1705 return;
1706 }
1707
1708 // loop 5 times to check getter/setter
1709 for (i = 0; i < 5; i++){
1710 UNumberFormat* overrideFmt;
1711 overrideFmt = unum_open(UNUM_DEFAULT, NULL, 0, localeString, NULL, &status);
1712 assertSuccess("unum_open()", &status);
1713 udat_adoptNumberFormatForFields(fmt, fields, overrideFmt, &status);
1714 overrideFmt = NULL; // no longer valid
1715 assertSuccess("udat_setNumberFormatForField()", &status);
1716
1717 getter_result = udat_getNumberFormatForField(fmt, 0x0064 /*'d'*/);
1718 if(getter_result == NULL) {
1719 log_err("FAIL: udat_getNumberFormatForField did not return a valid pointer\n");
1720 }
1721 }
1722 {
1723 UNumberFormat* overrideFmt;
1724 overrideFmt = unum_open(UNUM_DEFAULT, NULL, 0, localeString, NULL, &status);
1725 assertSuccess("unum_open()", &status);
1726 udat_setNumberFormat(fmt, overrideFmt); // test the same override NF will not crash
1727 unum_close(overrideFmt);
1728 }
1729 udat_close(fmt);
1730
1731 for (i=0; i<UPRV_LENGTHOF(overrideNumberFormat); i++){
1732 UChar ubuf[kUbufMax];
1733 UDateFormat* fmt2;
1734 UNumberFormat* overrideFmt2;
1735
1736 fmt2 =udat_open(UDAT_PATTERN, UDAT_PATTERN,"en_US", zoneGMT, -1, pattern, u_strlen(pattern), &status);
1737 assertSuccess("udat_open() with en_US", &status);
1738
1739 overrideFmt2 = unum_open(UNUM_DEFAULT, NULL, 0, localeString, NULL, &status);
1740 assertSuccess("unum_open() in loop", &status);
1741
1742 u_uastrcpy(fields, overrideNumberFormat[i][0]);
1743 u_unescape(overrideNumberFormat[i][1], expected, UPRV_LENGTHOF(expected));
1744
1745 if ( strcmp(overrideNumberFormat[i][0], "") == 0 ) { // use the one w/o field
1746 udat_adoptNumberFormat(fmt2, overrideFmt2);
1747 } else if ( strcmp(overrideNumberFormat[i][0], "mixed") == 0 ) { // set 1 field at first but then full override, both(M & d) should be override
1748 const char* singleLocale = "en@numbers=hebr";
1749 UNumberFormat* singleOverrideFmt;
1750 u_uastrcpy(fields, "d");
1751
1752 singleOverrideFmt = unum_open(UNUM_DEFAULT, NULL, 0, singleLocale, NULL, &status);
1753 assertSuccess("unum_open() in mixed", &status);
1754
1755 udat_adoptNumberFormatForFields(fmt2, fields, singleOverrideFmt, &status);
1756 assertSuccess("udat_setNumberFormatForField() in mixed", &status);
1757
1758 udat_adoptNumberFormat(fmt2, overrideFmt2);
1759 } else if ( strcmp(overrideNumberFormat[i][0], "do") == 0 ) { // o is an invalid field
1760 udat_adoptNumberFormatForFields(fmt2, fields, overrideFmt2, &status);
1761 if(status == U_INVALID_FORMAT_ERROR) {
1762 udat_close(fmt2);
1763 status = U_ZERO_ERROR;
1764 continue;
1765 }
1766 } else {
1767 udat_adoptNumberFormatForFields(fmt2, fields, overrideFmt2, &status);
1768 assertSuccess("udat_setNumberFormatForField() in loop", &status);
1769 }
1770
1771 udat_format(fmt2, july022008, ubuf, kUbufMax, NULL, &status);
1772 assertSuccess("udat_format() july022008", &status);
1773
1774 if (u_strncmp(ubuf, expected, kUbufMax) != 0)
1775 log_err("fail: udat_format for locale, expected %s, got %s\n",
1776 u_austrncpy(bbuf1,expected,kUbufMax), u_austrncpy(bbuf2,ubuf,kUbufMax) );
1777
1778 udat_close(fmt2);
1779 }
1780 }
1781
1782 /*
1783 * Ticket #11523
1784 * udat_parse and udat_parseCalendar should have the same error code when given the same invalid input.
1785 */
1786 static void TestParseErrorReturnValue(void) {
1787 UErrorCode status = U_ZERO_ERROR;
1788 UErrorCode expectStatus = U_PARSE_ERROR;
1789 UDateFormat* df;
1790 UCalendar* cal;
1791
1792 df = udat_open(UDAT_DEFAULT, UDAT_DEFAULT, NULL, NULL, -1, NULL, -1, &status);
1793 if (!assertSuccessCheck("udat_open()", &status, TRUE)) {
1794 return;
1795 }
1796
1797 cal = ucal_open(NULL, 0, "en_US", UCAL_GREGORIAN, &status);
1798 if (!assertSuccess("ucal_open()", &status)) {
1799 return;
1800 }
1801
1802 udat_parse(df, NULL, -1, NULL, &status);
1803 if (status != expectStatus) {
1804 log_err("%s should have been returned by udat_parse when given an invalid input, instead got - %s\n", u_errorName(expectStatus), u_errorName(status));
1805 }
1806
1807 status = U_ZERO_ERROR;
1808 udat_parseCalendar(df, cal, NULL, -1, NULL, &status);
1809 if (status != expectStatus) {
1810 log_err("%s should have been returned by udat_parseCalendar when given an invalid input, instead got - %s\n", u_errorName(expectStatus), u_errorName(status));
1811 }
1812
1813 ucal_close(cal);
1814 udat_close(df);
1815 }
1816
1817 /*
1818 * Ticket #11553
1819 * Test new udat_formatForFields, udat_formatCalendarForFields (and UFieldPositionIterator)
1820 */
1821 static const char localeForFields[] = "en_US";
1822 /* zoneGMT[]defined above */
1823 static const UDate date2015Feb25 = 1424841000000.0; /* Wednesday, February 25, 2015 at 5:10:00 AM GMT */
1824 static const UChar patNoFields[] = { 0x0027, 0x0078, 0x0078, 0x0078, 0x0027, 0 }; /* "'xxx'" */
1825
1826 typedef struct {
1827 int32_t field;
1828 int32_t beginPos;
1829 int32_t endPos;
1830 } FieldsData;
1831 static const FieldsData expectedFields[] = {
1832 { UDAT_DAY_OF_WEEK_FIELD /* 9*/, 0, 9 },
1833 { UDAT_MONTH_FIELD /* 2*/, 11, 19 },
1834 { UDAT_DATE_FIELD /* 3*/, 20, 22 },
1835 { UDAT_YEAR_FIELD /* 1*/, 24, 28 },
1836 { UDAT_HOUR1_FIELD /*15*/, 32, 33 },
1837 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
1838 { UDAT_TIME_SEPARATOR_FIELD /*35*/, 33, 34 },
1839 #endif
1840 { UDAT_MINUTE_FIELD /* 6*/, 34, 36 },
1841 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
1842 { UDAT_TIME_SEPARATOR_FIELD /*35*/, 36, 37 },
1843 #endif
1844 { UDAT_SECOND_FIELD /* 7*/, 37, 39 },
1845 { UDAT_AM_PM_FIELD /*14*/, 40, 42 },
1846 { UDAT_TIMEZONE_FIELD /*17*/, 43, 46 },
1847 { -1, -1, -1 },
1848 };
1849
1850 enum {kUBufFieldsLen = 128, kBBufFieldsLen = 256 };
1851
1852 static void TestFormatForFields(void) {
1853 UErrorCode status = U_ZERO_ERROR;
1854 UFieldPositionIterator* fpositer = ufieldpositer_open(&status);
1855 if ( U_FAILURE(status) ) {
1856 log_err("ufieldpositer_open fails, status %s\n", u_errorName(status));
1857 } else {
1858 UDateFormat* udfmt = udat_open(UDAT_LONG, UDAT_FULL, localeForFields, zoneGMT, -1, NULL, 0, &status);
1859 UCalendar* ucal = ucal_open(zoneGMT, -1, localeForFields, UCAL_DEFAULT, &status);
1860 if ( U_FAILURE(status) ) {
1861 log_data_err("udat_open or ucal_open fails for locale %s, status %s (Are you missing data?)\n", localeForFields, u_errorName(status));
1862 } else {
1863 int32_t ulen, field, beginPos, endPos;
1864 UChar ubuf[kUBufFieldsLen];
1865 const FieldsData * fptr;
1866
1867 status = U_ZERO_ERROR;
1868 ulen = udat_formatForFields(udfmt, date2015Feb25, ubuf, kUBufFieldsLen, fpositer, &status);
1869 if ( U_FAILURE(status) ) {
1870 log_err("udat_formatForFields fails, status %s\n", u_errorName(status));
1871 } else {
1872 for (fptr = expectedFields; ; fptr++) {
1873 field = ufieldpositer_next(fpositer, &beginPos, &endPos);
1874 if (field != fptr->field || (field >= 0 && (beginPos != fptr->beginPos || endPos != fptr->endPos))) {
1875 if (fptr->field >= 0) {
1876 log_err("udat_formatForFields as \"%s\"; expect field %d range %d-%d, get field %d range %d-%d\n",
1877 aescstrdup(ubuf, ulen), fptr->field, fptr->beginPos, fptr->endPos, field, beginPos, endPos);
1878 } else {
1879 log_err("udat_formatForFields as \"%s\"; expect field < 0, get field %d range %d-%d\n",
1880 aescstrdup(ubuf, ulen), field, beginPos, endPos);
1881 }
1882 break;
1883 }
1884 if (field < 0) {
1885 break;
1886 }
1887 }
1888 }
1889
1890 ucal_setMillis(ucal, date2015Feb25, &status);
1891 status = U_ZERO_ERROR;
1892 ulen = udat_formatCalendarForFields(udfmt, ucal, ubuf, kUBufFieldsLen, fpositer, &status);
1893 if ( U_FAILURE(status) ) {
1894 log_err("udat_formatCalendarForFields fails, status %s\n", u_errorName(status));
1895 } else {
1896 for (fptr = expectedFields; ; fptr++) {
1897 field = ufieldpositer_next(fpositer, &beginPos, &endPos);
1898 if (field != fptr->field || (field >= 0 && (beginPos != fptr->beginPos || endPos != fptr->endPos))) {
1899 if (fptr->field >= 0) {
1900 log_err("udat_formatFudat_formatCalendarForFieldsorFields as \"%s\"; expect field %d range %d-%d, get field %d range %d-%d\n",
1901 aescstrdup(ubuf, ulen), fptr->field, fptr->beginPos, fptr->endPos, field, beginPos, endPos);
1902 } else {
1903 log_err("udat_formatCalendarForFields as \"%s\"; expect field < 0, get field %d range %d-%d\n",
1904 aescstrdup(ubuf, ulen), field, beginPos, endPos);
1905 }
1906 break;
1907 }
1908 if (field < 0) {
1909 break;
1910 }
1911 }
1912 }
1913
1914 udat_applyPattern(udfmt, FALSE, patNoFields, -1);
1915 status = U_ZERO_ERROR;
1916 ulen = udat_formatForFields(udfmt, date2015Feb25, ubuf, kUBufFieldsLen, fpositer, &status);
1917 if ( U_FAILURE(status) ) {
1918 log_err("udat_formatForFields with no-field pattern fails, status %s\n", u_errorName(status));
1919 } else {
1920 field = ufieldpositer_next(fpositer, &beginPos, &endPos);
1921 if (field >= 0) {
1922 log_err("udat_formatForFields with no-field pattern as \"%s\"; expect field < 0, get field %d range %d-%d\n",
1923 aescstrdup(ubuf, ulen), field, beginPos, endPos);
1924 }
1925 }
1926
1927 ucal_close(ucal);
1928 udat_close(udfmt);
1929 }
1930 ufieldpositer_close(fpositer);
1931 }
1932 }
1933
1934 /* defined above
1935 static const UChar zoneGMT[] = { 0x47,0x4D,0x54,0 }; // "GMT"
1936 static const UDate date2015Feb25 = 1424841000000.0; // Wednesday, February 25, 2015 at 5:10:00 AM GMT
1937 */
1938
1939 typedef struct {
1940 const char * locale;
1941 UDateFormatStyle dateStyle;
1942 UDateFormatStyle timeStyle;
1943 const char * expect; /* for zoneGMT and date2015Feb25 */
1944 } StandardPatternItem;
1945
1946 static const StandardPatternItem stdPatternItems[] = {
1947 { "en_JP", UDAT_MEDIUM, UDAT_SHORT, "Feb 25, 2015 5:10" },
1948 { "en_CN", UDAT_MEDIUM, UDAT_SHORT, "25 Feb 2015 at 5:10 AM" },
1949 { "en_TW", UDAT_MEDIUM, UDAT_SHORT, "25 Feb 2015 at 5:10 AM" },
1950 { "en_KR", UDAT_MEDIUM, UDAT_SHORT, "25 Feb 2015 at 5:10 AM" },
1951 { NULL, (UDateFormatStyle)0, (UDateFormatStyle)0, NULL } /* terminator */
1952 };
1953
1954 enum { kUbufStdMax = 64, kBbufStdMax = 3*kUbufStdMax };
1955
1956 static void TestStandardPatterns(void) {
1957 const StandardPatternItem* itemPtr;
1958 for (itemPtr = stdPatternItems; itemPtr->locale != NULL; itemPtr++) {
1959 UErrorCode status = U_ZERO_ERROR;
1960 UDateFormat* udfmt = udat_open(itemPtr->timeStyle, itemPtr->dateStyle, itemPtr->locale, zoneGMT, -1, NULL, 0, &status);
1961 if ( U_FAILURE(status) ) {
1962 log_err("udat_open(%d, %d, \"%s\",...) fails, status %s\n",
1963 (int)itemPtr->timeStyle, (int)itemPtr->dateStyle, itemPtr->locale, u_errorName(status));
1964 } else {
1965 UChar uget[kUbufStdMax];
1966 int32_t ugetlen = udat_format(udfmt, date2015Feb25, uget, kUbufStdMax, NULL, &status);
1967 if ( U_FAILURE(status) ) {
1968 log_err("udat_format for (%d, %d, \"%s\",...) fails, status %s\n",
1969 (int)itemPtr->timeStyle, (int)itemPtr->dateStyle, itemPtr->locale, u_errorName(status));
1970 } else {
1971 UChar uexpect[kUbufStdMax];
1972 int32_t uexpectlen = u_unescape(itemPtr->expect, uexpect, kUbufStdMax);
1973 if (ugetlen != uexpectlen || u_strncmp(uget, uexpect, uexpectlen) != 0) {
1974 char bexpect[kBbufStdMax];
1975 char bget[kBbufStdMax];
1976 u_austrcpy(bexpect, uexpect);
1977 u_austrcpy(bget, uget);
1978 log_err("udat_format for (%d, %d, \"%s\",...):\n expect %s\n get %s\n",
1979 (int)itemPtr->timeStyle, (int)itemPtr->dateStyle, itemPtr->locale, bexpect, bget);
1980 }
1981 }
1982 udat_close(udfmt);
1983 }
1984 }
1985 }
1986
1987 /* defined above
1988 static const UChar zoneGMT[] = { 0x47,0x4D,0x54,0 }; // "GMT"
1989 static const UDate date2015Feb25 = 1424841000000.0; // Wednesday, February 25, 2015 at 5:10:00 AM GMT
1990 */
1991 static const UChar patternHmm[] = { 0x48,0x3A,0x6D,0x6D,0 }; /* "H:mm" */
1992 static const UChar formattedHmm[] = { 0x35,0x3A,0x31,0x30,0 }; /* "5:10" */
1993
1994 enum { kUBufOverrideSepMax = 32, kBBufOverrideSepMax = 64 };
1995
1996 static void TestApplyPatnOverridesTimeSep(void) {
1997 UErrorCode status;
1998 UDateFormat* udfmt;
1999 const char *locale = "da"; /* uses period for time separator */
2000 UChar ubuf[kUBufOverrideSepMax];
2001 int32_t ulen;
2002
2003 status = U_ZERO_ERROR;
2004 udfmt = udat_open(UDAT_PATTERN, UDAT_PATTERN, locale, zoneGMT, -1, patternHmm, -1, &status);
2005 if ( U_FAILURE(status) ) {
2006 log_err("udat_open(UDAT_PATTERN, UDAT_PATTERN, \"%s\",...) fails, status %s\n", locale, u_errorName(status));
2007 } else {
2008 ulen = udat_format(udfmt, date2015Feb25, ubuf, kUBufOverrideSepMax, NULL, &status);
2009 if ( U_FAILURE(status) ) {
2010 log_err("udat_format fails for UDAT_PATTERN \"%s\", status %s\n", locale, u_errorName(status));
2011 } else if (u_strcmp(ubuf, formattedHmm) != 0) {
2012 char bbuf[kBBufOverrideSepMax];
2013 u_strToUTF8(bbuf, kBBufOverrideSepMax, NULL, ubuf, ulen, &status);
2014 log_err("udat_format fails for UDAT_PATTERN \"%s\", expected 5:10, got %s\n", locale, bbuf);
2015 }
2016 udat_close(udfmt);
2017 }
2018
2019 status = U_ZERO_ERROR;
2020 udfmt = udat_open(UDAT_SHORT, UDAT_NONE, locale, zoneGMT, -1, NULL, 0, &status);
2021 if ( U_FAILURE(status) ) {
2022 log_err("udat_open(UDAT_SHORT, UDAT_NONE, \"%s\",...) fails, status %s\n", locale, u_errorName(status));
2023 } else {
2024 udat_applyPattern(udfmt, FALSE, patternHmm, -1);
2025 ulen = udat_format(udfmt, date2015Feb25, ubuf, kUBufOverrideSepMax, NULL, &status);
2026 if ( U_FAILURE(status) ) {
2027 log_err("udat_format fails for UDAT_SHORT \"%s\" + applyPattern, status %s\n", locale, u_errorName(status));
2028 } else if (u_strcmp(ubuf, formattedHmm) != 0) {
2029 char bbuf[kBBufOverrideSepMax];
2030 u_strToUTF8(bbuf, kBBufOverrideSepMax, NULL, ubuf, ulen, &status);
2031 log_err("udat_format fails for UDAT_SHORT \"%s\" + applyPattern, expected 5:10, got %s\n", locale, bbuf);
2032 }
2033 udat_close(udfmt);
2034 }
2035
2036 }
2037
2038 #define UDATE_SECOND (1000.0)
2039 #define UDATE_MINUTE (60.0*UDATE_SECOND)
2040 #define UDATE_HOUR (60.0*UDATE_MINUTE)
2041
2042 static const double dayOffsets[] = {
2043 0.0, /* 00:00:00 */
2044 UDATE_SECOND, /* 00:00:01 */
2045 UDATE_MINUTE, /* 00:01:00 */
2046 UDATE_HOUR, /* 01:00:00 */
2047 11.0*UDATE_HOUR + 59.0*UDATE_MINUTE, /* 11:59:00 */
2048 12.0*UDATE_HOUR, /* 12:00:00 */
2049 12.0*UDATE_HOUR + UDATE_SECOND, /* 12:00:01 */
2050 12.0*UDATE_HOUR + UDATE_MINUTE, /* 12:01:00 */
2051 13.0*UDATE_HOUR, /* 13:00:00 */
2052 23.0*UDATE_HOUR + 59.0*UDATE_MINUTE, /* 23:59:00 */
2053 };
2054 enum { kNumDayOffsets = UPRV_LENGTHOF(dayOffsets) };
2055
2056 static const char* ja12HrFmt_hm[kNumDayOffsets] = { /* aK:mm */
2057 "\\u5348\\u524D0:00", /* "午前0:00" */
2058 "\\u5348\\u524D0:00",
2059 "\\u5348\\u524D0:01",
2060 "\\u5348\\u524D1:00",
2061 "\\u5348\\u524D11:59",
2062 "\\u5348\\u5F8C0:00", /* "午後0:00" */
2063 "\\u5348\\u5F8C0:00",
2064 "\\u5348\\u5F8C0:01", /* "午後0:01" */
2065 "\\u5348\\u5F8C1:00",
2066 "\\u5348\\u5F8C11:59",
2067 };
2068
2069 static const char* ja12HrFmt_h[kNumDayOffsets] = { /* aK時 */
2070 "\\u5348\\u524D0\\u6642", /* "午前0時" */
2071 "\\u5348\\u524D0\\u6642",
2072 "\\u5348\\u524D0\\u6642",
2073 "\\u5348\\u524D1\\u6642",
2074 "\\u5348\\u524D11\\u6642",
2075 "\\u5348\\u5F8C0\\u6642", /* "午後0時" */
2076 "\\u5348\\u5F8C0\\u6642",
2077 "\\u5348\\u5F8C0\\u6642", /* "午後0時" */
2078 "\\u5348\\u5F8C1\\u6642",
2079 "\\u5348\\u5F8C11\\u6642",
2080 };
2081 typedef struct {
2082 const char* locale;
2083 const char* skeleton;
2084 const char ** expected;
2085 } Test12HrFmtItem;
2086
2087 static const Test12HrFmtItem test12HrFmtItems[] = {
2088 { "ja", "hm", ja12HrFmt_hm },
2089 { "ja", "h", ja12HrFmt_h },
2090 { NULL, NULL, NULL } /* terminator */
2091 };
2092
2093 enum { kUBufMax = 128, };
2094 static void Test12HrFormats(void) {
2095 const Test12HrFmtItem* itemPtr;
2096 for (itemPtr = test12HrFmtItems; itemPtr->locale != NULL; itemPtr++) {
2097 UErrorCode status = U_ZERO_ERROR;
2098 UCalendar* ucal = ucal_open(NULL, 0, itemPtr->locale, UCAL_DEFAULT, &status);
2099 if ( U_FAILURE(status) ) {
2100 log_data_err("ucal_open fails for locale %s: status %s (Are you missing data?)\n", itemPtr->locale, u_errorName(status));
2101 } else {
2102 ucal_clear(ucal);
2103 ucal_setDateTime(ucal, 2016, UCAL_JANUARY, 1, 0, 0, 0, &status);
2104 UDate baseDate = ucal_getMillis(ucal, &status);
2105 if ( U_FAILURE(status) ) {
2106 log_err("ucal_setDateTime or ucal_getMillis fails for locale %s: status %s\n", itemPtr->locale, u_errorName(status));
2107 } else {
2108 UDateTimePatternGenerator* udatpg = udatpg_open(itemPtr->locale, &status);
2109 if ( U_FAILURE(status) ) {
2110 log_data_err("udatpg_open fails for locale %s: status %s (Are you missing data?)\n", itemPtr->locale, u_errorName(status));
2111 } else {
2112 UChar ubuf1[kUbufMax], ubuf2[kUbufMax];
2113 int32_t ulen1 = u_unescape(itemPtr->skeleton, ubuf1, kUbufMax);
2114 int32_t ulen2 = udatpg_getBestPattern(udatpg, ubuf1, ulen1, ubuf2, kUbufMax, &status);
2115 if ( U_FAILURE(status) ) {
2116 log_err("udatpg_getBestPattern fails for locale %s, skeleton %s: status %s\n",
2117 itemPtr->locale, itemPtr->skeleton, u_errorName(status));
2118 } else {
2119 UDateFormat* udat = udat_open(UDAT_PATTERN, UDAT_PATTERN, itemPtr->locale, NULL, 0, ubuf2, ulen2, &status);
2120 if ( U_FAILURE(status) ) {
2121 log_data_err("udat_open fails for locale %s, skeleton %s: status %s (Are you missing data?)\n",
2122 itemPtr->locale, itemPtr->skeleton, u_errorName(status));
2123 } else {
2124 int32_t iDayOffset;
2125 for (iDayOffset = 0; iDayOffset < kNumDayOffsets; iDayOffset++) {
2126 status = U_ZERO_ERROR;
2127 ulen1 = udat_format(udat, baseDate + dayOffsets[iDayOffset], ubuf1, kUbufMax, NULL, &status);
2128 if ( U_FAILURE(status) ) {
2129 log_err("udat_format fails for locale %s, skeleton %s, iDayOffset %d: status %s\n",
2130 itemPtr->locale, itemPtr->skeleton, iDayOffset, u_errorName(status));
2131 } else {
2132 ulen2 = u_unescape(itemPtr->expected[iDayOffset], ubuf2, kUbufMax);
2133 if (ulen1 != ulen2 || u_strncmp(ubuf1, ubuf2, ulen2) != 0) {
2134 char bbuf1[kBbufMax], bbuf2[kBbufMax];
2135 u_austrncpy(bbuf1, ubuf1, ulen1);
2136 u_austrncpy(bbuf2, ubuf2, ulen2);
2137 log_err("udat_format fails for locale %s, skeleton %s, iDayOffset %d:\n expect %s\n get %s\n",
2138 itemPtr->locale, itemPtr->skeleton, iDayOffset, bbuf2, bbuf1);
2139 }
2140 }
2141
2142 }
2143 udat_close(udat);
2144 }
2145 }
2146 udatpg_close(udatpg);
2147 }
2148 }
2149 ucal_close(ucal);
2150 }
2151 }
2152 }
2153
2154 /* *** */
2155
2156 typedef struct {
2157 const char* locale;
2158 UATimeUnitTimePattern patType;
2159 const char* expect; /* universal char subset + escaped Unicode chars */
2160 } TimePatternItem;
2161 static const TimePatternItem timePatternItems[] = {
2162 { "en", UATIMEUNITTIMEPAT_HM, "h:mm" },
2163 { "en", UATIMEUNITTIMEPAT_HMS, "h:mm:ss" },
2164 { "en", UATIMEUNITTIMEPAT_MS, "m:ss" },
2165 { "da", UATIMEUNITTIMEPAT_HM, "h.mm" },
2166 { "da", UATIMEUNITTIMEPAT_HMS, "h.mm.ss" },
2167 { "da", UATIMEUNITTIMEPAT_MS, "m.ss" },
2168 { NULL, 0, NULL }
2169 };
2170
2171 typedef struct {
2172 const char* locale;
2173 UATimeUnitStyle width;
2174 UATimeUnitListPattern patType;
2175 const char* expect; /* universal char subset + escaped Unicode chars */
2176 } ListPatternItem;
2177 static const ListPatternItem listPatternItems[] = {
2178 { "en", UATIMEUNITSTYLE_FULL, UATIMEUNITLISTPAT_TWO_ONLY, "{0}, {1}" },
2179 { "en", UATIMEUNITSTYLE_FULL, UATIMEUNITLISTPAT_END_PIECE, "{0}, {1}" },
2180 { "en", UATIMEUNITSTYLE_FULL, UATIMEUNITLISTPAT_MIDDLE_PIECE, "{0}, {1}" },
2181 { "en", UATIMEUNITSTYLE_FULL, UATIMEUNITLISTPAT_START_PIECE, "{0}, {1}" },
2182 { "en", UATIMEUNITSTYLE_NARROW, UATIMEUNITLISTPAT_TWO_ONLY, "{0} {1}" },
2183 { "en", UATIMEUNITSTYLE_NARROW, UATIMEUNITLISTPAT_END_PIECE, "{0} {1}" },
2184 { "en", UATIMEUNITSTYLE_NARROW, UATIMEUNITLISTPAT_MIDDLE_PIECE, "{0} {1}" },
2185 { "en", UATIMEUNITSTYLE_NARROW, UATIMEUNITLISTPAT_START_PIECE, "{0} {1}" },
2186 { "en", UATIMEUNITSTYLE_SHORTER, UATIMEUNITLISTPAT_TWO_ONLY, "{0} {1}" },
2187 { "fr", UATIMEUNITSTYLE_FULL, UATIMEUNITLISTPAT_TWO_ONLY, "{0} et {1}" },
2188 { "fr", UATIMEUNITSTYLE_FULL, UATIMEUNITLISTPAT_END_PIECE, "{0} et {1}" },
2189 { "fr", UATIMEUNITSTYLE_FULL, UATIMEUNITLISTPAT_MIDDLE_PIECE, "{0}, {1}" },
2190 { "fr", UATIMEUNITSTYLE_FULL, UATIMEUNITLISTPAT_START_PIECE, "{0}, {1}" },
2191 { "fr", UATIMEUNITSTYLE_NARROW, UATIMEUNITLISTPAT_TWO_ONLY, "{0} {1}" },
2192 { "fr", UATIMEUNITSTYLE_NARROW, UATIMEUNITLISTPAT_END_PIECE, "{0} {1}" },
2193 { "fr", UATIMEUNITSTYLE_NARROW, UATIMEUNITLISTPAT_MIDDLE_PIECE, "{0} {1}" },
2194 { "fr", UATIMEUNITSTYLE_NARROW, UATIMEUNITLISTPAT_START_PIECE, "{0} {1}" },
2195 { "fr", UATIMEUNITSTYLE_SHORTER, UATIMEUNITLISTPAT_TWO_ONLY, "{0} {1}" },
2196 { NULL, 0, 0, NULL }
2197 };
2198
2199 enum {kUBufTimeUnitLen = 128, kBBufTimeUnitLen = 256 };
2200
2201 static void TestTimeUnitFormat(void) { /* Apple-specific */
2202 const TimePatternItem* timePatItemPtr;
2203 const ListPatternItem* listPatItemPtr;
2204 UChar uActual[kUBufTimeUnitLen];
2205 UChar uExpect[kUBufTimeUnitLen];
2206
2207 for (timePatItemPtr = timePatternItems; timePatItemPtr->locale != NULL; timePatItemPtr++) {
2208 UErrorCode status = U_ZERO_ERROR;
2209 int32_t ulenActual = uatmufmt_getTimePattern(timePatItemPtr->locale, timePatItemPtr->patType, uActual, kUBufTimeUnitLen, &status);
2210 if ( U_FAILURE(status) ) {
2211 log_err("uatmufmt_getTimePattern for locale %s, patType %d: status %s\n", timePatItemPtr->locale, (int)timePatItemPtr->patType, u_errorName(status));
2212 } else {
2213 int32_t ulenExpect = u_unescape(timePatItemPtr->expect, uExpect, kUBufTimeUnitLen);
2214 if (ulenActual != ulenExpect || u_strncmp(uActual, uExpect, ulenExpect) != 0) {
2215 char bActual[kBBufTimeUnitLen];
2216 u_strToUTF8(bActual, kBBufTimeUnitLen, NULL, uActual, ulenActual, &status);
2217 log_err("uatmufmt_getTimePattern for locale %s, patType %d: unexpected result %s\n", timePatItemPtr->locale, (int)timePatItemPtr->patType, bActual);
2218 }
2219 }
2220 }
2221
2222 for (listPatItemPtr = listPatternItems; listPatItemPtr->locale != NULL; listPatItemPtr++) {
2223 UErrorCode status = U_ZERO_ERROR;
2224 int32_t ulenActual = uatmufmt_getListPattern(listPatItemPtr->locale, listPatItemPtr->width, listPatItemPtr->patType, uActual, kUBufTimeUnitLen, &status);
2225 if ( U_FAILURE(status) ) {
2226 log_err("uatmufmt_getListPattern for locale %s, width %d, patType %d: status %s\n", listPatItemPtr->locale, (int)listPatItemPtr->width, (int)listPatItemPtr->patType, u_errorName(status));
2227 } else {
2228 int32_t ulenExpect = u_unescape(listPatItemPtr->expect, uExpect, kUBufTimeUnitLen);
2229 if (ulenActual != ulenExpect || u_strncmp(uActual, uExpect, ulenExpect) != 0) {
2230 char bActual[kBBufTimeUnitLen];
2231 u_strToUTF8(bActual, kBBufTimeUnitLen, NULL, uActual, ulenActual, &status);
2232 log_err("uatmufmt_getListPattern for locale %s, width %d, patType %d: unexpected result %s\n", listPatItemPtr->locale, (int)listPatItemPtr->width, (int)listPatItemPtr->patType, bActual);
2233 }
2234 }
2235 }
2236
2237 }
2238
2239 typedef enum RemapTesttype {
2240 REMAP_TESTTYPE_FULL = UDAT_FULL, // 0
2241 REMAP_TESTTYPE_LONG = UDAT_LONG, // 1
2242 REMAP_TESTTYPE_MEDIUM = UDAT_MEDIUM, // 2
2243 REMAP_TESTTYPE_SHORT = UDAT_SHORT, // 3
2244 REMAP_TESTTYPE_LONG_DF = UDAT_LONG + 4, // 5 long time, full date
2245 REMAP_TESTTYPE_SHORT_DS = UDAT_SHORT + 16, // 3 short time, short date
2246 REMAP_TESTTYPE_SKELETON = -1,
2247 REMAP_TESTTYPE_PATTERN = -2,
2248 } RemapTesttype;
2249
2250 typedef struct {
2251 const char * pattern;
2252 RemapTesttype testtype;
2253 uint32_t options;
2254 } RemapPatternTestItem;
2255
2256 static const RemapPatternTestItem remapPatItems[] = {
2257 { "full", REMAP_TESTTYPE_FULL, 0 },
2258 { "full", REMAP_TESTTYPE_FULL, UADATPG_FORCE_24_HOUR_CYCLE },
2259 { "full", REMAP_TESTTYPE_FULL, UADATPG_FORCE_12_HOUR_CYCLE },
2260 { "long", REMAP_TESTTYPE_LONG, 0 },
2261 { "long", REMAP_TESTTYPE_LONG, UADATPG_FORCE_24_HOUR_CYCLE },
2262 { "long", REMAP_TESTTYPE_LONG, UADATPG_FORCE_12_HOUR_CYCLE },
2263 { "medium", REMAP_TESTTYPE_MEDIUM, 0 },
2264 { "medium", REMAP_TESTTYPE_MEDIUM, UADATPG_FORCE_24_HOUR_CYCLE },
2265 { "medium", REMAP_TESTTYPE_MEDIUM, UADATPG_FORCE_12_HOUR_CYCLE },
2266 { "short", REMAP_TESTTYPE_SHORT, 0 },
2267 { "short", REMAP_TESTTYPE_SHORT, UADATPG_FORCE_24_HOUR_CYCLE },
2268 { "short", REMAP_TESTTYPE_SHORT, UADATPG_FORCE_12_HOUR_CYCLE },
2269 { "long_df", REMAP_TESTTYPE_LONG_DF, 0 },
2270 { "long_df", REMAP_TESTTYPE_LONG_DF, UADATPG_FORCE_24_HOUR_CYCLE },
2271 { "long_df", REMAP_TESTTYPE_LONG_DF, UADATPG_FORCE_12_HOUR_CYCLE },
2272 { "short_ds", REMAP_TESTTYPE_SHORT_DS, 0 },
2273 { "short_ds", REMAP_TESTTYPE_SHORT_DS, UADATPG_FORCE_24_HOUR_CYCLE },
2274 { "short_ds", REMAP_TESTTYPE_SHORT_DS, UADATPG_FORCE_12_HOUR_CYCLE },
2275
2276 { "jmmss", REMAP_TESTTYPE_SKELETON, 0 },
2277 { "jmmss", REMAP_TESTTYPE_SKELETON, UADATPG_FORCE_24_HOUR_CYCLE },
2278 { "jmmss", REMAP_TESTTYPE_SKELETON, UADATPG_FORCE_12_HOUR_CYCLE },
2279 { "jjmmss", REMAP_TESTTYPE_SKELETON, 0 },
2280 { "jjmmss", REMAP_TESTTYPE_SKELETON, UADATPG_FORCE_24_HOUR_CYCLE },
2281 { "jjmmss", REMAP_TESTTYPE_SKELETON, UADATPG_FORCE_24_HOUR_CYCLE | UDATPG_MATCH_HOUR_FIELD_LENGTH },
2282 { "jjmmss", REMAP_TESTTYPE_SKELETON, UADATPG_FORCE_12_HOUR_CYCLE },
2283 { "jjmmss", REMAP_TESTTYPE_SKELETON, UADATPG_FORCE_12_HOUR_CYCLE | UDATPG_MATCH_HOUR_FIELD_LENGTH },
2284 { "Jmm", REMAP_TESTTYPE_SKELETON, 0 },
2285 { "Jmm", REMAP_TESTTYPE_SKELETON, UADATPG_FORCE_24_HOUR_CYCLE },
2286 { "Jmm", REMAP_TESTTYPE_SKELETON, UADATPG_FORCE_12_HOUR_CYCLE },
2287 { "jmsv", REMAP_TESTTYPE_SKELETON, 0 },
2288 { "jmsv", REMAP_TESTTYPE_SKELETON, UADATPG_FORCE_24_HOUR_CYCLE },
2289 { "jmsv", REMAP_TESTTYPE_SKELETON, UADATPG_FORCE_12_HOUR_CYCLE },
2290 { "jmsz", REMAP_TESTTYPE_SKELETON, 0 },
2291 { "jmsz", REMAP_TESTTYPE_SKELETON, UADATPG_FORCE_24_HOUR_CYCLE },
2292 { "jmsz", REMAP_TESTTYPE_SKELETON, UADATPG_FORCE_12_HOUR_CYCLE },
2293
2294 { "h:mm:ss a", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_12_HOUR_CYCLE }, // 12=hour patterns
2295 { "h:mm:ss a", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_24_HOUR_CYCLE },
2296 { "a'xx'h:mm:ss d MMM y", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_12_HOUR_CYCLE },
2297 { "a'xx'h:mm:ss d MMM y", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_24_HOUR_CYCLE },
2298 { "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_12_HOUR_CYCLE },
2299 { "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_24_HOUR_CYCLE },
2300 { "EEE, d MMM y 'aha' a'xx'h:mm:ss", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_12_HOUR_CYCLE },
2301 { "EEE, d MMM y 'aha' a'xx'h:mm:ss", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_24_HOUR_CYCLE },
2302 { "yyMMddhhmmss", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_12_HOUR_CYCLE },
2303 { "yyMMddhhmmss", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_24_HOUR_CYCLE },
2304
2305 { "H:mm:ss", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_12_HOUR_CYCLE }, // 24=hour patterns
2306 { "H:mm:ss", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_24_HOUR_CYCLE },
2307 { "H:mm:ss d MMM y", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_12_HOUR_CYCLE },
2308 { "H:mm:ss d MMM y", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_24_HOUR_CYCLE },
2309 { "EEE, d MMM y 'aha' H:mm:ss 'hrs'", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_12_HOUR_CYCLE },
2310 { "EEE, d MMM y 'aha' H:mm:ss 'hrs'", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_24_HOUR_CYCLE },
2311 { "EEE, d MMM y 'aha' H'h'mm'm'ss", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_12_HOUR_CYCLE },
2312 { "EEE, d MMM y 'aha' H'h'mm'm'ss", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_24_HOUR_CYCLE },
2313 { NULL, (RemapTesttype)0, 0 }
2314 };
2315
2316 static const char * remapResults_root[] = {
2317 "HH:mm:ss zzzz", // full
2318 "HH:mm:ss zzzz", // force24
2319 "h:mm:ss a zzzz", // force12
2320 "HH:mm:ss z", // long
2321 "HH:mm:ss z", // force24
2322 "h:mm:ss a z", // force12
2323 "HH:mm:ss", // medium
2324 "HH:mm:ss", // force24
2325 "h:mm:ss a", // force12
2326 "HH:mm", // short
2327 "HH:mm", // force24
2328 "h:mm a", // force12
2329 "y MMMM d, EEEE HH:mm:ss z", // long_df
2330 "y MMMM d, EEEE HH:mm:ss z", // force24
2331 "y MMMM d, EEEE h:mm:ss a z", // force12
2332 "y-MM-dd HH:mm", // short_ds
2333 "y-MM-dd HH:mm", // force24
2334 "y-MM-dd h:mm a", // force12
2335
2336 "HH:mm:ss", // jmmss
2337 "HH:mm:ss", // force24
2338 "h:mm:ss a", // force12
2339 "HH:mm:ss", // jjmmss
2340 "HH:mm:ss", // force24
2341 "HH:mm:ss", // force24 | match hour field length
2342 "h:mm:ss a", // force12
2343 "hh:mm:ss a", // force12 | match hour field length
2344 "HH:mm", // Jmm
2345 "HH:mm", // force24
2346 "hh:mm", // force12
2347 "HH:mm:ss v", // jmsv
2348 "HH:mm:ss v", // force24
2349 "h:mm:ss a v", // force12
2350 "HH:mm:ss z", // jmsz
2351 "HH:mm:ss z", // force24
2352 "h:mm:ss a z", // force12
2353
2354 "h:mm:ss a", // "h:mm:ss"
2355 "HH:mm:ss", //
2356 "a'xx'h:mm:ss d MMM y", // "a'xx'h:mm:ss d MMM y"
2357 "HH:mm:ss d MMM y", //
2358 "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", // "EEE, d MMM y 'aha' h:mm:ss a 'hrs'"
2359 "EEE, d MMM y 'aha' HH:mm:ss 'hrs'", //
2360 "EEE, d MMM y 'aha' a'xx'h:mm:ss", // "EEE, d MMM y 'aha' a'xx'h:mm:ss"
2361 "EEE, d MMM y 'aha' HH:mm:ss", //
2362 "yyMMddhhmmss", // "yyMMddhhmmss"
2363 "yyMMddHHmmss", //
2364
2365 "h:mm:ss a", // "H:mm:ss"
2366 "H:mm:ss", //
2367 "h:mm:ss a d MMM y", // "H:mm:ss d MMM y"
2368 "H:mm:ss d MMM y", //
2369 "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", // "EEE, d MMM y 'aha' H:mm:ss 'hrs'"
2370 "EEE, d MMM y 'aha' H:mm:ss 'hrs'", //
2371 "EEE, d MMM y 'aha' h'h'mm'm'ss a", // "EEE, d MMM y 'aha' H'h'mm'm'ss"
2372 "EEE, d MMM y 'aha' H'h'mm'm'ss", //
2373 NULL
2374 };
2375
2376 static const char * remapResults_en[] = {
2377 "h:mm:ss a zzzz", // full
2378 "HH:mm:ss zzzz", // force24
2379 "h:mm:ss a zzzz", // force12
2380 "h:mm:ss a z", // long
2381 "HH:mm:ss z", // force24
2382 "h:mm:ss a z", // force12
2383 "h:mm:ss a", // medium
2384 "HH:mm:ss", // force24
2385 "h:mm:ss a", // force12
2386 "h:mm a", // short
2387 "HH:mm", // force24
2388 "h:mm a", // force12
2389 "EEEE, MMMM d, y 'at' h:mm:ss a z", // long_df
2390 "EEEE, MMMM d, y 'at' HH:mm:ss z", // force24
2391 "EEEE, MMMM d, y 'at' h:mm:ss a z", // force12
2392 "M/d/yy, h:mm a", // short_ds
2393 "M/d/yy, HH:mm", // force24
2394 "M/d/yy, h:mm a", // force12
2395
2396 "h:mm:ss a", // jmmss
2397 "HH:mm:ss", // force24
2398 "h:mm:ss a", // force12
2399 "h:mm:ss a", // jjmmss
2400 "HH:mm:ss", // force24
2401 "HH:mm:ss", // force24 | match hour field length
2402 "h:mm:ss a", // force12
2403 "hh:mm:ss a", // force12 | match hour field length
2404 "hh:mm", // Jmm
2405 "HH:mm", // force24
2406 "hh:mm", // force12
2407 "h:mm:ss a v", // jmsv
2408 "HH:mm:ss v", // force24
2409 "h:mm:ss a v", // force12
2410 "h:mm:ss a z", // jmsz
2411 "HH:mm:ss z", // force24
2412 "h:mm:ss a z", // force12
2413
2414 "h:mm:ss a", // "h:mm:ss"
2415 "HH:mm:ss", //
2416 "a'xx'h:mm:ss d MMM y", // "a'xx'h:mm:ss d MMM y"
2417 "HH:mm:ss d MMM y", //
2418 "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", // "EEE, d MMM y 'aha' h:mm:ss a 'hrs'"
2419 "EEE, d MMM y 'aha' HH:mm:ss 'hrs'", //
2420 "EEE, d MMM y 'aha' a'xx'h:mm:ss", // "EEE, d MMM y 'aha' a'xx'h:mm:ss"
2421 "EEE, d MMM y 'aha' HH:mm:ss", //
2422 "yyMMddhhmmss", // "yyMMddhhmmss"
2423 "yyMMddHHmmss", //
2424
2425 "h:mm:ss a", // "H:mm:ss"
2426 "H:mm:ss", //
2427 "h:mm:ss a d MMM y", // "H:mm:ss d MMM y"
2428 "H:mm:ss d MMM y", //
2429 "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", // "EEE, d MMM y 'aha' H:mm:ss 'hrs'"
2430 "EEE, d MMM y 'aha' H:mm:ss 'hrs'", //
2431 "EEE, d MMM y 'aha' h'h'mm'm'ss a", // "EEE, d MMM y 'aha' H'h'mm'm'ss"
2432 "EEE, d MMM y 'aha' H'h'mm'm'ss", //
2433 NULL
2434 };
2435
2436 static const char * remapResults_ja[] = {
2437 "H\\u6642mm\\u5206ss\\u79D2 zzzz", // full
2438 "H\\u6642mm\\u5206ss\\u79D2 zzzz", // force24
2439 "aK:mm:ss zzzz", // force12
2440 "H:mm:ss z", // long
2441 "H:mm:ss z", // force24
2442 "aK:mm:ss z", // force12
2443 "H:mm:ss", // medium
2444 "H:mm:ss", // force24
2445 "aK:mm:ss", // force12
2446 "H:mm", // short
2447 "H:mm", // force24
2448 "aK:mm", // force12
2449 "y\\u5E74M\\u6708d\\u65E5 EEEE H:mm:ss z", // long_df
2450 "y\\u5E74M\\u6708d\\u65E5 EEEE H:mm:ss z", // force24
2451 "y\\u5E74M\\u6708d\\u65E5 EEEE aK:mm:ss z", // force12
2452 "y/MM/dd H:mm", // short_ds
2453 "y/MM/dd H:mm", // force24
2454 "y/MM/dd aK:mm", // force12
2455
2456 "H:mm:ss", // jmmss
2457 "H:mm:ss", // force24
2458 "aK:mm:ss", // force12
2459 "H:mm:ss", // jjmmss
2460 "H:mm:ss", // force24
2461 "HH:mm:ss", // force24 | match hour field length
2462 "aK:mm:ss", // force12
2463 "aKK:mm:ss", // force12 | match hour field length
2464 "H:mm", // Jmm
2465 "H:mm", // force24
2466 "h:mm", // force12
2467 "H:mm:ss v", // jmsv
2468 "H:mm:ss v", // force24
2469 "aK:mm:ss v", // force12
2470 "H:mm:ss z", // jmsz
2471 "H:mm:ss z", // force24
2472 "aK:mm:ss z", // force12
2473
2474 "h:mm:ss a", // "h:mm:ss"
2475 "H:mm:ss", //
2476 "a'xx'h:mm:ss d MMM y", // "a'xx'h:mm:ss d MMM y"
2477 "H:mm:ss d MMM y", //
2478 "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", // "EEE, d MMM y 'aha' h:mm:ss a 'hrs'"
2479 "EEE, d MMM y 'aha' H:mm:ss 'hrs'", //
2480 "EEE, d MMM y 'aha' a'xx'h:mm:ss", // "EEE, d MMM y 'aha' a'xx'h:mm:ss"
2481 "EEE, d MMM y 'aha' H:mm:ss", //
2482 "yyMMddhhmmss", // "yyMMddhhmmss"
2483 "yyMMddHHmmss", //
2484
2485 "aK:mm:ss", // "H:mm:ss"
2486 "H:mm:ss", //
2487 "aK:mm:ss d MMM y", // "H:mm:ss d MMM y"
2488 "H:mm:ss d MMM y", //
2489 "EEE, d MMM y 'aha' aK:mm:ss 'hrs'", // "EEE, d MMM y 'aha' H:mm:ss 'hrs'"
2490 "EEE, d MMM y 'aha' H:mm:ss 'hrs'", //
2491 "EEE, d MMM y 'aha' aK'h'mm'm'ss", // "EEE, d MMM y 'aha' H'h'mm'm'ss"
2492 "EEE, d MMM y 'aha' H'h'mm'm'ss", //
2493 NULL
2494 };
2495
2496 static const char * remapResults_ko[] = {
2497 "a h\\uC2DC m\\uBD84 s\\uCD08 zzzz", // full
2498 "H\\uC2DC m\\uBD84 s\\uCD08 zzzz", // force24
2499 "a h\\uC2DC m\\uBD84 s\\uCD08 zzzz", // force12
2500 "a h\\uC2DC m\\uBD84 s\\uCD08 z", // long
2501 "H\\uC2DC m\\uBD84 s\\uCD08 z", // force24
2502 "a h\\uC2DC m\\uBD84 s\\uCD08 z", // force12
2503 "a h:mm:ss", // medium
2504 "HH:mm:ss", // force24
2505 "a h:mm:ss", // force12
2506 "a h:mm", // short
2507 "HH:mm", // force24
2508 "a h:mm", // force12
2509 "y\\uB144 M\\uC6D4 d\\uC77C EEEE a h\\uC2DC m\\uBD84 s\\uCD08 z", // long_df
2510 "y\\uB144 M\\uC6D4 d\\uC77C EEEE H\\uC2DC m\\uBD84 s\\uCD08 z", // force24
2511 "y\\uB144 M\\uC6D4 d\\uC77C EEEE a h\\uC2DC m\\uBD84 s\\uCD08 z", // force12
2512 "y. M. d. a h:mm", // short_ds
2513 "y. M. d. HH:mm", // force24
2514 "y. M. d. a h:mm", // force12
2515
2516 "a h:mm:ss", // jmmss
2517 "HH:mm:ss", // force24
2518 "a h:mm:ss", // force12
2519 "a h:mm:ss", // jjmmss
2520 "HH:mm:ss", // force24
2521 "HH:mm:ss", // force24 | match hour field length
2522 "a h:mm:ss", // force12
2523 "a hh:mm:ss", // force12 | match hour field length
2524 "hh:mm", // Jmm
2525 "HH:mm", // force24
2526 "hh:mm", // force12
2527 "a h:mm:ss v", // jmsv
2528 "H\\uC2DC m\\uBD84 s\\uCD08 v", // force24
2529 "a h:mm:ss v", // force12
2530 "a h\\uC2DC m\\uBD84 s\\uCD08 z", // jmsz
2531 "H\\uC2DC m\\uBD84 s\\uCD08 z", // force24
2532 "a h\\uC2DC m\\uBD84 s\\uCD08 z", // force12
2533
2534 "h:mm:ss a", // "h:mm:ss"
2535 "HH:mm:ss", //
2536 "a'xx'h:mm:ss d MMM y", // "a'xx'h:mm:ss d MMM y"
2537 "HH:mm:ss d MMM y", //
2538 "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", // "EEE, d MMM y 'aha' h:mm:ss a 'hrs'"
2539 "EEE, d MMM y 'aha' HH:mm:ss 'hrs'", //
2540 "EEE, d MMM y 'aha' a'xx'h:mm:ss", // "EEE, d MMM y 'aha' a'xx'h:mm:ss"
2541 "EEE, d MMM y 'aha' HH:mm:ss", //
2542 "yyMMddhhmmss", // "yyMMddhhmmss"
2543 "yyMMddHHmmss", //
2544
2545 "a h:mm:ss", // "H:mm:ss"
2546 "H:mm:ss", //
2547 "a h:mm:ss d MMM y", // "H:mm:ss d MMM y"
2548 "H:mm:ss d MMM y", //
2549 "EEE, d MMM y 'aha' a h:mm:ss 'hrs'", // "EEE, d MMM y 'aha' H:mm:ss 'hrs'"
2550 "EEE, d MMM y 'aha' H:mm:ss 'hrs'", //
2551 "EEE, d MMM y 'aha' a h'h'mm'm'ss", // "EEE, d MMM y 'aha' H'h'mm'm'ss"
2552 "EEE, d MMM y 'aha' H'h'mm'm'ss", //
2553 NULL
2554 };
2555
2556 static const char * remapResults_th[] = {
2557 "H \\u0E19\\u0E32\\u0E2C\\u0E34\\u0E01\\u0E32 mm \\u0E19\\u0E32\\u0E17\\u0E35 ss \\u0E27\\u0E34\\u0E19\\u0E32\\u0E17\\u0E35 zzzz", // full
2558 "H \\u0E19\\u0E32\\u0E2C\\u0E34\\u0E01\\u0E32 mm \\u0E19\\u0E32\\u0E17\\u0E35 ss \\u0E27\\u0E34\\u0E19\\u0E32\\u0E17\\u0E35 zzzz", // force24
2559 "h:mm:ss a zzzz", // force12
2560 "H \\u0E19\\u0E32\\u0E2C\\u0E34\\u0E01\\u0E32 mm \\u0E19\\u0E32\\u0E17\\u0E35 ss \\u0E27\\u0E34\\u0E19\\u0E32\\u0E17\\u0E35 z", // long
2561 "H \\u0E19\\u0E32\\u0E2C\\u0E34\\u0E01\\u0E32 mm \\u0E19\\u0E32\\u0E17\\u0E35 ss \\u0E27\\u0E34\\u0E19\\u0E32\\u0E17\\u0E35 z", // force24
2562 "h:mm:ss a z", // force12
2563 "HH:mm:ss", // medium
2564 "HH:mm:ss", // force24
2565 "h:mm:ss a", // force12
2566 "HH:mm", // short
2567 "HH:mm", // force24
2568 "h:mm a", // force12
2569 "EEEE\\u0E17\\u0E35\\u0E48 d MMMM G y H \\u0E19\\u0E32\\u0E2C\\u0E34\\u0E01\\u0E32 mm \\u0E19\\u0E32\\u0E17\\u0E35 ss \\u0E27\\u0E34\\u0E19\\u0E32\\u0E17\\u0E35 z", // long_df
2570 "EEEE\\u0E17\\u0E35\\u0E48 d MMMM G y H \\u0E19\\u0E32\\u0E2C\\u0E34\\u0E01\\u0E32 mm \\u0E19\\u0E32\\u0E17\\u0E35 ss \\u0E27\\u0E34\\u0E19\\u0E32\\u0E17\\u0E35 z", // force24
2571 "EEEE\\u0E17\\u0E35\\u0E48 d MMMM G y h:mm:ss a z", // force12
2572 "d/M/yy HH:mm", // short_ds
2573 "d/M/yy HH:mm", // force24
2574 "d/M/yy h:mm a", // force12
2575
2576 "HH:mm:ss", // jmmss
2577 "HH:mm:ss", // force24
2578 "h:mm:ss a", // force12
2579 "HH:mm:ss", // jjmmss
2580 "HH:mm:ss", // force24
2581 "HH:mm:ss", // force24 | match hour field length
2582 "h:mm:ss a", // force12
2583 "hh:mm:ss a", // force12 | match hour field length
2584 "HH:mm", // Jmm
2585 "HH:mm", // force24
2586 "hh:mm", // force12
2587 "H \\u0E19\\u0E32\\u0E2C\\u0E34\\u0E01\\u0E32 mm \\u0E19\\u0E32\\u0E17\\u0E35 ss \\u0E27\\u0E34\\u0E19\\u0E32\\u0E17\\u0E35 v", // jmsv
2588 "H \\u0E19\\u0E32\\u0E2C\\u0E34\\u0E01\\u0E32 mm \\u0E19\\u0E32\\u0E17\\u0E35 ss \\u0E27\\u0E34\\u0E19\\u0E32\\u0E17\\u0E35 v", // force24
2589 "h:mm:ss a v", // force12
2590 "H \\u0E19\\u0E32\\u0E2C\\u0E34\\u0E01\\u0E32 mm \\u0E19\\u0E32\\u0E17\\u0E35 ss \\u0E27\\u0E34\\u0E19\\u0E32\\u0E17\\u0E35 z", // jmsz
2591 "H \\u0E19\\u0E32\\u0E2C\\u0E34\\u0E01\\u0E32 mm \\u0E19\\u0E32\\u0E17\\u0E35 ss \\u0E27\\u0E34\\u0E19\\u0E32\\u0E17\\u0E35 z", // force24
2592 "h:mm:ss a z", // force12
2593
2594 "h:mm:ss a", // "h:mm:ss"
2595 "HH:mm:ss", //
2596 "a'xx'h:mm:ss d MMM y", // "a'xx'h:mm:ss d MMM y"
2597 "HH:mm:ss d MMM y", //
2598 "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", // "EEE, d MMM y 'aha' h:mm:ss a 'hrs'"
2599 "EEE, d MMM y 'aha' HH:mm:ss 'hrs'", //
2600 "EEE, d MMM y 'aha' a'xx'h:mm:ss", // "EEE, d MMM y 'aha' a'xx'h:mm:ss"
2601 "EEE, d MMM y 'aha' HH:mm:ss", //
2602 "yyMMddhhmmss", // "yyMMddhhmmss"
2603 "yyMMddHHmmss", //
2604
2605 "h:mm:ss a", // "H:mm:ss"
2606 "H:mm:ss", //
2607 "h:mm:ss a d MMM y", // "H:mm:ss d MMM y"
2608 "H:mm:ss d MMM y", //
2609 "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", // "EEE, d MMM y 'aha' H:mm:ss 'hrs'"
2610 "EEE, d MMM y 'aha' H:mm:ss 'hrs'", //
2611 "EEE, d MMM y 'aha' h'h'mm'm'ss a", // "EEE, d MMM y 'aha' H'h'mm'm'ss"
2612 "EEE, d MMM y 'aha' H'h'mm'm'ss", //
2613 NULL
2614 };
2615
2616 static const char * remapResults_hi[] = {
2617 "a h:mm:ss zzzz", // full
2618 "HH:mm:ss zzzz", // force24
2619 "a h:mm:ss zzzz", // force12
2620 "a h:mm:ss z", // long
2621 "HH:mm:ss z", // force24
2622 "a h:mm:ss z", // force12
2623 "a h:mm:ss", // medium
2624 "HH:mm:ss", // force24
2625 "a h:mm:ss", // force12
2626 "a h:mm", // short
2627 "HH:mm", // force24
2628 "a h:mm", // force12
2629 "EEEE, d MMMM y, a h:mm:ss z", // long_df
2630 "EEEE, d MMMM y, HH:mm:ss z", // force24
2631 "EEEE, d MMMM y, a h:mm:ss z", // force12
2632 "d/M/yy, a h:mm", // short_ds
2633 "d/M/yy, HH:mm", // force24
2634 "d/M/yy, a h:mm", // force12
2635
2636 "a h:mm:ss", // jmmss
2637 "HH:mm:ss", // force24
2638 "a h:mm:ss", // force12
2639 "a h:mm:ss", // jjmmss
2640 "HH:mm:ss", // force24
2641 "HH:mm:ss", // force24 | match hour field length
2642 "a h:mm:ss", // force12
2643 "a hh:mm:ss", // force12 | match hour field length
2644 "hh:mm", // Jmm
2645 "HH:mm", // force24
2646 "hh:mm", // force12
2647 "a h:mm:ss v", // jmsv
2648 "HH:mm:ss v", // force24
2649 "a h:mm:ss v", // force12
2650 "a h:mm:ss z", // jmsz
2651 "HH:mm:ss z", // force24
2652 "a h:mm:ss z", // force12
2653
2654 "h:mm:ss a", // "h:mm:ss"
2655 "HH:mm:ss", //
2656 "a'xx'h:mm:ss d MMM y", // "a'xx'h:mm:ss d MMM y"
2657 "HH:mm:ss d MMM y", //
2658 "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", // "EEE, d MMM y 'aha' h:mm:ss a 'hrs'"
2659 "EEE, d MMM y 'aha' HH:mm:ss 'hrs'", //
2660 "EEE, d MMM y 'aha' a'xx'h:mm:ss", // "EEE, d MMM y 'aha' a'xx'h:mm:ss"
2661 "EEE, d MMM y 'aha' HH:mm:ss", //
2662 "yyMMddhhmmss", // "yyMMddhhmmss"
2663 "yyMMddHHmmss", //
2664
2665 "a h:mm:ss", // "H:mm:ss"
2666 "H:mm:ss", //
2667 "a h:mm:ss d MMM y", // "H:mm:ss d MMM y"
2668 "H:mm:ss d MMM y", //
2669 "EEE, d MMM y 'aha' a h:mm:ss 'hrs'", // "EEE, d MMM y 'aha' H:mm:ss 'hrs'"
2670 "EEE, d MMM y 'aha' H:mm:ss 'hrs'", //
2671 "EEE, d MMM y 'aha' a h'h'mm'm'ss", // "EEE, d MMM y 'aha' H'h'mm'm'ss"
2672 "EEE, d MMM y 'aha' H'h'mm'm'ss", //
2673 NULL
2674 };
2675
2676 static const char * remapResults_ar[] = {
2677 "h:mm:ss\\u00A0a zzzz", // full
2678 "HH:mm:ss zzzz", // force24
2679 "h:mm:ss\\u00A0a zzzz", // force12
2680 "h:mm:ss\\u00A0a z", // long
2681 "HH:mm:ss z", // force24
2682 "h:mm:ss\\u00A0a z", // force12
2683 "h:mm:ss\\u00A0a", // medium
2684 "HH:mm:ss", // force24
2685 "h:mm:ss\\u00A0a", // force12
2686 "h:mm\\u00A0a", // short
2687 "HH:mm", // force24
2688 "h:mm\\u00A0a", // force12
2689 "EEEE\\u060C d MMMM\\u060C y\\u060C h:mm:ss\\u00A0a z", // long_df
2690 "EEEE\\u060C d MMMM\\u060C y\\u060C HH:mm:ss z", // force24
2691 "EEEE\\u060C d MMMM\\u060C y\\u060C h:mm:ss\\u00A0a z", // force12
2692 "d\\u200F/M\\u200F/y\\u060C h:mm\\u00A0a", // short_ds
2693 "d\\u200F/M\\u200F/y\\u060C HH:mm", // force24
2694 "d\\u200F/M\\u200F/y\\u060C h:mm\\u00A0a", // force12
2695
2696 "h:mm:ss\\u00A0a", // jmmss
2697 "HH:mm:ss", // force24
2698 "h:mm:ss\\u00A0a", // force12
2699 "h:mm:ss\\u00A0a", // jjmmss
2700 "HH:mm:ss", // force24
2701 "HH:mm:ss", // force24 | match hour field length
2702 "h:mm:ss\\u00A0a", // force12
2703 "hh:mm:ss\\u00A0a", // force12 | match hour field length
2704 "hh:mm", // Jmm
2705 "HH:mm", // force24
2706 "hh:mm", // force12
2707 "h:mm:ss\\u00A0a v", // jmsv
2708 "HH:mm:ss v", // force24
2709 "h:mm:ss\\u00A0a v", // force12
2710 "h:mm:ss\\u00A0a z", // jmsz
2711 "HH:mm:ss z", // force24
2712 "h:mm:ss\\u00A0a z", // force12
2713
2714 "h:mm:ss a", // "h:mm:ss"
2715 "HH:mm:ss", //
2716 "a'xx'h:mm:ss d MMM y", // "a'xx'h:mm:ss d MMM y"
2717 "HH:mm:ss d MMM y", //
2718 "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", // "EEE, d MMM y 'aha' h:mm:ss a 'hrs'"
2719 "EEE, d MMM y 'aha' HH:mm:ss 'hrs'", //
2720 "EEE, d MMM y 'aha' a'xx'h:mm:ss", // "EEE, d MMM y 'aha' a'xx'h:mm:ss"
2721 "EEE, d MMM y 'aha' HH:mm:ss", //
2722 "yyMMddhhmmss", // "yyMMddhhmmss"
2723 "yyMMddHHmmss", //
2724
2725 "h:mm:ssa", // "H:mm:ss" (should there be \\u00A0 before a?)
2726 "H:mm:ss", //
2727 "h:mm:ssa d MMM y", // "H:mm:ss d MMM y" (should there be \\u00A0 before a?)
2728 "H:mm:ss d MMM y", //
2729 "EEE, d MMM y 'aha' h:mm:ssa 'hrs'", // "EEE, d MMM y 'aha' H:mm:ss 'hrs'" (should there be \\u00A0 before a?)
2730 "EEE, d MMM y 'aha' H:mm:ss 'hrs'", //
2731 "EEE, d MMM y 'aha' h'h'mm'm'ssa", // "EEE, d MMM y 'aha' H'h'mm'm'ss" (should there be \\u00A0 before a?)
2732 "EEE, d MMM y 'aha' H'h'mm'm'ss", //
2733 NULL
2734 };
2735
2736 typedef struct {
2737 const char * locale;
2738 const char ** resultsPtr;
2739 } RemapPatternLocaleResults;
2740
2741 static const RemapPatternLocaleResults remapLocResults[] = {
2742 { "root", remapResults_root },
2743 { "en", remapResults_en },
2744 { "ja", remapResults_ja },
2745 { "ko", remapResults_ko },
2746 { "th", remapResults_th },
2747 { "hi", remapResults_hi },
2748 { "ar", remapResults_ar },
2749 { NULL, NULL }
2750 };
2751
2752 enum { kUBufRemapMax = 64, kBBufRemapMax = 128 };
2753
2754 static void TestRemapPatternWithOpts(void) { /* Apple-specific */
2755 const RemapPatternLocaleResults * locResPtr;
2756 for (locResPtr = remapLocResults; locResPtr->locale != NULL; locResPtr++) {
2757 UErrorCode status = U_ZERO_ERROR;
2758 UDateTimePatternGenerator* dtpg = udatpg_open(locResPtr->locale, &status);
2759 if ( U_FAILURE(status) ) {
2760 log_data_err("udatpg_open fails for locale %s, status %s (Are you missing data?)\n", locResPtr->locale, u_errorName(status));
2761 } else {
2762 const RemapPatternTestItem * testItemPtr = remapPatItems;
2763 const char ** expResultsPtr = locResPtr->resultsPtr;
2764 for (; testItemPtr->pattern != NULL && *expResultsPtr != NULL; testItemPtr++, expResultsPtr++) {
2765 UChar uskel[kUBufRemapMax];
2766 UChar upatn[kUBufRemapMax];
2767 UChar uget[kUBufRemapMax];
2768 UChar uexp[kUBufRemapMax];
2769 int32_t uelen, ulen = 0;
2770
2771 status = U_ZERO_ERROR;
2772 if (testItemPtr->testtype >= 0) {
2773 UDateFormatStyle timeStyle = (UDateFormatStyle)((int32_t)testItemPtr->testtype & 0x03);
2774 UDateFormatStyle dateStyle = (UDateFormatStyle)((((int32_t)testItemPtr->testtype >> 2) & 0x07) - 1);
2775 UDateFormat* dfmt = udat_open(timeStyle, dateStyle, locResPtr->locale, NULL, 0, NULL, 0, &status);
2776 if ( U_FAILURE(status) ) {
2777 log_data_err("udat_open fails for locale %s, status %s (Are you missing data?)\n", locResPtr->locale, u_errorName(status));
2778 continue;
2779 } else {
2780 ulen = udat_toPattern(dfmt, FALSE, upatn, kUBufRemapMax, &status);
2781 udat_close(dfmt);
2782 if ( U_FAILURE(status) ) {
2783 log_err("udat_toPattern fails for locale %s, status %s\n", locResPtr->locale, u_errorName(status));
2784 continue;
2785 }
2786 }
2787 } else if (testItemPtr->testtype == REMAP_TESTTYPE_SKELETON) {
2788 u_strFromUTF8(uskel, kUBufRemapMax, &ulen, testItemPtr->pattern, -1, &status);
2789 ulen = udatpg_getBestPatternWithOptions(dtpg, uskel, ulen, (UDateTimePatternMatchOptions)testItemPtr->options, upatn, kUBufRemapMax, &status);
2790 if ( U_FAILURE(status) ) {
2791 log_err("udatpg_getBestPatternWithOptions fails for locale %s, skeleton \"%s\": status %s\n", locResPtr->locale, testItemPtr->pattern, u_errorName(status));
2792 continue;
2793 }
2794 } else {
2795 ulen = u_unescape(testItemPtr->pattern, upatn, kUBufRemapMax);
2796 }
2797 uelen = u_unescape(*expResultsPtr, uexp, kUBufRemapMax);
2798 ulen = uadatpg_remapPatternWithOptions(dtpg, upatn, ulen, (UDateTimePatternMatchOptions)testItemPtr->options, uget, kUBufRemapMax, &status);
2799 if ( U_FAILURE(status) ) {
2800 log_err("uadatpg_remapPatternWithOptions fails for locale %s pattern \"%s\" opts %08X: status %s\n",
2801 locResPtr->locale, testItemPtr->pattern, testItemPtr->options, u_errorName(status));
2802 } else if (uelen != ulen || u_strncmp(uget, uexp, ulen) != 0) {
2803 char bebuf[kBBufRemapMax];
2804 char bbuf[kBBufRemapMax];
2805 UErrorCode tempStatus = U_ZERO_ERROR;
2806 u_strToUTF8(bebuf, kBBufRemapMax, NULL, uexp, uelen, &tempStatus);
2807 u_strToUTF8(bbuf, kBBufRemapMax, NULL, uget, ulen, &tempStatus);
2808 log_err("uadatpg_remapPatternWithOptions for locale %s pattern \"%s\" opts %08X: expect \"%s\", get \"%s\"\n",
2809 locResPtr->locale, testItemPtr->pattern, testItemPtr->options, bebuf, bbuf);
2810 }
2811 }
2812 udatpg_close(dtpg);
2813 }
2814 }
2815 }
2816
2817 #endif /* #if !UCONFIG_NO_FORMATTING */