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