]> git.saurik.com Git - apple/icu.git/blame - icuSources/test/cintltst/cdattst.c
ICU-66108.tar.gz
[apple/icu.git] / icuSources / test / cintltst / cdattst.c
CommitLineData
f3c0d7a5
A
1// © 2016 and later: Unicode, Inc. and others.
2// License & terms of use: http://www.unicode.org/copyright.html
b75a7d8f 3/********************************************************************
2ca993e8
A
4 * COPYRIGHT:
5 * Copyright (c) 1997-2016, International Business Machines Corporation and
b75a7d8f
A
6 * others. All Rights Reserved.
7 ********************************************************************/
8/********************************************************************************
9*
10* File CDATTST.C
11*
12* Modification History:
2ca993e8 13* Name Description
b75a7d8f
A
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
340931cb 24#include "unicode/uchar.h"
b75a7d8f
A
25#include "unicode/uloc.h"
26#include "unicode/udat.h"
4388f060 27#include "unicode/udatpg.h"
b75a7d8f
A
28#include "unicode/ucal.h"
29#include "unicode/unum.h"
30#include "unicode/ustring.h"
b331163b 31#include "unicode/ufieldpositer.h"
b75a7d8f
A
32#include "cintltst.h"
33#include "cdattst.h"
34#include "cformtst.h"
35#include "cmemory.h"
4f1e1a09 36#if !U_PLATFORM_HAS_WIN32_API
b331163b 37#include "unicode/uatimeunitformat.h" /* Apple-specific */
4f1e1a09 38#endif
b75a7d8f 39
374ca955 40#include <math.h>
340931cb 41#include <stdio.h> // for sprintf
374ca955 42
3d1f044b
A
43#define ADD_ALLOC_TEST 0
44#define WRITE_HOUR_MISMATCH_ERRS 0
340931cb 45#define WRITE_COUNTRY_FALLBACK_RESULTS 0
3d1f044b
A
46
47#if ADD_ALLOC_TEST
48static void TestPerf(void);
49#endif
374ca955 50static void TestExtremeDates(void);
73c04bcf 51static void TestAllLocales(void);
46f4442e 52static void TestRelativeCrash(void);
4388f060 53static void TestContext(void);
51004dcb 54static void TestCalendarDateParse(void);
b331163b
A
55static void TestParseErrorReturnValue(void);
56static void TestFormatForFields(void);
1546d4af 57static void TestForceGannenNumbering(void);
2ca993e8 58static void TestStandardPatterns(void);
b331163b 59static void TestApplyPatnOverridesTimeSep(void);
2ca993e8 60static void Test12HrFormats(void);
340931cb 61static void Test12HrPatterns(void);
4f1e1a09 62#if !U_PLATFORM_HAS_WIN32_API
b331163b 63static void TestTimeUnitFormat(void); /* Apple-specific */
3d1f044b 64static void TestTimeUnitFormatWithNumStyle(void); /* Apple-specific */
4f1e1a09 65#endif
340931cb 66static void TestMapPatternCharToFields(void); /* Apple <rdar://problem/62136559> */
b331163b 67static void TestRemapPatternWithOpts(void); /* Apple-specific */
3d1f044b
A
68#if WRITE_HOUR_MISMATCH_ERRS
69static void WriteHourMismatchErrs(void); /* 52980140*/
70#endif
340931cb
A
71#if WRITE_COUNTRY_FALLBACK_RESULTS
72static void WriteCountryFallbackResults(void); /* Apple <rdar://problem/26911014> */
73#endif
74static void TestCountryFallback(void); /* Apple <rdar://problem/26911014> */
374ca955 75
b75a7d8f
A
76void addDateForTest(TestNode** root);
77
374ca955 78#define TESTCASE(x) addTest(root, &x, "tsformat/cdattst/" #x)
b75a7d8f
A
79
80void addDateForTest(TestNode** root)
81{
3d1f044b
A
82#if ADD_ALLOC_TEST
83 TESTCASE(TestPerf);
84#endif
374ca955 85 TESTCASE(TestDateFormat);
46f4442e 86 TESTCASE(TestRelativeDateFormat);
374ca955
A
87 TESTCASE(TestSymbols);
88 TESTCASE(TestDateFormatCalendar);
89 TESTCASE(TestExtremeDates);
73c04bcf 90 TESTCASE(TestAllLocales);
46f4442e 91 TESTCASE(TestRelativeCrash);
4388f060 92 TESTCASE(TestContext);
51004dcb 93 TESTCASE(TestCalendarDateParse);
b331163b
A
94 TESTCASE(TestOverrideNumberFormat);
95 TESTCASE(TestParseErrorReturnValue);
96 TESTCASE(TestFormatForFields);
1546d4af 97 TESTCASE(TestForceGannenNumbering);
2ca993e8 98 TESTCASE(TestStandardPatterns);
b331163b 99 TESTCASE(TestApplyPatnOverridesTimeSep);
2ca993e8 100 TESTCASE(Test12HrFormats);
340931cb 101 TESTCASE(Test12HrPatterns);
4f1e1a09 102#if !U_PLATFORM_HAS_WIN32_API
b331163b 103 TESTCASE(TestTimeUnitFormat); /* Apple-specific */
3d1f044b 104 TESTCASE(TestTimeUnitFormatWithNumStyle); /* Apple-specific */
4f1e1a09 105#endif
340931cb 106 TESTCASE(TestMapPatternCharToFields); /* Apple <rdar://problem/62136559> */
b331163b 107 TESTCASE(TestRemapPatternWithOpts); /* Apple-specific */
3d1f044b
A
108#if WRITE_HOUR_MISMATCH_ERRS
109 TESTCASE(WriteHourMismatchErrs); /* 52980140 */
110#endif
340931cb
A
111#if WRITE_COUNTRY_FALLBACK_RESULTS
112 TESTCASE(WriteCountryFallbackResults); /* Apple <rdar://problem/26911014> */
113#endif
114 TESTCASE(TestCountryFallback); /* Apple <rdar://problem/26911014> */
b75a7d8f 115}
340931cb 116
b75a7d8f
A
117/* Testing the DateFormat API */
118static void TestDateFormat()
119{
120 UDateFormat *def, *fr, *it, *de, *def1, *fr_pat;
121 UDateFormat *any;
122 UDateFormat *copy;
123 UErrorCode status = U_ZERO_ERROR;
124 UChar* result = NULL;
125 const UCalendar *cal;
126 const UNumberFormat *numformat1, *numformat2;
b331163b 127 UNumberFormat *adoptNF;
46f4442e 128 UChar temp[50];
b75a7d8f
A
129 int32_t numlocales;
130 UDate d1;
131 int i;
132 int32_t resultlength;
133 int32_t resultlengthneeded;
134 int32_t parsepos;
135 UDate d = 837039928046.0;
136 double num = -10456.37;
137 /*const char* str="yyyy.MM.dd G 'at' hh:mm:ss z";
138 const char t[]="2/3/76 2:50 AM";*/
139 /*Testing udat_open() to open a dateformat */
374ca955
A
140
141 ctest_setTimeZone(NULL, &status);
142
b75a7d8f
A
143 log_verbose("\nTesting udat_open() with various parameters\n");
144 fr = udat_open(UDAT_FULL, UDAT_DEFAULT, "fr_FR", NULL,0, NULL, 0,&status);
145 if(U_FAILURE(status))
146 {
2ca993e8 147 log_data_err("FAIL: error in creating the dateformat using full time style with french locale -> %s (Are you missing data?)\n",
b75a7d8f
A
148 myErrorName(status) );
149 return;
150 }
2ca993e8 151 /* this is supposed to open default date format, but later on it treats it like it is "en_US"
b75a7d8f
A
152 - very bad if you try to run the tests on machine where default locale is NOT "en_US" */
153 /* def = udat_open(UDAT_SHORT, UDAT_SHORT, NULL, NULL, 0, &status); */
154 def = udat_open(UDAT_SHORT, UDAT_SHORT, "en_US", NULL, 0,NULL, 0, &status);
155 if(U_FAILURE(status))
156 {
2ca993e8 157 log_err("FAIL: error in creating the dateformat using short date and time style\n %s\n",
b75a7d8f
A
158 myErrorName(status) );
159 return;
160 }
161 it = udat_open(UDAT_DEFAULT, UDAT_MEDIUM, "it_IT", NULL, 0, NULL, 0,&status);
162 if(U_FAILURE(status))
163 {
2ca993e8 164 log_err("FAIL: error in creating the dateformat using medium date style with italian locale\n %s\n",
b75a7d8f
A
165 myErrorName(status) );
166 return;
167 }
168 de = udat_open(UDAT_LONG, UDAT_LONG, "de_DE", NULL, 0, NULL, 0,&status);
169 if(U_FAILURE(status))
170 {
171 log_err("FAIL: error in creating the dateformat using long time and date styles with german locale\n %s\n",
172 myErrorName(status));
173 return;
174 }
175 /*creating a default dateformat */
176 def1 = udat_open(UDAT_SHORT, UDAT_SHORT, NULL, NULL, 0,NULL, 0, &status);
177 if(U_FAILURE(status))
178 {
2ca993e8 179 log_err("FAIL: error in creating the dateformat using short date and time style\n %s\n",
b75a7d8f
A
180 myErrorName(status) );
181 return;
182 }
183
184
2ca993e8 185 /*Testing udat_getAvailable() and udat_countAvailable()*/
b75a7d8f
A
186 log_verbose("\nTesting getAvailableLocales and countAvailable()\n");
187 numlocales=udat_countAvailable();
188 /* use something sensible w/o hardcoding the count */
189 if(numlocales < 0)
190 log_data_err("FAIL: error in countAvailable\n");
191 log_verbose("The number of locales for which date/time formatting patterns are available is %d\n", numlocales);
2ca993e8 192
b75a7d8f
A
193 for(i=0;i<numlocales;i++) {
194 UErrorCode subStatus = U_ZERO_ERROR;
195 log_verbose("Testing open of %s\n", udat_getAvailable(i));
73c04bcf 196 any = udat_open(UDAT_SHORT, UDAT_SHORT, udat_getAvailable(i), NULL ,0, NULL, 0, &subStatus);
b75a7d8f 197 if(U_FAILURE(subStatus)) {
73c04bcf 198 log_data_err("FAIL: date format %s (getAvailable(%d)) is not instantiable: %s\n", udat_getAvailable(i), i, u_errorName(subStatus));
b75a7d8f
A
199 }
200 udat_close(any);
201 }
202
203 /*Testing udat_clone()*/
204 log_verbose("\nTesting the udat_clone() function of date format\n");
205 copy=udat_clone(def, &status);
206 if(U_FAILURE(status)){
207 log_err("Error in creating the clone using udat_clone: %s\n", myErrorName(status) );
208 }
209 /*if(def != copy)
210 log_err("Error in udat_clone");*/ /*how should i check for equality???? */
2ca993e8 211
b75a7d8f
A
212 /*Testing udat_format()*/
213 log_verbose("\nTesting the udat_format() function of date format\n");
51004dcb 214 u_uastrcpy(temp, "7/10/96, 4:05 PM");
b75a7d8f
A
215 /*format using def */
216 resultlength=0;
217 resultlengthneeded=udat_format(def, d, NULL, resultlength, NULL, &status);
218 if(status==U_BUFFER_OVERFLOW_ERROR)
219 {
220 status=U_ZERO_ERROR;
221 resultlength=resultlengthneeded+1;
222 if(result != NULL) {
223 free(result);
224 result = NULL;
225 }
226 result=(UChar*)malloc(sizeof(UChar) * resultlength);
227 udat_format(def, d, result, resultlength, NULL, &status);
228 }
229 if(U_FAILURE(status) || !result)
230 {
231 log_err("FAIL: Error in formatting using udat_format(.....) %s\n", myErrorName(status) );
232 return;
233 }
234 else
235 log_verbose("PASS: formatting successful\n");
236 if(u_strcmp(result, temp)==0)
46f4442e 237 log_verbose("PASS: Date Format for US locale successful using udat_format()\n");
729e4ab9
A
238 else {
239 char xbuf[2048];
240 char gbuf[2048];
241 u_austrcpy(xbuf, temp);
242 u_austrcpy(gbuf, result);
243 log_err("FAIL: Date Format for US locale failed using udat_format() - expected %s got %s\n", xbuf, gbuf);
244 }
b75a7d8f 245 /*format using fr */
2ca993e8
A
246
247 u_unescape("10 juil. 1996 \\u00E0 16:05:28 heure d\\u2019\\u00E9t\\u00E9 du Pacifique", temp, 50);
b75a7d8f
A
248 if(result != NULL) {
249 free(result);
250 result = NULL;
251 }
252 result=myDateFormat(fr, d);
253 if(u_strcmp(result, temp)==0)
374ca955 254 log_verbose("PASS: Date Format for french locale successful using udat_format()\n");
b75a7d8f 255 else
46f4442e
A
256 log_data_err("FAIL: Date Format for french locale failed using udat_format().\n" );
257
374ca955 258 /*format using it */
b331163b 259 u_uastrcpy(temp, "10 lug 1996, 16:05:28");
2ca993e8
A
260
261 {
46f4442e
A
262 UChar *fmtted;
263 char g[100];
264 char x[100];
2ca993e8 265
46f4442e
A
266 fmtted = myDateFormat(it,d);
267 u_austrcpy(g, fmtted);
268 u_austrcpy(x, temp);
269 if(u_strcmp(fmtted, temp)==0) {
270 log_verbose("PASS: Date Format for italian locale successful uisng udat_format() - wanted %s, got %s\n", x, g);
271 } else {
272 log_data_err("FAIL: Date Format for italian locale failed using udat_format() - wanted %s, got %s\n", x, g);
273 }
274 }
2ca993e8 275
b75a7d8f
A
276 /*Testing parsing using udat_parse()*/
277 log_verbose("\nTesting parsing using udat_parse()\n");
51004dcb 278 u_uastrcpy(temp,"2/3/76, 2:50 AM");
b75a7d8f 279 parsepos=0;
374ca955 280 status=U_ZERO_ERROR;
2ca993e8 281
b75a7d8f
A
282 d1=udat_parse(def, temp, u_strlen(temp), &parsepos, &status);
283 if(U_FAILURE(status))
284 {
285 log_err("FAIL: Error in parsing using udat_parse(.....) %s\n", myErrorName(status) );
286 }
287 else
288 log_verbose("PASS: parsing succesful\n");
289 /*format it back and check for equality */
2ca993e8
A
290
291
b75a7d8f
A
292 if(u_strcmp(myDateFormat(def, d1),temp)!=0)
293 log_err("FAIL: error in parsing\n");
294
374ca955
A
295 /*Testing parsing using udat_parse()*/
296 log_verbose("\nTesting parsing using udat_parse()\n");
297 u_uastrcpy(temp,"2/Don't parse this part");
298 status=U_ZERO_ERROR;
2ca993e8 299
374ca955
A
300 d1=udat_parse(def, temp, u_strlen(temp), NULL, &status);
301 if(status != U_PARSE_ERROR)
302 {
303 log_err("FAIL: udat_parse(\"bad string\") passed when it should have failed\n");
304 }
305 else
306 log_verbose("PASS: parsing succesful\n");
2ca993e8
A
307
308
309
b75a7d8f
A
310 /*Testing udat_openPattern() */
311 status=U_ZERO_ERROR;
312 log_verbose("\nTesting the udat_openPattern with a specified pattern\n");
313 /*for french locale */
51004dcb 314 fr_pat=udat_open(UDAT_PATTERN, UDAT_PATTERN,"fr_FR",NULL,0,temp, u_strlen(temp), &status);
b75a7d8f
A
315 if(U_FAILURE(status))
316 {
2ca993e8 317 log_err("FAIL: Error in creating a date format using udat_openPattern \n %s\n",
b75a7d8f
A
318 myErrorName(status) );
319 }
320 else
321 log_verbose("PASS: creating dateformat using udat_openPattern() succesful\n");
322
2ca993e8 323
b75a7d8f
A
324 /*Testing applyPattern and toPattern */
325 log_verbose("\nTesting applyPattern and toPattern()\n");
326 udat_applyPattern(def1, FALSE, temp, u_strlen(temp));
327 log_verbose("Extracting the pattern\n");
328
329 resultlength=0;
330 resultlengthneeded=udat_toPattern(def1, FALSE, NULL, resultlength, &status);
331 if(status==U_BUFFER_OVERFLOW_ERROR)
332 {
333 status=U_ZERO_ERROR;
334 resultlength=resultlengthneeded + 1;
335 result=(UChar*)malloc(sizeof(UChar) * resultlength);
336 udat_toPattern(def1, FALSE, result, resultlength, &status);
337 }
338 if(U_FAILURE(status))
339 {
2ca993e8 340 log_err("FAIL: error in extracting the pattern from UNumberFormat\n %s\n",
b75a7d8f
A
341 myErrorName(status) );
342 }
343 if(u_strcmp(result, temp)!=0)
344 log_err("FAIL: Error in extracting the pattern\n");
345 else
346 log_verbose("PASS: applyPattern and toPattern work fine\n");
2ca993e8 347
b75a7d8f 348 if(result != NULL) {
2ca993e8 349 free(result);
b75a7d8f
A
350 result = NULL;
351 }
2ca993e8
A
352
353
b75a7d8f
A
354 /*Testing getter and setter functions*/
355 /*isLenient and setLenient()*/
356 log_verbose("\nTesting the isLenient and setLenient properties\n");
357 udat_setLenient(fr, udat_isLenient(it));
2ca993e8 358 if(udat_isLenient(fr) != udat_isLenient(it))
b75a7d8f
A
359 log_err("ERROR: setLenient() failed\n");
360 else
361 log_verbose("PASS: setLenient() successful\n");
362
363
364 /*Test get2DigitYearStart set2DigitYearStart */
365 log_verbose("\nTesting the get and set 2DigitYearStart properties\n");
366 d1= udat_get2DigitYearStart(fr_pat,&status);
367 if(U_FAILURE(status)) {
368 log_err("ERROR: udat_get2DigitYearStart failed %s\n", myErrorName(status) );
369 }
370 status = U_ZERO_ERROR;
371 udat_set2DigitYearStart(def1 ,d1, &status);
372 if(U_FAILURE(status)) {
373 log_err("ERROR: udat_set2DigitYearStart failed %s\n", myErrorName(status) );
374 }
375 if(udat_get2DigitYearStart(fr_pat, &status) != udat_get2DigitYearStart(def1, &status))
376 log_err("FAIL: error in set2DigitYearStart\n");
377 else
378 log_verbose("PASS: set2DigitYearStart successful\n");
379 /*try setting it to another value */
380 udat_set2DigitYearStart(de, 2000.0, &status);
381 if(U_FAILURE(status)){
382 log_verbose("ERROR: udat_set2DigitYearStart failed %s\n", myErrorName(status) );
383 }
384 if(udat_get2DigitYearStart(de, &status) != 2000)
385 log_err("FAIL: error in set2DigitYearStart\n");
386 else
387 log_verbose("PASS: set2DigitYearStart successful\n");
388
2ca993e8 389
b75a7d8f
A
390
391 /*Test getNumberFormat() and setNumberFormat() */
392 log_verbose("\nTesting the get and set NumberFormat properties of date format\n");
393 numformat1=udat_getNumberFormat(fr_pat);
394 udat_setNumberFormat(def1, numformat1);
395 numformat2=udat_getNumberFormat(def1);
396 if(u_strcmp(myNumformat(numformat1, num), myNumformat(numformat2, num)) !=0)
397 log_err("FAIL: error in setNumberFormat or getNumberFormat()\n");
398 else
399 log_verbose("PASS:setNumberFormat and getNumberFormat succesful\n");
2ca993e8 400
b331163b
A
401 /*Test getNumberFormat() and adoptNumberFormat() */
402 log_verbose("\nTesting the get and adopt NumberFormat properties of date format\n");
403 adoptNF= unum_open(UNUM_DEFAULT, NULL, 0, NULL, NULL, &status);
404 udat_adoptNumberFormat(def1, adoptNF);
405 numformat2=udat_getNumberFormat(def1);
406 if(u_strcmp(myNumformat(adoptNF, num), myNumformat(numformat2, num)) !=0)
407 log_err("FAIL: error in adoptNumberFormat or getNumberFormat()\n");
408 else
409 log_verbose("PASS:adoptNumberFormat and getNumberFormat succesful\n");
b75a7d8f
A
410
411 /*try setting the number format to another format */
412 numformat1=udat_getNumberFormat(def);
413 udat_setNumberFormat(def1, numformat1);
414 numformat2=udat_getNumberFormat(def1);
415 if(u_strcmp(myNumformat(numformat1, num), myNumformat(numformat2, num)) !=0)
416 log_err("FAIL: error in setNumberFormat or getNumberFormat()\n");
417 else
418 log_verbose("PASS: setNumberFormat and getNumberFormat succesful\n");
419
420
421
422 /*Test getCalendar and setCalendar*/
423 log_verbose("\nTesting the udat_getCalendar() and udat_setCalendar() properties\n");
424 cal=udat_getCalendar(fr_pat);
2ca993e8
A
425
426
b75a7d8f
A
427 udat_setCalendar(def1, cal);
428 if(!ucal_equivalentTo(udat_getCalendar(fr_pat), udat_getCalendar(def1)))
429 log_err("FAIL: Error in setting and getting the calendar\n");
430 else
431 log_verbose("PASS: getting and setting calendar successful\n");
2ca993e8 432
b75a7d8f
A
433 if(result!=NULL) {
434 free(result);
435 }
2ca993e8 436
b75a7d8f
A
437 /*Closing the UDateForamt */
438 udat_close(def);
439 udat_close(fr);
440 udat_close(it);
441 udat_close(de);
442 udat_close(def1);
443 udat_close(fr_pat);
444 udat_close(copy);
2ca993e8 445
374ca955 446 ctest_resetTimeZone();
b75a7d8f
A
447}
448
46f4442e
A
449/*
450Test combined relative date formatting (relative date + non-relative time).
451This is a bit tricky since we can't have static test data for comparison, the
452relative date formatting is relative to the time the tests are run. We generate
453the data for comparison dynamically. However, the tests could fail if they are
454run right at midnight Pacific time and the call to ucal_getNow() is before midnight
455while the calls to udat_format are after midnight or span midnight.
456*/
457static const UDate dayInterval = 24.0*60.0*60.0*1000.0;
458static const UChar trdfZone[] = { 0x0055, 0x0053, 0x002F, 0x0050, 0x0061, 0x0063, 0x0069, 0x0066, 0x0069, 0x0063, 0 }; /* US/Pacific */
459static const char trdfLocale[] = "en_US";
460static const UChar minutesPatn[] = { 0x006D, 0x006D, 0 }; /* "mm" */
461static const UChar monthLongPatn[] = { 0x004D, 0x004D, 0x004D, 0x004D, 0 }; /* "MMMM" */
462static const UChar monthMediumPatn[] = { 0x004D, 0x004D, 0x004D, 0 }; /* "MMM" */
463static const UChar monthShortPatn[] = { 0x004D, 0 }; /* "M" */
464static const UDateFormatStyle dateStylesList[] = { UDAT_FULL, UDAT_LONG, UDAT_MEDIUM, UDAT_SHORT, UDAT_NONE };
465static const UChar *monthPatnsList[] = { monthLongPatn, monthLongPatn, monthMediumPatn, monthShortPatn, NULL };
466static const UChar newTimePatn[] = { 0x0048, 0x0048, 0x002C, 0x006D, 0x006D, 0 }; /* "HH,mm" */
467static const UChar minutesStr[] = { 0x0034, 0x0039, 0 }; /* "49", minutes string to search for in output */
468enum { kDateOrTimeOutMax = 96, kDateAndTimeOutMax = 192 };
469
51004dcb
A
470static const UDate minutesTolerance = 2 * 60.0 * 1000.0;
471static const UDate daysTolerance = 2 * 24.0 * 60.0 * 60.0 * 1000.0;
472
46f4442e
A
473static void TestRelativeDateFormat()
474{
475 UDate today = 0.0;
476 const UDateFormatStyle * stylePtr;
477 const UChar ** monthPtnPtr;
478 UErrorCode status = U_ZERO_ERROR;
479 UCalendar * ucal = ucal_open(trdfZone, -1, trdfLocale, UCAL_GREGORIAN, &status);
480 if ( U_SUCCESS(status) ) {
481 int32_t year, month, day;
482 ucal_setMillis(ucal, ucal_getNow(), &status);
483 year = ucal_get(ucal, UCAL_YEAR, &status);
484 month = ucal_get(ucal, UCAL_MONTH, &status);
485 day = ucal_get(ucal, UCAL_DATE, &status);
486 ucal_setDateTime(ucal, year, month, day, 18, 49, 0, &status); /* set to today at 18:49:00 */
487 today = ucal_getMillis(ucal, &status);
488 ucal_close(ucal);
489 }
490 if ( U_FAILURE(status) || today == 0.0 ) {
729e4ab9 491 log_data_err("Generate UDate for a specified time today fails, error %s - (Are you missing data?)\n", myErrorName(status) );
46f4442e
A
492 return;
493 }
494 for (stylePtr = dateStylesList, monthPtnPtr = monthPatnsList; *stylePtr != UDAT_NONE; ++stylePtr, ++monthPtnPtr) {
495 UDateFormat* fmtRelDateTime;
496 UDateFormat* fmtRelDate;
497 UDateFormat* fmtTime;
498 int32_t dayOffset, limit;
499 UFieldPosition fp;
51004dcb
A
500 UChar strDateTime[kDateAndTimeOutMax];
501 UChar strDate[kDateOrTimeOutMax];
502 UChar strTime[kDateOrTimeOutMax];
503 UChar * strPtr;
46f4442e
A
504 int32_t dtpatLen;
505
506 fmtRelDateTime = udat_open(UDAT_SHORT, *stylePtr | UDAT_RELATIVE, trdfLocale, trdfZone, -1, NULL, 0, &status);
507 if ( U_FAILURE(status) ) {
729e4ab9 508 log_data_err("udat_open timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s (Are you missing data?)\n", *stylePtr, myErrorName(status) );
46f4442e
A
509 continue;
510 }
511 fmtRelDate = udat_open(UDAT_NONE, *stylePtr | UDAT_RELATIVE, trdfLocale, trdfZone, -1, NULL, 0, &status);
512 if ( U_FAILURE(status) ) {
513 log_err("udat_open timeStyle NONE dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
514 udat_close(fmtRelDateTime);
515 continue;
516 }
517 fmtTime = udat_open(UDAT_SHORT, UDAT_NONE, trdfLocale, trdfZone, -1, NULL, 0, &status);
518 if ( U_FAILURE(status) ) {
519 log_err("udat_open timeStyle SHORT dateStyle NONE fails, error %s\n", myErrorName(status) );
520 udat_close(fmtRelDateTime);
521 udat_close(fmtRelDate);
522 continue;
523 }
524
525 dtpatLen = udat_toPatternRelativeDate(fmtRelDateTime, strDate, kDateAndTimeOutMax, &status);
526 if ( U_FAILURE(status) ) {
51004dcb
A
527 log_err("udat_toPatternRelativeDate timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
528 status = U_ZERO_ERROR;
46f4442e 529 } else if ( u_strstr(strDate, *monthPtnPtr) == NULL || dtpatLen != u_strlen(strDate) ) {
51004dcb 530 log_err("udat_toPatternRelativeDate timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) date pattern incorrect\n", *stylePtr );
46f4442e
A
531 }
532 dtpatLen = udat_toPatternRelativeTime(fmtRelDateTime, strTime, kDateAndTimeOutMax, &status);
533 if ( U_FAILURE(status) ) {
51004dcb
A
534 log_err("udat_toPatternRelativeTime timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
535 status = U_ZERO_ERROR;
46f4442e 536 } else if ( u_strstr(strTime, minutesPatn) == NULL || dtpatLen != u_strlen(strTime) ) {
51004dcb 537 log_err("udat_toPatternRelativeTime timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) time pattern incorrect\n", *stylePtr );
46f4442e
A
538 }
539 dtpatLen = udat_toPattern(fmtRelDateTime, FALSE, strDateTime, kDateAndTimeOutMax, &status);
540 if ( U_FAILURE(status) ) {
51004dcb
A
541 log_err("udat_toPattern timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
542 status = U_ZERO_ERROR;
46f4442e 543 } else if ( u_strstr(strDateTime, strDate) == NULL || u_strstr(strDateTime, strTime) == NULL || dtpatLen != u_strlen(strDateTime) ) {
51004dcb 544 log_err("udat_toPattern timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) dateTime pattern incorrect\n", *stylePtr );
46f4442e
A
545 }
546 udat_applyPatternRelative(fmtRelDateTime, strDate, u_strlen(strDate), newTimePatn, u_strlen(newTimePatn), &status);
547 if ( U_FAILURE(status) ) {
51004dcb
A
548 log_err("udat_applyPatternRelative timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
549 status = U_ZERO_ERROR;
46f4442e 550 } else {
51004dcb
A
551 udat_toPattern(fmtRelDateTime, FALSE, strDateTime, kDateAndTimeOutMax, &status);
552 if ( U_FAILURE(status) ) {
553 log_err("udat_toPattern timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
554 status = U_ZERO_ERROR;
555 } else if ( u_strstr(strDateTime, newTimePatn) == NULL ) {
556 log_err("udat_applyPatternRelative timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) didn't update time pattern\n", *stylePtr );
557 }
46f4442e
A
558 }
559 udat_applyPatternRelative(fmtRelDateTime, strDate, u_strlen(strDate), strTime, u_strlen(strTime), &status); /* restore original */
560
561 fp.field = UDAT_MINUTE_FIELD;
562 for (dayOffset = -2, limit = 2; dayOffset <= limit; ++dayOffset) {
563 UDate dateToUse = today + (float)dayOffset*dayInterval;
564
565 udat_format(fmtRelDateTime, dateToUse, strDateTime, kDateAndTimeOutMax, &fp, &status);
566 if ( U_FAILURE(status) ) {
567 log_err("udat_format timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
568 status = U_ZERO_ERROR;
569 } else {
51004dcb
A
570 int32_t parsePos = 0;
571 UDate dateResult = udat_parse(fmtRelDateTime, strDateTime, -1, &parsePos, &status);
572 UDate dateDiff = (dateResult >= dateToUse)? dateResult - dateToUse: dateToUse - dateResult;
573 if ( U_FAILURE(status) || dateDiff > minutesTolerance ) {
574 log_err("udat_parse timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s, expect approx %.1f, got %.1f, parsePos %d\n",
575 *stylePtr, myErrorName(status), dateToUse, dateResult, parsePos );
576 status = U_ZERO_ERROR;
2ca993e8 577 }
51004dcb 578
46f4442e
A
579 udat_format(fmtRelDate, dateToUse, strDate, kDateOrTimeOutMax, NULL, &status);
580 if ( U_FAILURE(status) ) {
581 log_err("udat_format timeStyle NONE dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
582 status = U_ZERO_ERROR;
583 } else if ( u_strstr(strDateTime, strDate) == NULL ) {
584 log_err("relative date string not found in udat_format timeStyle SHORT dateStyle (%d | UDAT_RELATIVE)\n", *stylePtr );
51004dcb
A
585 } else {
586 parsePos = 0;
587 dateResult = udat_parse(fmtRelDate, strDate, -1, &parsePos, &status);
588 dateDiff = (dateResult >= dateToUse)? dateResult - dateToUse: dateToUse - dateResult;
589 if ( U_FAILURE(status) || dateDiff > daysTolerance ) {
590 log_err("udat_parse timeStyle NONE dateStyle (%d | UDAT_RELATIVE) fails, error %s, expect approx %.1f, got %.1f, parsePos %d\n",
591 *stylePtr, myErrorName(status), dateToUse, dateResult, parsePos );
592 status = U_ZERO_ERROR;
2ca993e8 593 }
46f4442e
A
594 }
595
596 udat_format(fmtTime, dateToUse, strTime, kDateOrTimeOutMax, NULL, &status);
597 if ( U_FAILURE(status) ) {
598 log_err("udat_format timeStyle SHORT dateStyle NONE fails, error %s\n", myErrorName(status) );
599 status = U_ZERO_ERROR;
600 } else if ( u_strstr(strDateTime, strTime) == NULL ) {
601 log_err("time string not found in udat_format timeStyle SHORT dateStyle (%d | UDAT_RELATIVE)\n", *stylePtr );
602 }
603
604 strPtr = u_strstr(strDateTime, minutesStr);
605 if ( strPtr != NULL ) {
3d1f044b 606 int32_t beginIndex = (int32_t)(strPtr - strDateTime);
46f4442e
A
607 if ( fp.beginIndex != beginIndex ) {
608 log_err("UFieldPosition beginIndex %d, expected %d, in udat_format timeStyle SHORT dateStyle (%d | UDAT_RELATIVE)\n", fp.beginIndex, beginIndex, *stylePtr );
609 }
610 } else {
611 log_err("minutes string not found in udat_format timeStyle SHORT dateStyle (%d | UDAT_RELATIVE)\n", *stylePtr );
612 }
613 }
614 }
615
616 udat_close(fmtRelDateTime);
617 udat_close(fmtRelDate);
618 udat_close(fmtTime);
619 }
620}
621
b75a7d8f
A
622/*Testing udat_getSymbols() and udat_setSymbols() and udat_countSymbols()*/
623static void TestSymbols()
624{
1a147d09 625 UDateFormat *def, *fr, *zhChiCal, *esMX;
b75a7d8f 626 UErrorCode status = U_ZERO_ERROR;
2ca993e8 627 UChar *value=NULL;
b75a7d8f
A
628 UChar *result = NULL;
629 int32_t resultlength;
630 int32_t resultlengthout;
631 UChar *pattern;
2ca993e8 632
b75a7d8f
A
633
634 /*creating a dateformat with french locale */
635 log_verbose("\ncreating a date format with french locale\n");
636 fr = udat_open(UDAT_FULL, UDAT_DEFAULT, "fr_FR", NULL, 0, NULL, 0, &status);
637 if(U_FAILURE(status))
638 {
2ca993e8 639 log_data_err("error in creating the dateformat using full time style with french locale -> %s (Are you missing data?)\n",
b75a7d8f
A
640 myErrorName(status) );
641 return;
642 }
643 /*creating a default dateformat */
644 log_verbose("\ncreating a date format with default locale\n");
2ca993e8 645 /* this is supposed to open default date format, but later on it treats it like it is "en_US"
b75a7d8f
A
646 - very bad if you try to run the tests on machine where default locale is NOT "en_US" */
647 /* def = udat_open(UDAT_DEFAULT,UDAT_DEFAULT ,NULL, NULL, 0, &status); */
648 def = udat_open(UDAT_DEFAULT,UDAT_DEFAULT ,"en_US", NULL, 0, NULL, 0, &status);
649 if(U_FAILURE(status))
650 {
2ca993e8 651 log_err("error in creating the dateformat using short date and time style\n %s\n",
b75a7d8f
A
652 myErrorName(status) );
653 return;
654 }
b331163b
A
655 /*creating a dateformat with zh locale */
656 log_verbose("\ncreating a date format with zh locale for chinese calendar\n");
657 zhChiCal = udat_open(UDAT_NONE, UDAT_FULL, "zh@calendar=chinese", NULL, 0, NULL, 0, &status);
658 if(U_FAILURE(status))
659 {
2ca993e8 660 log_data_err("error in creating the dateformat using full date, no time, locale zh@calendar=chinese -> %s (Are you missing data?)\n",
b331163b
A
661 myErrorName(status) );
662 return;
663 }
1a147d09
A
664 /*creating a dateformat with es_MX locale */
665 log_verbose("\ncreating a date format with es_MX locale\n");
666 esMX = udat_open(UDAT_SHORT, UDAT_NONE, "es_MX", NULL, 0, NULL, 0, &status);
667 if(U_FAILURE(status))
668 {
669 log_data_err("error in creating the dateformat using no date, short time, locale es_MX -> %s (Are you missing data?)\n",
670 myErrorName(status) );
671 return;
672 }
2ca993e8
A
673
674
b75a7d8f
A
675 /*Testing countSymbols, getSymbols and setSymbols*/
676 log_verbose("\nTesting countSymbols\n");
677 /*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 */
2ca993e8 678 if(udat_countSymbols(def, UDAT_ERAS)!=2 || udat_countSymbols(def, UDAT_MONTHS)!=12 ||
b75a7d8f
A
679 udat_countSymbols(def, UDAT_SHORT_MONTHS)!=12 || udat_countSymbols(def, UDAT_WEEKDAYS)!=8 ||
680 udat_countSymbols(def, UDAT_SHORT_WEEKDAYS)!=8 || udat_countSymbols(def, UDAT_AM_PMS)!=2 ||
73c04bcf 681 udat_countSymbols(def, UDAT_QUARTERS) != 4 || udat_countSymbols(def, UDAT_SHORT_QUARTERS) != 4 ||
b331163b
A
682 udat_countSymbols(def, UDAT_LOCALIZED_CHARS)!=1 || udat_countSymbols(def, UDAT_SHORTER_WEEKDAYS)!=8 ||
683 udat_countSymbols(zhChiCal, UDAT_CYCLIC_YEARS_NARROW)!=60 || udat_countSymbols(zhChiCal, UDAT_ZODIAC_NAMES_NARROW)!=12)
b75a7d8f
A
684 {
685 log_err("FAIL: error in udat_countSymbols\n");
686 }
687 else
688 log_verbose("PASS: udat_countSymbols() successful\n");
689
690 /*testing getSymbols*/
691 log_verbose("\nTesting getSymbols\n");
692 pattern=(UChar*)malloc(sizeof(UChar) * 10);
693 u_uastrcpy(pattern, "jeudi");
694 resultlength=0;
695 resultlengthout=udat_getSymbols(fr, UDAT_WEEKDAYS, 5 , NULL, resultlength, &status);
696 if(status==U_BUFFER_OVERFLOW_ERROR)
697 {
698 status=U_ZERO_ERROR;
699 resultlength=resultlengthout+1;
700 if(result != NULL) {
701 free(result);
702 result = NULL;
703 }
704 result=(UChar*)malloc(sizeof(UChar) * resultlength);
705 udat_getSymbols(fr, UDAT_WEEKDAYS, 5, result, resultlength, &status);
2ca993e8 706
b75a7d8f
A
707 }
708 if(U_FAILURE(status))
709 {
710 log_err("FAIL: Error in udat_getSymbols().... %s\n", myErrorName(status) );
711 }
712 else
713 log_verbose("PASS: getSymbols succesful\n");
714
715 if(u_strcmp(result, pattern)==0)
716 log_verbose("PASS: getSymbols retrieved the right value\n");
717 else
718 log_data_err("FAIL: getSymbols retrieved the wrong value\n");
719
720 /*run series of tests to test getsymbols regressively*/
721 log_verbose("\nTesting getSymbols() regressively\n");
722 VerifygetSymbols(fr, UDAT_WEEKDAYS, 1, "dimanche");
723 VerifygetSymbols(def, UDAT_WEEKDAYS, 1, "Sunday");
724 VerifygetSymbols(fr, UDAT_SHORT_WEEKDAYS, 7, "sam.");
51004dcb 725 VerifygetSymbols(fr, UDAT_SHORTER_WEEKDAYS, 7, "sa");
b75a7d8f
A
726 VerifygetSymbols(def, UDAT_SHORT_WEEKDAYS, 7, "Sat");
727 VerifygetSymbols(def, UDAT_MONTHS, 11, "December");
728 VerifygetSymbols(def, UDAT_MONTHS, 0, "January");
729 VerifygetSymbols(fr, UDAT_ERAS, 0, "av. J.-C.");
730 VerifygetSymbols(def, UDAT_AM_PMS, 0, "AM");
731 VerifygetSymbols(def, UDAT_AM_PMS, 1, "PM");
732 VerifygetSymbols(fr, UDAT_SHORT_MONTHS, 0, "janv.");
733 VerifygetSymbols(def, UDAT_SHORT_MONTHS, 11, "Dec");
73c04bcf
A
734 VerifygetSymbols(fr, UDAT_QUARTERS, 0, "1er trimestre");
735 VerifygetSymbols(def, UDAT_QUARTERS, 3, "4th quarter");
736 VerifygetSymbols(fr, UDAT_SHORT_QUARTERS, 1, "T2");
737 VerifygetSymbols(def, UDAT_SHORT_QUARTERS, 2, "Q3");
b331163b
A
738 VerifygetSymbols(zhChiCal, UDAT_CYCLIC_YEARS_ABBREVIATED, 0, "\\u7532\\u5B50");
739 VerifygetSymbols(zhChiCal, UDAT_CYCLIC_YEARS_NARROW, 59, "\\u7678\\u4EA5");
740 VerifygetSymbols(zhChiCal, UDAT_ZODIAC_NAMES_ABBREVIATED, 0, "\\u9F20");
741 VerifygetSymbols(zhChiCal, UDAT_ZODIAC_NAMES_WIDE, 11, "\\u732A");
1a147d09
A
742 VerifygetSymbols(esMX, UDAT_AM_PMS, 0, "a.m."); // see <rdar://problem/52923924>
743 VerifygetSymbols(esMX, UDAT_AM_PMS, 1, "p.m."); // see <rdar://problem/52923924>
2ca993e8
A
744#if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
745 VerifygetSymbols(def,UDAT_LOCALIZED_CHARS, 0, "GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB:");
746#else
747 VerifygetSymbols(def,UDAT_LOCALIZED_CHARS, 0, "GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB");
748#endif
b75a7d8f
A
749
750
751 if(result != NULL) {
752 free(result);
753 result = NULL;
754 }
2ca993e8
A
755free(pattern);
756
b75a7d8f
A
757 log_verbose("\nTesting setSymbols\n");
758 /*applying the pattern so that setSymbolss works */
759 resultlength=0;
760 resultlengthout=udat_toPattern(fr, FALSE, NULL, resultlength, &status);
761 if(status==U_BUFFER_OVERFLOW_ERROR)
762 {
763 status=U_ZERO_ERROR;
764 resultlength=resultlengthout + 1;
765 pattern=(UChar*)malloc(sizeof(UChar) * resultlength);
766 udat_toPattern(fr, FALSE, pattern, resultlength, &status);
767 }
768 if(U_FAILURE(status))
769 {
2ca993e8 770 log_err("FAIL: error in extracting the pattern from UNumberFormat\n %s\n",
b75a7d8f
A
771 myErrorName(status) );
772 }
2ca993e8 773
b75a7d8f
A
774 udat_applyPattern(def, FALSE, pattern, u_strlen(pattern));
775 resultlength=0;
776 resultlengthout=udat_toPattern(def, FALSE, NULL, resultlength,&status);
777 if(status==U_BUFFER_OVERFLOW_ERROR)
778 {
779 status=U_ZERO_ERROR;
780 resultlength=resultlengthout + 1;
781 if(result != NULL) {
782 free(result);
783 result = NULL;
784 }
785 result=(UChar*)malloc(sizeof(UChar) * resultlength);
786 udat_toPattern(fr, FALSE,result, resultlength, &status);
787 }
788 if(U_FAILURE(status))
789 {
2ca993e8 790 log_err("FAIL: error in extracting the pattern from UNumberFormat\n %s\n",
b75a7d8f
A
791 myErrorName(status) );
792 }
793 if(u_strcmp(result, pattern)==0)
794 log_verbose("Pattern applied properly\n");
795 else
796 log_err("pattern could not be applied properly\n");
797
798free(pattern);
799 /*testing set symbols */
800 resultlength=0;
801 resultlengthout=udat_getSymbols(fr, UDAT_MONTHS, 11 , NULL, resultlength, &status);
802 if(status==U_BUFFER_OVERFLOW_ERROR){
803 status=U_ZERO_ERROR;
804 resultlength=resultlengthout+1;
805 if(result != NULL) {
806 free(result);
807 result = NULL;
808 }
809 result=(UChar*)malloc(sizeof(UChar) * resultlength);
810 udat_getSymbols(fr, UDAT_MONTHS, 11, result, resultlength, &status);
2ca993e8 811
b75a7d8f
A
812 }
813 if(U_FAILURE(status))
814 log_err("FAIL: error in getSymbols() %s\n", myErrorName(status) );
815 resultlength=resultlengthout+1;
2ca993e8 816
b75a7d8f
A
817 udat_setSymbols(def, UDAT_MONTHS, 11, result, resultlength, &status);
818 if(U_FAILURE(status))
819 {
820 log_err("FAIL: Error in udat_setSymbols() : %s\n", myErrorName(status) );
821 }
822 else
823 log_verbose("PASS: SetSymbols successful\n");
2ca993e8 824
b75a7d8f
A
825 resultlength=0;
826 resultlengthout=udat_getSymbols(def, UDAT_MONTHS, 11, NULL, resultlength, &status);
827 if(status==U_BUFFER_OVERFLOW_ERROR){
828 status=U_ZERO_ERROR;
829 resultlength=resultlengthout+1;
830 value=(UChar*)malloc(sizeof(UChar) * resultlength);
831 udat_getSymbols(def, UDAT_MONTHS, 11, value, resultlength, &status);
832 }
833 if(U_FAILURE(status))
834 log_err("FAIL: error in retrieving the value using getSymbols i.e roundtrip\n");
2ca993e8 835
b75a7d8f
A
836 if(u_strcmp(result, value)!=0)
837 log_data_err("FAIL: Error in settting and getting symbols\n");
838 else
839 log_verbose("PASS: setSymbols successful\n");
2ca993e8
A
840
841
b75a7d8f
A
842 /*run series of tests to test setSymbols regressively*/
843 log_verbose("\nTesting setSymbols regressively\n");
b75a7d8f 844 VerifysetSymbols(def, UDAT_ERAS, 0, "BeforeChrist");
73c04bcf
A
845 VerifysetSymbols(def, UDAT_ERA_NAMES, 1, "AnnoDomini");
846 VerifysetSymbols(def, UDAT_WEEKDAYS, 1, "Sundayweek");
b75a7d8f 847 VerifysetSymbols(def, UDAT_SHORT_WEEKDAYS, 7, "Satweek");
73c04bcf
A
848 VerifysetSymbols(def, UDAT_NARROW_WEEKDAYS, 4, "M");
849 VerifysetSymbols(def, UDAT_STANDALONE_WEEKDAYS, 1, "Sonntagweek");
850 VerifysetSymbols(def, UDAT_STANDALONE_SHORT_WEEKDAYS, 7, "Sams");
851 VerifysetSymbols(def, UDAT_STANDALONE_NARROW_WEEKDAYS, 4, "V");
b75a7d8f
A
852 VerifysetSymbols(fr, UDAT_MONTHS, 11, "december");
853 VerifysetSymbols(fr, UDAT_SHORT_MONTHS, 0, "Jan");
73c04bcf
A
854 VerifysetSymbols(fr, UDAT_NARROW_MONTHS, 1, "R");
855 VerifysetSymbols(fr, UDAT_STANDALONE_MONTHS, 11, "dezember");
856 VerifysetSymbols(fr, UDAT_STANDALONE_SHORT_MONTHS, 7, "Aug");
857 VerifysetSymbols(fr, UDAT_STANDALONE_NARROW_MONTHS, 2, "M");
858 VerifysetSymbols(fr, UDAT_QUARTERS, 0, "1. Quart");
859 VerifysetSymbols(fr, UDAT_SHORT_QUARTERS, 1, "QQ2");
860 VerifysetSymbols(fr, UDAT_STANDALONE_QUARTERS, 2, "3rd Quar.");
861 VerifysetSymbols(fr, UDAT_STANDALONE_SHORT_QUARTERS, 3, "4QQ");
b331163b
A
862 VerifysetSymbols(zhChiCal, UDAT_CYCLIC_YEARS_ABBREVIATED, 1, "yi-chou");
863 VerifysetSymbols(zhChiCal, UDAT_ZODIAC_NAMES_ABBREVIATED, 1, "Ox");
864
b75a7d8f 865
b75a7d8f
A
866 /*run series of tests to test get and setSymbols regressively*/
867 log_verbose("\nTesting get and set symbols regressively\n");
868 VerifygetsetSymbols(fr, def, UDAT_WEEKDAYS, 1);
869 VerifygetsetSymbols(fr, def, UDAT_WEEKDAYS, 7);
870 VerifygetsetSymbols(fr, def, UDAT_SHORT_WEEKDAYS, 1);
871 VerifygetsetSymbols(fr, def, UDAT_SHORT_WEEKDAYS, 7);
872 VerifygetsetSymbols(fr, def, UDAT_MONTHS, 0);
873 VerifygetsetSymbols(fr, def, UDAT_SHORT_MONTHS, 0);
874 VerifygetsetSymbols(fr, def, UDAT_ERAS,1);
875 VerifygetsetSymbols(fr, def, UDAT_LOCALIZED_CHARS, 0);
876 VerifygetsetSymbols(fr, def, UDAT_AM_PMS, 1);
877
878
879 /*closing*/
2ca993e8 880
b75a7d8f
A
881 udat_close(fr);
882 udat_close(def);
b331163b 883 udat_close(zhChiCal);
1a147d09 884 udat_close(esMX);
b75a7d8f
A
885 if(result != NULL) {
886 free(result);
887 result = NULL;
888 }
889 free(value);
2ca993e8 890
b75a7d8f
A
891}
892
893/**
894 * Test DateFormat(Calendar) API
895 */
896static void TestDateFormatCalendar() {
897 UDateFormat *date=0, *time=0, *full=0;
898 UCalendar *cal=0;
899 UChar buf[256];
900 char cbuf[256];
901 int32_t pos;
902 UDate when;
903 UErrorCode ec = U_ZERO_ERROR;
b331163b
A
904 UChar buf1[256];
905 int32_t len1;
906 const char *expected;
907 UChar uExpected[32];
b75a7d8f 908
374ca955
A
909 ctest_setTimeZone(NULL, &ec);
910
b75a7d8f
A
911 /* Create a formatter for date fields. */
912 date = udat_open(UDAT_NONE, UDAT_SHORT, "en_US", NULL, 0, NULL, 0, &ec);
913 if (U_FAILURE(ec)) {
2ca993e8 914 log_data_err("FAIL: udat_open(NONE, SHORT, en_US) failed with %s (Are you missing data?)\n",
b75a7d8f
A
915 u_errorName(ec));
916 goto FAIL;
917 }
918
919 /* Create a formatter for time fields. */
920 time = udat_open(UDAT_SHORT, UDAT_NONE, "en_US", NULL, 0, NULL, 0, &ec);
921 if (U_FAILURE(ec)) {
2ca993e8 922 log_err("FAIL: udat_open(SHORT, NONE, en_US) failed with %s\n",
b75a7d8f
A
923 u_errorName(ec));
924 goto FAIL;
925 }
926
927 /* Create a full format for output */
928 full = udat_open(UDAT_FULL, UDAT_FULL, "en_US", NULL, 0, NULL, 0, &ec);
929 if (U_FAILURE(ec)) {
2ca993e8 930 log_err("FAIL: udat_open(FULL, FULL, en_US) failed with %s\n",
b75a7d8f
A
931 u_errorName(ec));
932 goto FAIL;
933 }
934
935 /* Create a calendar */
936 cal = ucal_open(NULL, 0, "en_US", UCAL_GREGORIAN, &ec);
937 if (U_FAILURE(ec)) {
2ca993e8 938 log_err("FAIL: ucal_open(en_US) failed with %s\n",
b75a7d8f
A
939 u_errorName(ec));
940 goto FAIL;
941 }
942
943 /* Parse the date */
944 ucal_clear(cal);
945 u_uastrcpy(buf, "4/5/2001");
946 pos = 0;
947 udat_parseCalendar(date, cal, buf, -1, &pos, &ec);
948 if (U_FAILURE(ec)) {
949 log_err("FAIL: udat_parseCalendar(4/5/2001) failed at %d with %s\n",
950 pos, u_errorName(ec));
951 goto FAIL;
952 }
953
b331163b
A
954 /* Check if formatCalendar matches the original date */
955 len1 = udat_formatCalendar(date, cal, buf1, UPRV_LENGTHOF(buf1), NULL, &ec);
956 if (U_FAILURE(ec)) {
957 log_err("FAIL: udat_formatCalendar(4/5/2001) failed with %s\n",
958 u_errorName(ec));
959 goto FAIL;
960 }
961 expected = "4/5/01";
962 u_uastrcpy(uExpected, expected);
963 if (u_strlen(uExpected) != len1 || u_strncmp(uExpected, buf1, len1) != 0) {
964 log_err("FAIL: udat_formatCalendar(4/5/2001), expected: %s", expected);
965 }
966
b75a7d8f
A
967 /* Parse the time */
968 u_uastrcpy(buf, "5:45 PM");
969 pos = 0;
970 udat_parseCalendar(time, cal, buf, -1, &pos, &ec);
971 if (U_FAILURE(ec)) {
972 log_err("FAIL: udat_parseCalendar(17:45) failed at %d with %s\n",
973 pos, u_errorName(ec));
974 goto FAIL;
975 }
b331163b
A
976
977 /* Check if formatCalendar matches the original time */
978 len1 = udat_formatCalendar(time, cal, buf1, UPRV_LENGTHOF(buf1), NULL, &ec);
979 if (U_FAILURE(ec)) {
980 log_err("FAIL: udat_formatCalendar(17:45) failed with %s\n",
981 u_errorName(ec));
982 goto FAIL;
983 }
984 expected = "5:45 PM";
985 u_uastrcpy(uExpected, expected);
986 if (u_strlen(uExpected) != len1 || u_strncmp(uExpected, buf1, len1) != 0) {
987 log_err("FAIL: udat_formatCalendar(17:45), expected: %s", expected);
988 }
989
b75a7d8f
A
990 /* Check result */
991 when = ucal_getMillis(cal, &ec);
992 if (U_FAILURE(ec)) {
993 log_err("FAIL: ucal_getMillis() failed with %s\n", u_errorName(ec));
994 goto FAIL;
995 }
996 udat_format(full, when, buf, sizeof(buf), NULL, &ec);
997 if (U_FAILURE(ec)) {
998 log_err("FAIL: udat_format() failed with %s\n", u_errorName(ec));
999 goto FAIL;
1000 }
1001 u_austrcpy(cbuf, buf);
1002 /* Thursday, April 5, 2001 5:45:00 PM PDT 986517900000 */
1003 if (when == 986517900000.0) {
1004 log_verbose("Ok: Parsed result: %s\n", cbuf);
1005 } else {
374ca955 1006 log_err("FAIL: Parsed result: %s, exp 4/5/2001 5:45 PM\n", cbuf);
b75a7d8f
A
1007 }
1008
2ca993e8 1009 FAIL:
b75a7d8f
A
1010 udat_close(date);
1011 udat_close(time);
1012 udat_close(full);
1013 ucal_close(cal);
374ca955
A
1014
1015 ctest_resetTimeZone();
b75a7d8f
A
1016}
1017
51004dcb
A
1018
1019
1020/**
57a6839d 1021 * Test parsing two digit year against "YY" vs. "YYYY" patterns
51004dcb
A
1022 */
1023static void TestCalendarDateParse() {
1024
57a6839d
A
1025 int32_t result;
1026 UErrorCode ec = U_ZERO_ERROR;
51004dcb 1027 UDateFormat* simpleDateFormat = 0;
57a6839d
A
1028 int32_t parsePos = 0;
1029 int32_t twoDigitCenturyStart = 75;
1030 int32_t currentTwoDigitYear = 0;
1031 int32_t startCentury = 0;
51004dcb
A
1032 UCalendar* tempCal = 0;
1033 UCalendar* calendar = 0;
1034
1035 U_STRING_DECL(pattern, "yyyy", 4);
1036 U_STRING_DECL(pattern2, "yy", 2);
1037 U_STRING_DECL(text, "75", 2);
1038
1039 U_STRING_INIT(pattern, "yyyy", 4);
1040 U_STRING_INIT(pattern2, "yy", 2);
1041 U_STRING_INIT(text, "75", 2);
1042
1043 simpleDateFormat = udat_open(UDAT_FULL, UDAT_FULL, "en-GB", 0, 0, 0, 0, &ec);
1044 if (U_FAILURE(ec)) {
1045 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));
1046 return;
1047 }
1048 udat_applyPattern(simpleDateFormat, 0, pattern, u_strlen(pattern));
1049 udat_setLenient(simpleDateFormat, 0);
1050
1051 currentTwoDigitYear = getCurrentYear() % 100;
1052 startCentury = getCurrentYear() - currentTwoDigitYear;
1053 if (twoDigitCenturyStart > currentTwoDigitYear) {
57a6839d 1054 startCentury -= 100;
51004dcb 1055 }
57a6839d
A
1056 tempCal = ucal_open(NULL, -1, NULL, UCAL_GREGORIAN, &ec);
1057 ucal_setMillis(tempCal, 0, &ec);
1058 ucal_setDateTime(tempCal, startCentury + twoDigitCenturyStart, UCAL_JANUARY, 1, 0, 0, 0, &ec);
1059 udat_set2DigitYearStart(simpleDateFormat, ucal_getMillis(tempCal, &ec), &ec);
51004dcb 1060
57a6839d
A
1061 calendar = ucal_open(NULL, -1, NULL, UCAL_GREGORIAN, &ec);
1062 ucal_setMillis(calendar, 0, &ec);
1063 ucal_setDateTime(calendar, twoDigitCenturyStart, UCAL_JANUARY, 1, 0, 0, 0, &ec);
51004dcb 1064
57a6839d 1065 udat_parseCalendar(simpleDateFormat, calendar, text, u_strlen(text), &parsePos, &ec);
51004dcb
A
1066
1067 /* Check result */
1068 result = ucal_get(calendar, UCAL_YEAR, &ec);
1069 if (U_FAILURE(ec)) {
1070 log_err("FAIL: ucal_get(UCAL_YEAR) failed with %s\n", u_errorName(ec));
1071 goto FAIL;
1072 }
1073
1074 if (result != 75) {
1075 log_err("FAIL: parsed incorrect year: %d\n", result);
1076 goto FAIL;
1077 }
1078
1079 parsePos = 0;
1080 udat_applyPattern(simpleDateFormat, 0, pattern2, u_strlen(pattern2));
57a6839d 1081 udat_parseCalendar(simpleDateFormat, calendar, text, u_strlen(text), &parsePos, &ec);
51004dcb
A
1082
1083 /* Check result */
1084 result = ucal_get(calendar, UCAL_YEAR, &ec);
1085 if (U_FAILURE(ec)) {
1086 log_err("FAIL: ucal_get(UCAL_YEAR) failed with %s\n", u_errorName(ec));
1087 goto FAIL;
1088 }
1089
1090 if (result != 1975) {
1091 log_err("FAIL: parsed incorrect year: %d\n", result);
1092 goto FAIL;
1093 }
1094
1095 FAIL:
1096 udat_close(simpleDateFormat);
1097 udat_close(tempCal);
1098 udat_close(calendar);
1099}
1100
1101
b75a7d8f 1102/*INTERNAL FUNCTIONS USED*/
51004dcb
A
1103static int getCurrentYear() {
1104 static int currentYear = 0;
1105 if (currentYear == 0) {
1106 UErrorCode status = U_ZERO_ERROR;
1107 UCalendar *cal = ucal_open(NULL, -1, NULL, UCAL_GREGORIAN, &status);
1108 if (!U_FAILURE(status)) {
1109 /* Get the current year from the default UCalendar */
1110 currentYear = ucal_get(cal, UCAL_YEAR, &status);
1111 ucal_close(cal);
1112 }
1113 }
1114
1115 return currentYear;
1116}
1117
729e4ab9
A
1118/* N.B.: use idx instead of index to avoid 'shadow' warnings in strict mode. */
1119static void VerifygetSymbols(UDateFormat* datfor, UDateFormatSymbolType type, int32_t idx, const char* expected)
b75a7d8f
A
1120{
1121 UChar *pattern=NULL;
1122 UErrorCode status = U_ZERO_ERROR;
1123 UChar *result=NULL;
1124 int32_t resultlength, resultlengthout;
3d1f044b 1125 int32_t patternSize = (int32_t)strlen(expected) + 1;
2ca993e8 1126
b331163b
A
1127 pattern=(UChar*)malloc(sizeof(UChar) * patternSize);
1128 u_unescape(expected, pattern, patternSize);
b75a7d8f 1129 resultlength=0;
729e4ab9 1130 resultlengthout=udat_getSymbols(datfor, type, idx , NULL, resultlength, &status);
b75a7d8f
A
1131 if(status==U_BUFFER_OVERFLOW_ERROR)
1132 {
1133 status=U_ZERO_ERROR;
1134 resultlength=resultlengthout+1;
1135 result=(UChar*)malloc(sizeof(UChar) * resultlength);
729e4ab9 1136 udat_getSymbols(datfor, type, idx, result, resultlength, &status);
2ca993e8 1137
b75a7d8f
A
1138 }
1139 if(U_FAILURE(status))
1140 {
1141 log_err("FAIL: Error in udat_getSymbols()... %s\n", myErrorName(status) );
1142 return;
1143 }
1144 if(u_strcmp(result, pattern)==0)
1145 log_verbose("PASS: getSymbols retrieved the right value\n");
1146 else{
2ca993e8 1147 log_data_err("FAIL: getSymbols retrieved the wrong value\n Expected %s Got %s\n", expected,
b331163b 1148 aescstrdup(result,-1) );
b75a7d8f
A
1149 }
1150 free(result);
1151 free(pattern);
1152}
1153
729e4ab9 1154static void VerifysetSymbols(UDateFormat* datfor, UDateFormatSymbolType type, int32_t idx, const char* expected)
b75a7d8f
A
1155{
1156 UChar *result=NULL;
1157 UChar *value=NULL;
1158 int32_t resultlength, resultlengthout;
1159 UErrorCode status = U_ZERO_ERROR;
3d1f044b 1160 int32_t valueLen, valueSize = (int32_t)strlen(expected) + 1;
b75a7d8f 1161
b331163b
A
1162 value=(UChar*)malloc(sizeof(UChar) * valueSize);
1163 valueLen = u_unescape(expected, value, valueSize);
1164 udat_setSymbols(datfor, type, idx, value, valueLen, &status);
b75a7d8f
A
1165 if(U_FAILURE(status))
1166 {
1167 log_err("FAIL: Error in udat_setSymbols() %s\n", myErrorName(status) );
1168 return;
1169 }
1170
1171 resultlength=0;
729e4ab9 1172 resultlengthout=udat_getSymbols(datfor, type, idx, NULL, resultlength, &status);
b75a7d8f
A
1173 if(status==U_BUFFER_OVERFLOW_ERROR){
1174 status=U_ZERO_ERROR;
1175 resultlength=resultlengthout+1;
1176 result=(UChar*)malloc(sizeof(UChar) * resultlength);
729e4ab9 1177 udat_getSymbols(datfor, type, idx, result, resultlength, &status);
b75a7d8f
A
1178 }
1179 if(U_FAILURE(status)){
2ca993e8 1180 log_err("FAIL: error in retrieving the value using getSymbols after setting it previously\n %s\n",
b75a7d8f
A
1181 myErrorName(status) );
1182 return;
1183 }
2ca993e8 1184
b75a7d8f 1185 if(u_strcmp(result, value)!=0){
b331163b
A
1186 log_err("FAIL:Error in setting and then getting symbols\n Expected %s Got %s\n", expected,
1187 aescstrdup(result,-1) );
b75a7d8f
A
1188 }
1189 else
1190 log_verbose("PASS: setSymbols successful\n");
1191
1192 free(value);
1193 free(result);
1194}
1195
1196
729e4ab9 1197static void VerifygetsetSymbols(UDateFormat* from, UDateFormat* to, UDateFormatSymbolType type, int32_t idx)
b75a7d8f
A
1198{
1199 UChar *result=NULL;
1200 UChar *value=NULL;
1201 int32_t resultlength, resultlengthout;
1202 UErrorCode status = U_ZERO_ERROR;
2ca993e8 1203
b75a7d8f 1204 resultlength=0;
729e4ab9 1205 resultlengthout=udat_getSymbols(from, type, idx , NULL, resultlength, &status);
b75a7d8f
A
1206 if(status==U_BUFFER_OVERFLOW_ERROR){
1207 status=U_ZERO_ERROR;
1208 resultlength=resultlengthout+1;
1209 result=(UChar*)malloc(sizeof(UChar) * resultlength);
729e4ab9 1210 udat_getSymbols(from, type, idx, result, resultlength, &status);
b75a7d8f
A
1211 }
1212 if(U_FAILURE(status)){
1213 log_err("FAIL: error in getSymbols() %s\n", myErrorName(status) );
1214 return;
1215 }
2ca993e8 1216
b75a7d8f 1217 resultlength=resultlengthout+1;
729e4ab9 1218 udat_setSymbols(to, type, idx, result, resultlength, &status);
b75a7d8f
A
1219 if(U_FAILURE(status))
1220 {
1221 log_err("FAIL: Error in udat_setSymbols() : %s\n", myErrorName(status) );
1222 return;
1223 }
1224
1225 resultlength=0;
729e4ab9 1226 resultlengthout=udat_getSymbols(to, type, idx, NULL, resultlength, &status);
b75a7d8f
A
1227 if(status==U_BUFFER_OVERFLOW_ERROR){
1228 status=U_ZERO_ERROR;
1229 resultlength=resultlengthout+1;
1230 value=(UChar*)malloc(sizeof(UChar) * resultlength);
729e4ab9 1231 udat_getSymbols(to, type, idx, value, resultlength, &status);
b75a7d8f
A
1232 }
1233 if(U_FAILURE(status)){
2ca993e8 1234 log_err("FAIL: error in retrieving the value using getSymbols i.e roundtrip\n %s\n",
b75a7d8f
A
1235 myErrorName(status) );
1236 return;
1237 }
2ca993e8 1238
b75a7d8f
A
1239 if(u_strcmp(result, value)!=0){
1240 log_data_err("FAIL:Error in setting and then getting symbols\n Expected %s Got %s\n", austrdup(result),
1241 austrdup(value) );
1242 }
1243 else
1244 log_verbose("PASS: setSymbols successful\n");
1245
1246 free(value);
1247 free(result);
1248}
1249
1250
1251static UChar* myNumformat(const UNumberFormat* numfor, double d)
1252{
1253 UChar *result2=NULL;
1254 int32_t resultlength, resultlengthneeded;
1255 UErrorCode status = U_ZERO_ERROR;
2ca993e8 1256
b75a7d8f
A
1257 resultlength=0;
1258 resultlengthneeded=unum_formatDouble(numfor, d, NULL, resultlength, NULL, &status);
1259 if(status==U_BUFFER_OVERFLOW_ERROR)
1260 {
1261 status=U_ZERO_ERROR;
1262 resultlength=resultlengthneeded+1;
1263 /*result2=(UChar*)malloc(sizeof(UChar) * resultlength);*/ /* this leaks */
1264 result2=(UChar*)ctst_malloc(sizeof(UChar) * resultlength); /*this won't*/
1265 unum_formatDouble(numfor, d, result2, resultlength, NULL, &status);
1266 }
1267 if(U_FAILURE(status))
1268 {
1269 log_err("FAIL: Error in formatting using unum_format(.....) %s\n", myErrorName(status) );
1270 return 0;
1271 }
2ca993e8 1272
b75a7d8f
A
1273 return result2;
1274}
1275
374ca955
A
1276/**
1277 * The search depth for TestExtremeDates. The total number of
1278 * dates that will be tested is (2^EXTREME_DATES_DEPTH) - 1.
1279 */
1280#define EXTREME_DATES_DEPTH 8
1281
1282/**
1283 * Support for TestExtremeDates (below).
1284 *
1285 * Test a single date to see whether udat_format handles it properly.
1286 */
1287static UBool _aux1ExtremeDates(UDateFormat* fmt, UDate date,
1288 UChar* buf, int32_t buflen, char* cbuf,
1289 UErrorCode* ec) {
1290 int32_t len = udat_format(fmt, date, buf, buflen, 0, ec);
1291 if (!assertSuccess("udat_format", ec)) return FALSE;
1292 u_austrncpy(cbuf, buf, buflen);
1293 if (len < 4) {
1294 log_err("FAIL: udat_format(%g) => \"%s\"\n", date, cbuf);
1295 } else {
1296 log_verbose("udat_format(%g) => \"%s\"\n", date, cbuf);
1297 }
1298 return TRUE;
1299}
1300
1301/**
1302 * Support for TestExtremeDates (below).
1303 *
1304 * Recursively test between 'small' and 'large', up to the depth
1305 * limit specified by EXTREME_DATES_DEPTH.
1306 */
1307static UBool _aux2ExtremeDates(UDateFormat* fmt, UDate small, UDate large,
1308 UChar* buf, int32_t buflen, char* cbuf,
1309 int32_t count,
1310 UErrorCode* ec) {
1311 /* Logarithmic midpoint; see below */
1312 UDate mid = (UDate) exp((log(small) + log(large)) / 2);
1313 if (count == EXTREME_DATES_DEPTH) {
1314 return TRUE;
1315 }
1316 return
1317 _aux1ExtremeDates(fmt, mid, buf, buflen, cbuf, ec) &&
1318 _aux2ExtremeDates(fmt, small, mid, buf, buflen, cbuf, count+1, ec) &&
1319 _aux2ExtremeDates(fmt, mid, large, buf, buflen, cbuf, count+1, ec);
1320}
1321
1322/**
1323 * http://www.jtcsv.com/cgibin/icu-bugs?findid=3659
1324 *
1325 * For certain large dates, udat_format crashes on MacOS. This test
1326 * attempts to reproduce this problem by doing a recursive logarithmic*
1327 * binary search of a predefined interval (from 'small' to 'large').
1328 *
1329 * The limit of the search is given by EXTREME_DATES_DEPTH, above.
1330 *
1331 * *The search has to be logarithmic, not linear. A linear search of the
1332 * range 0..10^30, for example, will find 0.5*10^30, then 0.25*10^30 and
1333 * 0.75*10^30, etc. A logarithmic search will find 10^15, then 10^7.5
1334 * and 10^22.5, etc.
1335 */
1336static void TestExtremeDates() {
1337 UDateFormat *fmt;
1338 UErrorCode ec;
1339 UChar buf[256];
1340 char cbuf[256];
1341 const double small = 1000; /* 1 sec */
1342 const double large = 1e+30; /* well beyond usable UDate range */
1343
1344 /* There is no need to test larger values from 1e+30 to 1e+300;
1345 the failures occur around 1e+27, and never above 1e+30. */
2ca993e8 1346
374ca955
A
1347 ec = U_ZERO_ERROR;
1348 fmt = udat_open(UDAT_LONG, UDAT_LONG, "en_US",
1349 0, 0, 0, 0, &ec);
729e4ab9
A
1350 if (U_FAILURE(ec)) {
1351 log_data_err("FAIL: udat_open (%s) (Are you missing data?)\n", u_errorName(ec));
1352 return;
1353 }
374ca955 1354
2ca993e8 1355 _aux2ExtremeDates(fmt, small, large, buf, UPRV_LENGTHOF(buf), cbuf, 0, &ec);
374ca955
A
1356
1357 udat_close(fmt);
1358}
1359
73c04bcf
A
1360static void TestAllLocales(void) {
1361 int32_t idx, dateIdx, timeIdx, localeCount;
1362 static const UDateFormatStyle style[] = {
1363 UDAT_FULL, UDAT_LONG, UDAT_MEDIUM, UDAT_SHORT
1364 };
1365 localeCount = uloc_countAvailable();
1366 for (idx = 0; idx < localeCount; idx++) {
2ca993e8
A
1367 for (dateIdx = 0; dateIdx < UPRV_LENGTHOF(style); dateIdx++) {
1368 for (timeIdx = 0; timeIdx < UPRV_LENGTHOF(style); timeIdx++) {
73c04bcf
A
1369 UErrorCode status = U_ZERO_ERROR;
1370 udat_close(udat_open(style[dateIdx], style[timeIdx],
1371 uloc_getAvailable(idx), NULL, 0, NULL, 0, &status));
1372 if (U_FAILURE(status)) {
1373 log_err("FAIL: udat_open(%s) failed with (%s) dateIdx=%d, timeIdx=%d\n",
1374 uloc_getAvailable(idx), u_errorName(status), dateIdx, timeIdx);
1375 }
1376 }
1377 }
1378 }
1379}
1380
46f4442e
A
1381static void TestRelativeCrash(void) {
1382 static const UChar tzName[] = { 0x0055, 0x0053, 0x002F, 0x0050, 0x0061, 0x0063, 0x0069, 0x0066, 0x0069, 0x0063, 0 };
1383 static const UDate aDate = -631152000000.0;
1384
1385 UErrorCode status = U_ZERO_ERROR;
1386 UErrorCode expectStatus = U_ILLEGAL_ARGUMENT_ERROR;
1387 UDateFormat icudf;
1388
1389 icudf = udat_open(UDAT_NONE, UDAT_SHORT_RELATIVE, "en", tzName, -1, NULL, 0, &status);
1390 if ( U_SUCCESS(status) ) {
1391 const char *what = "???";
1392 {
1393 UErrorCode subStatus = U_ZERO_ERROR;
1394 what = "udat_set2DigitYearStart";
1395 log_verbose("Trying %s on a relative date..\n", what);
2ca993e8 1396 udat_set2DigitYearStart(icudf, aDate, &subStatus);
46f4442e
A
1397 if(subStatus == expectStatus) {
1398 log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
1399 } else {
1400 log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
2ca993e8 1401 }
46f4442e
A
1402 }
1403 {
1404 /* clone works polymorphically. try it anyways */
1405 UErrorCode subStatus = U_ZERO_ERROR;
1406 UDateFormat *oth;
1407 what = "clone";
1408 log_verbose("Trying %s on a relative date..\n", what);
1409 oth = udat_clone(icudf, &subStatus);
1410 if(subStatus == U_ZERO_ERROR) {
1411 log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
1412 udat_close(oth); /* ? */
1413 } else {
1414 log_err("FAIL: didn't crash on %s, but got %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
2ca993e8 1415 }
46f4442e
A
1416 }
1417 {
1418 UErrorCode subStatus = U_ZERO_ERROR;
1419 what = "udat_get2DigitYearStart";
1420 log_verbose("Trying %s on a relative date..\n", what);
2ca993e8 1421 udat_get2DigitYearStart(icudf, &subStatus);
46f4442e
A
1422 if(subStatus == expectStatus) {
1423 log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
1424 } else {
1425 log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
2ca993e8 1426 }
46f4442e
A
1427 }
1428 {
1429 /* Now udat_toPattern works for relative date formatters, unless localized is TRUE */
1430 UErrorCode subStatus = U_ZERO_ERROR;
1431 what = "udat_toPattern";
1432 log_verbose("Trying %s on a relative date..\n", what);
2ca993e8 1433 udat_toPattern(icudf, TRUE,NULL,0, &subStatus);
46f4442e
A
1434 if(subStatus == expectStatus) {
1435 log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
1436 } else {
1437 log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
2ca993e8 1438 }
46f4442e
A
1439 }
1440 {
1441 UErrorCode subStatus = U_ZERO_ERROR;
1442 what = "udat_applyPattern";
1443 log_verbose("Trying %s on a relative date..\n", what);
2ca993e8 1444 udat_applyPattern(icudf, FALSE,tzName,-1);
46f4442e
A
1445 subStatus = U_ILLEGAL_ARGUMENT_ERROR; /* what it should be, if this took an errorcode. */
1446 if(subStatus == expectStatus) {
1447 log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
1448 } else {
1449 log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
2ca993e8 1450 }
46f4442e
A
1451 }
1452 {
51004dcb 1453 UChar erabuf[32];
46f4442e
A
1454 UErrorCode subStatus = U_ZERO_ERROR;
1455 what = "udat_getSymbols";
1456 log_verbose("Trying %s on a relative date..\n", what);
2ca993e8 1457 udat_getSymbols(icudf, UDAT_ERAS,0,erabuf,UPRV_LENGTHOF(erabuf), &subStatus);
729e4ab9
A
1458 if(subStatus == U_ZERO_ERROR) {
1459 log_verbose("Success: %s returned %s.\n", what, u_errorName(subStatus));
1460 } else {
1461 log_err("FAIL: didn't crash on %s, but got %s instead of U_ZERO_ERROR.\n", what, u_errorName(subStatus));
2ca993e8 1462 }
729e4ab9
A
1463 }
1464 {
1465 UErrorCode subStatus = U_ZERO_ERROR;
1466 UChar symbolValue = 0x0041;
1467 what = "udat_setSymbols";
1468 log_verbose("Trying %s on a relative date..\n", what);
1469 udat_setSymbols(icudf, UDAT_ERAS,0,&symbolValue,1, &subStatus); /* bogus values */
46f4442e
A
1470 if(subStatus == expectStatus) {
1471 log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
1472 } else {
1473 log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
2ca993e8 1474 }
46f4442e
A
1475 }
1476 {
1477 UErrorCode subStatus = U_ZERO_ERROR;
1478 what = "udat_countSymbols";
1479 log_verbose("Trying %s on a relative date..\n", what);
2ca993e8 1480 udat_countSymbols(icudf, UDAT_ERAS);
46f4442e
A
1481 subStatus = U_ILLEGAL_ARGUMENT_ERROR; /* should have an errorcode. */
1482 if(subStatus == expectStatus) {
1483 log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
1484 } else {
1485 log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
2ca993e8 1486 }
46f4442e 1487 }
2ca993e8 1488
46f4442e
A
1489 udat_close(icudf);
1490 } else {
729e4ab9 1491 log_data_err("FAIL: err calling udat_open() ->%s (Are you missing data?)\n", u_errorName(status));
46f4442e
A
1492 }
1493}
1494
4388f060
A
1495static const UChar skeleton_yMMMM[] = { 0x79,0x4D,0x4D,0x4D,0x4D,0 }; /* "yMMMM"; fr maps to "MMMM y", cs maps to "LLLL y" */
1496static const UChar july2008_frDefault[] = { 0x6A,0x75,0x69,0x6C,0x6C,0x65,0x74,0x20,0x32,0x30,0x30,0x38,0 }; /* "juillet 2008" */
1497static const UChar july2008_frTitle[] = { 0x4A,0x75,0x69,0x6C,0x6C,0x65,0x74,0x20,0x32,0x30,0x30,0x38,0 }; /* "Juillet 2008" sentence-begin, standalone */
1498static const UChar july2008_csDefault[] = { 0x10D,0x65,0x72,0x76,0x65,0x6E,0x65,0x63,0x20,0x32,0x30,0x30,0x38,0 }; /* "c(hacek)ervenec 2008" */
1499static 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 */
1500
1501typedef struct {
1502 const char * locale;
1503 const UChar * skeleton;
51004dcb 1504 UDisplayContext capitalizationContext;
4388f060
A
1505 const UChar * expectedFormat;
1506} TestContextItem;
1507
1508static const TestContextItem textContextItems[] = {
51004dcb 1509 { "fr", skeleton_yMMMM, UDISPCTX_CAPITALIZATION_NONE, july2008_frDefault },
4388f060 1510#if !UCONFIG_NO_BREAK_ITERATION
51004dcb
A
1511 { "fr", skeleton_yMMMM, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, july2008_frDefault },
1512 { "fr", skeleton_yMMMM, UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, july2008_frTitle },
1513 { "fr", skeleton_yMMMM, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, july2008_frDefault },
1514 { "fr", skeleton_yMMMM, UDISPCTX_CAPITALIZATION_FOR_STANDALONE, july2008_frTitle },
4388f060 1515#endif
51004dcb 1516 { "cs", skeleton_yMMMM, UDISPCTX_CAPITALIZATION_NONE, july2008_csDefault },
4388f060 1517#if !UCONFIG_NO_BREAK_ITERATION
51004dcb
A
1518 { "cs", skeleton_yMMMM, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, july2008_csDefault },
1519 { "cs", skeleton_yMMMM, UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, july2008_csTitle },
1520 { "cs", skeleton_yMMMM, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, july2008_csTitle },
1521 { "cs", skeleton_yMMMM, UDISPCTX_CAPITALIZATION_FOR_STANDALONE, july2008_csDefault },
4388f060 1522#endif
51004dcb 1523 { NULL, NULL, (UDisplayContext)0, NULL }
4388f060
A
1524};
1525
57a6839d
A
1526static const UChar today_enDefault[] = { 0x74,0x6F,0x64,0x61,0x79,0 }; /* "today" */
1527static const UChar today_enTitle[] = { 0x54,0x6F,0x64,0x61,0x79,0 }; /* "Today" sentence-begin, uiListOrMenu, standalone */
1528static const UChar yesterday_enDefault[] = { 0x79,0x65,0x73,0x74,0x65,0x72,0x64,0x61,0x79,0 }; /* "yesterday" */
1529static const UChar yesterday_enTitle[] = { 0x59,0x65,0x73,0x74,0x65,0x72,0x64,0x61,0x79,0 }; /* "Yesterday" sentence-begin, uiListOrMenu, standalone */
1530static const UChar today_nbDefault[] = { 0x69,0x20,0x64,0x61,0x67,0 }; /* "i dag" */
1531static const UChar today_nbTitle[] = { 0x49,0x20,0x64,0x61,0x67,0 }; /* "I dag" sentence-begin, standalone */
1532static const UChar yesterday_nbDefault[] = { 0x69,0x20,0x67,0xE5,0x72,0 };
1533static const UChar yesterday_nbTitle[] = { 0x49,0x20,0x67,0xE5,0x72,0 };
1534
1535typedef struct {
1536 const char * locale;
1537 UDisplayContext capitalizationContext;
1538 const UChar * expectedFormatToday;
1539 const UChar * expectedFormatYesterday;
1540} TestRelativeContextItem;
1541
1542static const TestRelativeContextItem textContextRelativeItems[] = {
1543 { "en", UDISPCTX_CAPITALIZATION_NONE, today_enDefault, yesterday_enDefault },
1544#if !UCONFIG_NO_BREAK_ITERATION
1545 { "en", UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, today_enDefault, yesterday_enDefault },
1546 { "en", UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, today_enTitle, yesterday_enTitle },
1547 { "en", UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, today_enTitle, yesterday_enTitle },
1548 { "en", UDISPCTX_CAPITALIZATION_FOR_STANDALONE, today_enTitle, yesterday_enTitle },
1549#endif
1550 { "nb", UDISPCTX_CAPITALIZATION_NONE, today_nbDefault, yesterday_nbDefault },
1551#if !UCONFIG_NO_BREAK_ITERATION
1552 { "nb", UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, today_nbDefault, yesterday_nbDefault },
1553 { "nb", UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, today_nbTitle, yesterday_nbTitle },
1554 { "nb", UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, today_nbDefault, yesterday_nbDefault },
1555 { "nb", UDISPCTX_CAPITALIZATION_FOR_STANDALONE, today_nbTitle, yesterday_nbTitle },
1556#endif
1557 { NULL, (UDisplayContext)0, NULL, NULL }
1558};
1559
a62d09fc
A
1560static const UChar january_esDefault[] = { 0x65,0x6E,0x65,0x72,0x6F,0 }; /* "enero" */
1561static const UChar january_esTitle[] = { 0x45,0x6E,0x65,0x72,0x6F,0 }; /* "Enero */
1562static const UChar monday_daDefault[] = { 0x6D,0x61,0x6E,0x64,0x61,0x67,0 }; /* "mandag" */
1563static const UChar monday_daTitle[] = { 0x4D,0x61,0x6E,0x64,0x61,0x67,0 }; /* "Mandag */
1564
1565typedef struct {
1566 const char * locale;
1567 UDateFormatSymbolType type;
1568 int32_t index;
1569 UDisplayContext capitalizationContext;
1570 const UChar * expectedFormat;
1571} TestSymbolContextItem;
1572
1573static const TestSymbolContextItem testContextSymbolItems[] = {
1574 { "es", UDAT_MONTHS, 0, UDISPCTX_CAPITALIZATION_NONE, january_esDefault },
1575#if !UCONFIG_NO_BREAK_ITERATION
1576 { "es", UDAT_MONTHS, 0, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, january_esDefault },
1577 { "es", UDAT_MONTHS, 0, UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, january_esTitle },
1578 { "es", UDAT_MONTHS, 0, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, january_esTitle },
1579 { "es", UDAT_MONTHS, 0, UDISPCTX_CAPITALIZATION_FOR_STANDALONE, january_esTitle },
1580#endif
1581 { "da", UDAT_WEEKDAYS, 2, UDISPCTX_CAPITALIZATION_NONE, monday_daDefault },
1582#if !UCONFIG_NO_BREAK_ITERATION
1583 { "da", UDAT_WEEKDAYS, 2, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, monday_daDefault },
1584 { "da", UDAT_WEEKDAYS, 2, UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, monday_daTitle },
1585 { "da", UDAT_WEEKDAYS, 2, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, monday_daDefault },
1586 { "da", UDAT_WEEKDAYS, 2, UDISPCTX_CAPITALIZATION_FOR_STANDALONE, monday_daDefault },
1587#endif
1588 { NULL, (UDateFormatSymbolType)0, 0, (UDisplayContext)0, NULL }
1589};
1590
57a6839d
A
1591static const UChar zoneGMT[] = { 0x47,0x4D,0x54,0 }; /* "GMT" */
1592static const UDate july022008 = 1215000000000.0;
4388f060
A
1593enum { kUbufMax = 64, kBbufMax = 3*kUbufMax };
1594
1595static void TestContext(void) {
57a6839d
A
1596 const TestContextItem* textContextItemPtr;
1597 const TestRelativeContextItem* textRelContextItemPtr;
a62d09fc
A
1598 const TestSymbolContextItem* testSymContextItemPtr;
1599
57a6839d 1600 for (textContextItemPtr = textContextItems; textContextItemPtr->locale != NULL; ++textContextItemPtr) {
4388f060 1601 UErrorCode status = U_ZERO_ERROR;
57a6839d
A
1602 UDateTimePatternGenerator* udtpg = udatpg_open(textContextItemPtr->locale, &status);
1603 if ( U_SUCCESS(status) ) {
1604 UChar ubuf[kUbufMax];
1605 int32_t len = udatpg_getBestPattern(udtpg, textContextItemPtr->skeleton, -1, ubuf, kUbufMax, &status);
1606 if ( U_SUCCESS(status) ) {
1607 UDateFormat* udfmt = udat_open(UDAT_PATTERN, UDAT_PATTERN, textContextItemPtr->locale, zoneGMT, -1, ubuf, len, &status);
1608 if ( U_SUCCESS(status) ) {
51004dcb 1609 udat_setContext(udfmt, textContextItemPtr->capitalizationContext, &status);
57a6839d 1610 if ( U_SUCCESS(status) ) {
51004dcb 1611 UDisplayContext getContext;
4388f060
A
1612 len = udat_format(udfmt, july022008, ubuf, kUbufMax, NULL, &status);
1613 if ( U_FAILURE(status) ) {
1614 log_err("FAIL: udat_format for locale %s, capitalizationContext %d, status %s\n",
1615 textContextItemPtr->locale, (int)textContextItemPtr->capitalizationContext, u_errorName(status) );
1616 status = U_ZERO_ERROR;
1617 } else if (u_strncmp(ubuf, textContextItemPtr->expectedFormat, kUbufMax) != 0) {
1618 char bbuf1[kBbufMax];
1619 char bbuf2[kBbufMax];
1620 log_err("FAIL: udat_format for locale %s, capitalizationContext %d, expected %s, got %s\n",
1621 textContextItemPtr->locale, (int)textContextItemPtr->capitalizationContext,
1622 u_austrncpy(bbuf1,textContextItemPtr->expectedFormat,kUbufMax), u_austrncpy(bbuf2,ubuf,kUbufMax) );
1623 }
51004dcb 1624 getContext = udat_getContext(udfmt, UDISPCTX_TYPE_CAPITALIZATION, &status);
4388f060 1625 if ( U_FAILURE(status) ) {
51004dcb 1626 log_err("FAIL: udat_getContext for locale %s, capitalizationContext %d, status %s\n",
4388f060 1627 textContextItemPtr->locale, (int)textContextItemPtr->capitalizationContext, u_errorName(status) );
51004dcb
A
1628 } else if (getContext != textContextItemPtr->capitalizationContext) {
1629 log_err("FAIL: udat_getContext for locale %s, capitalizationContext %d, got context %d\n",
1630 textContextItemPtr->locale, (int)textContextItemPtr->capitalizationContext, (int)getContext );
4388f060 1631 }
57a6839d
A
1632 } else {
1633 log_err("FAIL: udat_setContext for locale %s, capitalizationContext %d, status %s\n",
1634 textContextItemPtr->locale, (int)textContextItemPtr->capitalizationContext, u_errorName(status) );
4388f060 1635 }
57a6839d
A
1636 udat_close(udfmt);
1637 } else {
1638 log_data_err("FAIL: udat_open for locale %s, status %s\n", textContextItemPtr->locale, u_errorName(status) );
4388f060 1639 }
57a6839d
A
1640 } else {
1641 log_err("FAIL: udatpg_getBestPattern for locale %s, status %s\n", textContextItemPtr->locale, u_errorName(status) );
4388f060 1642 }
57a6839d
A
1643 udatpg_close(udtpg);
1644 } else {
1645 log_data_err("FAIL: udatpg_open for locale %s, status %s\n", textContextItemPtr->locale, u_errorName(status) );
1646 }
1647 }
1648 for (textRelContextItemPtr = textContextRelativeItems; textRelContextItemPtr->locale != NULL; ++textRelContextItemPtr) {
1649 UErrorCode status = U_ZERO_ERROR;
1650 UCalendar* ucal = ucal_open(zoneGMT, -1, "root", UCAL_GREGORIAN, &status);
1651 if ( U_SUCCESS(status) ) {
1652 UDateFormat* udfmt = udat_open(UDAT_NONE, UDAT_LONG_RELATIVE, textRelContextItemPtr->locale, zoneGMT, -1, NULL, 0, &status);
1653 if ( U_SUCCESS(status) ) {
1654 udat_setContext(udfmt, textRelContextItemPtr->capitalizationContext, &status);
1655 if ( U_SUCCESS(status) ) {
1656 UDate yesterday, today = ucal_getNow();
1657 UChar ubuf[kUbufMax];
1658 char bbuf1[kBbufMax];
1659 char bbuf2[kBbufMax];
1660 int32_t len = udat_format(udfmt, today, ubuf, kUbufMax, NULL, &status);
1661 (void)len;
1662 if ( U_FAILURE(status) ) {
1663 log_err("FAIL: udat_format today for locale %s, capitalizationContext %d, status %s\n",
1664 textRelContextItemPtr->locale, (int)textRelContextItemPtr->capitalizationContext, u_errorName(status) );
1665 } else if (u_strncmp(ubuf, textRelContextItemPtr->expectedFormatToday, kUbufMax) != 0) {
1666 log_err("FAIL: udat_format today for locale %s, capitalizationContext %d, expected %s, got %s\n",
1667 textRelContextItemPtr->locale, (int)textRelContextItemPtr->capitalizationContext,
1668 u_austrncpy(bbuf1,textRelContextItemPtr->expectedFormatToday,kUbufMax), u_austrncpy(bbuf2,ubuf,kUbufMax) );
1669 }
1670 status = U_ZERO_ERROR;
1671 ucal_setMillis(ucal, today, &status);
1672 ucal_add(ucal, UCAL_DATE, -1, &status);
1673 yesterday = ucal_getMillis(ucal, &status);
1674 if ( U_SUCCESS(status) ) {
1675 len = udat_format(udfmt, yesterday, ubuf, kUbufMax, NULL, &status);
1676 if ( U_FAILURE(status) ) {
1677 log_err("FAIL: udat_format yesterday for locale %s, capitalizationContext %d, status %s\n",
1678 textRelContextItemPtr->locale, (int)textRelContextItemPtr->capitalizationContext, u_errorName(status) );
1679 } else if (u_strncmp(ubuf, textRelContextItemPtr->expectedFormatYesterday, kUbufMax) != 0) {
1680 log_err("FAIL: udat_format yesterday for locale %s, capitalizationContext %d, expected %s, got %s\n",
1681 textRelContextItemPtr->locale, (int)textRelContextItemPtr->capitalizationContext,
1682 u_austrncpy(bbuf1,textRelContextItemPtr->expectedFormatYesterday,kUbufMax), u_austrncpy(bbuf2,ubuf,kUbufMax) );
1683 }
1684 }
1685 } else {
1686 log_err("FAIL: udat_setContext relative for locale %s, capitalizationContext %d, status %s\n",
1687 textRelContextItemPtr->locale, (int)textRelContextItemPtr->capitalizationContext, u_errorName(status) );
1688 }
1689 udat_close(udfmt);
1690 } else {
1691 log_data_err("FAIL: udat_open relative for locale %s, status %s\n", textRelContextItemPtr->locale, u_errorName(status) );
1692 }
1693 ucal_close(ucal);
1694 } else {
1695 log_data_err("FAIL: ucal_open for locale root, status %s\n", u_errorName(status) );
4388f060
A
1696 }
1697 }
a62d09fc
A
1698
1699 for (testSymContextItemPtr = testContextSymbolItems; testSymContextItemPtr->locale != NULL; ++testSymContextItemPtr) {
1700 UErrorCode status = U_ZERO_ERROR;
1701 UDateFormat* udfmt = udat_open(UDAT_MEDIUM, UDAT_FULL, testSymContextItemPtr->locale, zoneGMT, -1, NULL, 0, &status);
1702 if ( U_SUCCESS(status) ) {
1703 udat_setContext(udfmt, testSymContextItemPtr->capitalizationContext, &status);
1704 if ( U_SUCCESS(status) ) {
1705 UChar ubuf[kUbufMax];
1706 int32_t len = udat_getSymbols(udfmt, testSymContextItemPtr->type, testSymContextItemPtr->index, ubuf, kUbufMax, &status);
1707 if ( U_FAILURE(status) ) {
1708 log_err("FAIL: udat_getSymbols for locale %s, capitalizationContext %d, status %s\n",
1709 testSymContextItemPtr->locale, (int)testSymContextItemPtr->capitalizationContext, u_errorName(status) );
1710 } else if (u_strncmp(ubuf, testSymContextItemPtr->expectedFormat, kUbufMax) != 0) {
1711 char bbuf1[kBbufMax];
1712 char bbuf2[kBbufMax];
1713 log_err("FAIL: udat_getSymbols for locale %s, capitalizationContext %d, expected %s, got %s\n",
1714 testSymContextItemPtr->locale, (int)testSymContextItemPtr->capitalizationContext,
1715 u_austrncpy(bbuf1,testSymContextItemPtr->expectedFormat,kUbufMax), u_austrncpy(bbuf2,ubuf,kUbufMax) );
1716 }
1717 } else {
1718 log_err("FAIL: udat_setContext std for locale %s, capitalizationContext %d, status %s\n",
1719 testSymContextItemPtr->locale, (int)testSymContextItemPtr->capitalizationContext, u_errorName(status) );
1720 }
1721 udat_close(udfmt);
1722 } else {
1723 log_data_err("FAIL: udat_open std for locale %s, status %s\n", testSymContextItemPtr->locale, u_errorName(status) );
1724 }
1725 }
4388f060
A
1726}
1727
b331163b 1728
2ca993e8 1729// overrideNumberFormat[i][0] is to tell which field to set,
b331163b 1730// overrideNumberFormat[i][1] is the expected result
2ca993e8 1731static const char * overrideNumberFormat[][2] = {
b331163b
A
1732 {"", "\\u521D\\u4E03 \\u521D\\u4E8C"},
1733 {"d", "07 \\u521D\\u4E8C"},
1734 {"do", "07 \\u521D\\u4E8C"},
1735 {"Md", "\\u521D\\u4E03 \\u521D\\u4E8C"},
1736 {"MdMMd", "\\u521D\\u4E03 \\u521D\\u4E8C"},
1737 {"mixed", "\\u521D\\u4E03 \\u521D\\u4E8C"}
1738};
1739
1740static void TestOverrideNumberFormat(void) {
1741 UErrorCode status = U_ZERO_ERROR;
1742 UChar pattern[50];
1743 UChar expected[50];
1744 UChar fields[50];
1745 char bbuf1[kBbufMax];
1746 char bbuf2[kBbufMax];
1747 const char* localeString = "zh@numbers=hanidays";
1748 UDateFormat* fmt;
1749 const UNumberFormat* getter_result;
1750 int32_t i;
1751
1752 u_uastrcpy(fields, "d");
1753 u_uastrcpy(pattern,"MM d");
1754
1755 fmt=udat_open(UDAT_PATTERN, UDAT_PATTERN, "en_US", zoneGMT, -1, pattern, u_strlen(pattern), &status);
1756 if (!assertSuccess("udat_open()", &status)) {
1757 return;
1758 }
1759
1760 // loop 5 times to check getter/setter
1761 for (i = 0; i < 5; i++){
3d1f044b 1762 status = U_ZERO_ERROR;
b331163b
A
1763 UNumberFormat* overrideFmt;
1764 overrideFmt = unum_open(UNUM_DEFAULT, NULL, 0, localeString, NULL, &status);
1765 assertSuccess("unum_open()", &status);
1766 udat_adoptNumberFormatForFields(fmt, fields, overrideFmt, &status);
1767 overrideFmt = NULL; // no longer valid
1768 assertSuccess("udat_setNumberFormatForField()", &status);
1769
f3c0d7a5 1770 getter_result = udat_getNumberFormatForField(fmt, 0x0064 /*'d'*/);
b331163b
A
1771 if(getter_result == NULL) {
1772 log_err("FAIL: udat_getNumberFormatForField did not return a valid pointer\n");
1773 }
1774 }
1775 {
3d1f044b 1776 status = U_ZERO_ERROR;
b331163b
A
1777 UNumberFormat* overrideFmt;
1778 overrideFmt = unum_open(UNUM_DEFAULT, NULL, 0, localeString, NULL, &status);
1779 assertSuccess("unum_open()", &status);
3d1f044b
A
1780 if (U_SUCCESS(status)) {
1781 udat_setNumberFormat(fmt, overrideFmt); // test the same override NF will not crash
1782 }
b331163b
A
1783 unum_close(overrideFmt);
1784 }
1785 udat_close(fmt);
2ca993e8 1786
b331163b 1787 for (i=0; i<UPRV_LENGTHOF(overrideNumberFormat); i++){
3d1f044b 1788 status = U_ZERO_ERROR;
b331163b
A
1789 UChar ubuf[kUbufMax];
1790 UDateFormat* fmt2;
1791 UNumberFormat* overrideFmt2;
1792
1793 fmt2 =udat_open(UDAT_PATTERN, UDAT_PATTERN,"en_US", zoneGMT, -1, pattern, u_strlen(pattern), &status);
1794 assertSuccess("udat_open() with en_US", &status);
1795
1796 overrideFmt2 = unum_open(UNUM_DEFAULT, NULL, 0, localeString, NULL, &status);
1797 assertSuccess("unum_open() in loop", &status);
1798
3d1f044b
A
1799 if (U_FAILURE(status)) {
1800 continue;
1801 }
1802
b331163b
A
1803 u_uastrcpy(fields, overrideNumberFormat[i][0]);
1804 u_unescape(overrideNumberFormat[i][1], expected, UPRV_LENGTHOF(expected));
1805
1806 if ( strcmp(overrideNumberFormat[i][0], "") == 0 ) { // use the one w/o field
1807 udat_adoptNumberFormat(fmt2, overrideFmt2);
1808 } else if ( strcmp(overrideNumberFormat[i][0], "mixed") == 0 ) { // set 1 field at first but then full override, both(M & d) should be override
1809 const char* singleLocale = "en@numbers=hebr";
1810 UNumberFormat* singleOverrideFmt;
1811 u_uastrcpy(fields, "d");
1812
1813 singleOverrideFmt = unum_open(UNUM_DEFAULT, NULL, 0, singleLocale, NULL, &status);
1814 assertSuccess("unum_open() in mixed", &status);
1815
1816 udat_adoptNumberFormatForFields(fmt2, fields, singleOverrideFmt, &status);
1817 assertSuccess("udat_setNumberFormatForField() in mixed", &status);
1818
1819 udat_adoptNumberFormat(fmt2, overrideFmt2);
1820 } else if ( strcmp(overrideNumberFormat[i][0], "do") == 0 ) { // o is an invalid field
1821 udat_adoptNumberFormatForFields(fmt2, fields, overrideFmt2, &status);
1822 if(status == U_INVALID_FORMAT_ERROR) {
1823 udat_close(fmt2);
1824 status = U_ZERO_ERROR;
1825 continue;
1826 }
1827 } else {
1828 udat_adoptNumberFormatForFields(fmt2, fields, overrideFmt2, &status);
1829 assertSuccess("udat_setNumberFormatForField() in loop", &status);
1830 }
1831
1832 udat_format(fmt2, july022008, ubuf, kUbufMax, NULL, &status);
1833 assertSuccess("udat_format() july022008", &status);
1834
2ca993e8 1835 if (u_strncmp(ubuf, expected, kUbufMax) != 0)
b331163b
A
1836 log_err("fail: udat_format for locale, expected %s, got %s\n",
1837 u_austrncpy(bbuf1,expected,kUbufMax), u_austrncpy(bbuf2,ubuf,kUbufMax) );
1838
1839 udat_close(fmt2);
1840 }
1841}
1842
1843/*
1844 * Ticket #11523
1845 * udat_parse and udat_parseCalendar should have the same error code when given the same invalid input.
1846 */
1847static void TestParseErrorReturnValue(void) {
1848 UErrorCode status = U_ZERO_ERROR;
1849 UErrorCode expectStatus = U_PARSE_ERROR;
1850 UDateFormat* df;
1851 UCalendar* cal;
1852
1853 df = udat_open(UDAT_DEFAULT, UDAT_DEFAULT, NULL, NULL, -1, NULL, -1, &status);
1854 if (!assertSuccessCheck("udat_open()", &status, TRUE)) {
1855 return;
1856 }
1857
1858 cal = ucal_open(NULL, 0, "en_US", UCAL_GREGORIAN, &status);
1859 if (!assertSuccess("ucal_open()", &status)) {
1860 return;
1861 }
1862
1863 udat_parse(df, NULL, -1, NULL, &status);
1864 if (status != expectStatus) {
1865 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));
1866 }
1867
1868 status = U_ZERO_ERROR;
1869 udat_parseCalendar(df, cal, NULL, -1, NULL, &status);
1870 if (status != expectStatus) {
1871 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));
1872 }
1873
1874 ucal_close(cal);
1875 udat_close(df);
1876}
1877
1878/*
1879 * Ticket #11553
1880 * Test new udat_formatForFields, udat_formatCalendarForFields (and UFieldPositionIterator)
1881 */
1882static const char localeForFields[] = "en_US";
1883/* zoneGMT[]defined above */
1884static const UDate date2015Feb25 = 1424841000000.0; /* Wednesday, February 25, 2015 at 5:10:00 AM GMT */
f3c0d7a5 1885static const UChar patNoFields[] = { 0x0027, 0x0078, 0x0078, 0x0078, 0x0027, 0 }; /* "'xxx'" */
b331163b
A
1886
1887typedef struct {
1888 int32_t field;
1889 int32_t beginPos;
1890 int32_t endPos;
1891} FieldsData;
1892static const FieldsData expectedFields[] = {
1893 { UDAT_DAY_OF_WEEK_FIELD /* 9*/, 0, 9 },
1894 { UDAT_MONTH_FIELD /* 2*/, 11, 19 },
1895 { UDAT_DATE_FIELD /* 3*/, 20, 22 },
1896 { UDAT_YEAR_FIELD /* 1*/, 24, 28 },
1897 { UDAT_HOUR1_FIELD /*15*/, 32, 33 },
2ca993e8
A
1898#if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
1899 { UDAT_TIME_SEPARATOR_FIELD /*35*/, 33, 34 },
1900#endif
b331163b 1901 { UDAT_MINUTE_FIELD /* 6*/, 34, 36 },
2ca993e8
A
1902#if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
1903 { UDAT_TIME_SEPARATOR_FIELD /*35*/, 36, 37 },
1904#endif
b331163b
A
1905 { UDAT_SECOND_FIELD /* 7*/, 37, 39 },
1906 { UDAT_AM_PM_FIELD /*14*/, 40, 42 },
1907 { UDAT_TIMEZONE_FIELD /*17*/, 43, 46 },
1908 { -1, -1, -1 },
1909};
1910
1911enum {kUBufFieldsLen = 128, kBBufFieldsLen = 256 };
1912
1913static void TestFormatForFields(void) {
1914 UErrorCode status = U_ZERO_ERROR;
1915 UFieldPositionIterator* fpositer = ufieldpositer_open(&status);
1916 if ( U_FAILURE(status) ) {
1917 log_err("ufieldpositer_open fails, status %s\n", u_errorName(status));
1918 } else {
1919 UDateFormat* udfmt = udat_open(UDAT_LONG, UDAT_FULL, localeForFields, zoneGMT, -1, NULL, 0, &status);
1920 UCalendar* ucal = ucal_open(zoneGMT, -1, localeForFields, UCAL_DEFAULT, &status);
1921 if ( U_FAILURE(status) ) {
1922 log_data_err("udat_open or ucal_open fails for locale %s, status %s (Are you missing data?)\n", localeForFields, u_errorName(status));
1923 } else {
1924 int32_t ulen, field, beginPos, endPos;
1925 UChar ubuf[kUBufFieldsLen];
1926 const FieldsData * fptr;
2ca993e8 1927
b331163b
A
1928 status = U_ZERO_ERROR;
1929 ulen = udat_formatForFields(udfmt, date2015Feb25, ubuf, kUBufFieldsLen, fpositer, &status);
1930 if ( U_FAILURE(status) ) {
1931 log_err("udat_formatForFields fails, status %s\n", u_errorName(status));
1932 } else {
1933 for (fptr = expectedFields; ; fptr++) {
1934 field = ufieldpositer_next(fpositer, &beginPos, &endPos);
1935 if (field != fptr->field || (field >= 0 && (beginPos != fptr->beginPos || endPos != fptr->endPos))) {
1936 if (fptr->field >= 0) {
1937 log_err("udat_formatForFields as \"%s\"; expect field %d range %d-%d, get field %d range %d-%d\n",
1938 aescstrdup(ubuf, ulen), fptr->field, fptr->beginPos, fptr->endPos, field, beginPos, endPos);
1939 } else {
1940 log_err("udat_formatForFields as \"%s\"; expect field < 0, get field %d range %d-%d\n",
1941 aescstrdup(ubuf, ulen), field, beginPos, endPos);
1942 }
1943 break;
1944 }
1945 if (field < 0) {
1946 break;
1947 }
1948 }
1949 }
2ca993e8 1950
b331163b
A
1951 ucal_setMillis(ucal, date2015Feb25, &status);
1952 status = U_ZERO_ERROR;
1953 ulen = udat_formatCalendarForFields(udfmt, ucal, ubuf, kUBufFieldsLen, fpositer, &status);
1954 if ( U_FAILURE(status) ) {
1955 log_err("udat_formatCalendarForFields fails, status %s\n", u_errorName(status));
1956 } else {
1957 for (fptr = expectedFields; ; fptr++) {
1958 field = ufieldpositer_next(fpositer, &beginPos, &endPos);
1959 if (field != fptr->field || (field >= 0 && (beginPos != fptr->beginPos || endPos != fptr->endPos))) {
1960 if (fptr->field >= 0) {
1961 log_err("udat_formatFudat_formatCalendarForFieldsorFields as \"%s\"; expect field %d range %d-%d, get field %d range %d-%d\n",
1962 aescstrdup(ubuf, ulen), fptr->field, fptr->beginPos, fptr->endPos, field, beginPos, endPos);
1963 } else {
1964 log_err("udat_formatCalendarForFields as \"%s\"; expect field < 0, get field %d range %d-%d\n",
1965 aescstrdup(ubuf, ulen), field, beginPos, endPos);
1966 }
1967 break;
1968 }
1969 if (field < 0) {
1970 break;
1971 }
1972 }
1973 }
1974
f3c0d7a5
A
1975 udat_applyPattern(udfmt, FALSE, patNoFields, -1);
1976 status = U_ZERO_ERROR;
1977 ulen = udat_formatForFields(udfmt, date2015Feb25, ubuf, kUBufFieldsLen, fpositer, &status);
1978 if ( U_FAILURE(status) ) {
1979 log_err("udat_formatForFields with no-field pattern fails, status %s\n", u_errorName(status));
1980 } else {
1981 field = ufieldpositer_next(fpositer, &beginPos, &endPos);
1982 if (field >= 0) {
1983 log_err("udat_formatForFields with no-field pattern as \"%s\"; expect field < 0, get field %d range %d-%d\n",
1984 aescstrdup(ubuf, ulen), field, beginPos, endPos);
1985 }
1986 }
1987
b331163b
A
1988 ucal_close(ucal);
1989 udat_close(udfmt);
1990 }
1991 ufieldpositer_close(fpositer);
1992 }
1993}
1994
1546d4af
A
1995static void TestForceGannenNumbering(void) {
1996 UErrorCode status;
1997 const char* locID = "ja_JP@calendar=japanese";
1998 UDate refDate = 600336000000.0; // 1989 Jan 9 Monday = Heisei 1
1999 const UChar* testSkeleton = u"yMMMd";
2000
2001 // Test Gannen year forcing
2002 status = U_ZERO_ERROR;
2003 UDateTimePatternGenerator* dtpgen = udatpg_open(locID, &status);
2004 if (U_FAILURE(status)) {
2005 log_data_err("Fail in udatpg_open locale %s: %s", locID, u_errorName(status));
2006 } else {
2007 UChar pattern[kUbufMax];
2008 int32_t patlen = udatpg_getBestPattern(dtpgen, testSkeleton, -1, pattern, kUbufMax, &status);
2009 if (U_FAILURE(status)) {
2010 log_data_err("Fail in udatpg_getBestPattern locale %s: %s", locID, u_errorName(status));
2011 } else {
2012 UDateFormat *testFmt = udat_open(UDAT_PATTERN, UDAT_PATTERN, locID, NULL, 0, pattern, patlen, &status);
2013 if (U_FAILURE(status)) {
2014 log_data_err("Fail in udat_open locale %s: %s", locID, u_errorName(status));
2015 } else {
2016 UChar testString[kUbufMax];
2017 int32_t testStrLen = udat_format(testFmt, refDate, testString, kUbufMax, NULL, &status);
2018 if (U_FAILURE(status)) {
2019 log_err("Fail in udat_format locale %s: %s", locID, u_errorName(status));
2020 } else if (testStrLen < 3 || testString[2] != 0x5143) {
2021 char bbuf[kBbufMax];
3d1f044b
A
2022 u_austrncpy(bbuf, testString, testStrLen);
2023 log_err("Formatting year 1 as Gannen, got%s but expected 3rd char to be 0x5143", bbuf);
1546d4af
A
2024 }
2025 udat_close(testFmt);
2026 }
2027 }
2028 udatpg_close(dtpgen);
2029 }
2030}
2031
2ca993e8
A
2032/* defined above
2033static const UChar zoneGMT[] = { 0x47,0x4D,0x54,0 }; // "GMT"
2034static const UDate date2015Feb25 = 1424841000000.0; // Wednesday, February 25, 2015 at 5:10:00 AM GMT
2035*/
2036
2037typedef struct {
2038 const char * locale;
2039 UDateFormatStyle dateStyle;
2040 UDateFormatStyle timeStyle;
2041 const char * expect; /* for zoneGMT and date2015Feb25 */
2042} StandardPatternItem;
2043
2044static const StandardPatternItem stdPatternItems[] = {
a62d09fc 2045 { "en_JP", UDAT_MEDIUM, UDAT_SHORT, "Feb 25, 2015 5:10" },
9f1b1155
A
2046 { "en_CN", UDAT_MEDIUM, UDAT_SHORT, "Feb 25, 2015 at 5:10 AM" },
2047 { "en_TW", UDAT_MEDIUM, UDAT_SHORT, "Feb 25, 2015 at 5:10 AM" },
3d1f044b
A
2048 { "en_KR", UDAT_MEDIUM, UDAT_SHORT, "Feb 25, 2015 5:10 AM" },
2049 // Add tests for Apple <rdar://problem/51014042>; currently no specific locales for these
340931cb 2050 { "en_AZ", UDAT_MEDIUM, UDAT_SHORT, "25 Feb 2015 at 05:10" }, // en uses h, AZ Azerbaijanvpref cycle H
3d1f044b
A
2051 { "fr_US", UDAT_NONE, UDAT_SHORT, "5:10 AM" }, // fr uses H, US pref cycle h
2052 { "rkt", UDAT_NONE, UDAT_SHORT, "5:10 AM" }, // rkt (no locale) => rkt_Beng_BD, BD pref cycle h unlike root H
2053 // Add tests for Apple <rdar://problem/47494884>
2054 { "ur_PK", UDAT_MEDIUM, UDAT_SHORT, "25 \\u0641\\u0631\\u0648\\u060C 2015 5:10 \\u0642.\\u062F." },
2055 { "ur_IN", UDAT_MEDIUM, UDAT_SHORT, "\\u06F2\\u06F5 \\u0641\\u0631\\u0648\\u060C \\u06F2\\u06F0\\u06F1\\u06F5 \\u06F5:\\u06F1\\u06F0 \\u0642.\\u062F." },
2056 { "ur_Arab", UDAT_MEDIUM, UDAT_SHORT, "25 \\u0641\\u0631\\u0648\\u060C 2015 5:10 \\u0642.\\u062F." },
2057 { "ur_Aran", UDAT_MEDIUM, UDAT_SHORT, "25 \\u0641\\u0631\\u0648\\u060C 2015 5:10 \\u0642.\\u062F." },
2058 { "ur_Arab_PK", UDAT_MEDIUM, UDAT_SHORT, "25 \\u0641\\u0631\\u0648\\u060C 2015 5:10 \\u0642.\\u062F." },
2059 { "ur_Aran_PK", UDAT_MEDIUM, UDAT_SHORT, "25 \\u0641\\u0631\\u0648\\u060C 2015 5:10 \\u0642.\\u062F." },
2060 { "ur_Arab_IN", UDAT_MEDIUM, UDAT_SHORT, "\\u06F2\\u06F5 \\u0641\\u0631\\u0648\\u060C \\u06F2\\u06F0\\u06F1\\u06F5 \\u06F5:\\u06F1\\u06F0 \\u0642.\\u062F." },
2061 { "ur_Aran_IN", UDAT_MEDIUM, UDAT_SHORT, "\\u06F2\\u06F5 \\u0641\\u0631\\u0648\\u060C \\u06F2\\u06F0\\u06F1\\u06F5 \\u06F5:\\u06F1\\u06F0 \\u0642.\\u062F." },
340931cb
A
2062 // Add tests for Apple <rdar://problem/59940681>
2063 { "zh@calendar=buddhist", UDAT_NONE, UDAT_MEDIUM, "\\u4E0A\\u53485:10:00" },
2064 { "zh@calendar=buddhist", UDAT_NONE, UDAT_SHORT, "\\u4E0A\\u53485:10" },
2065 { "zh_Hant@calendar=buddhist", UDAT_NONE, UDAT_MEDIUM, "\\u4E0A\\u53485:10:00" },
2066 { "zh_Hant@calendar=buddhist", UDAT_NONE, UDAT_SHORT, "\\u4E0A\\u53485:10" },
2067 // Add tests for Apple <rdar://problem/43349838>
2068 { "pl", UDAT_FULL, UDAT_SHORT, "\\u015Broda, 25 lutego 2015 o 05:10" },
2069 { "pl", UDAT_LONG, UDAT_SHORT, "25 lutego 2015 o 05:10" },
2070 { "pl", UDAT_MEDIUM, UDAT_SHORT, "25.02.2015 o 05:10" },
2071 { "pl", UDAT_SHORT, UDAT_SHORT, "25.02.2015, 05:10" },
2072 // Add tests for Apple <rdar://65019572>
2073 { "iu_Latn_CA", UDAT_LONG, UDAT_SHORT, "2015 M02 25 5:10 AM" },
2074 { "iu_CA", UDAT_LONG, UDAT_SHORT, "\\u1555\\u155d\\u1557\\u140a\\u14d5 25, 2015 5:10 am" },
2075 { "nv", UDAT_LONG, UDAT_SHORT, "February 25, 2015 at 5:10 AM" },
2ca993e8
A
2076 { NULL, (UDateFormatStyle)0, (UDateFormatStyle)0, NULL } /* terminator */
2077};
2078
2079enum { kUbufStdMax = 64, kBbufStdMax = 3*kUbufStdMax };
2080
2081static void TestStandardPatterns(void) {
2082 const StandardPatternItem* itemPtr;
2083 for (itemPtr = stdPatternItems; itemPtr->locale != NULL; itemPtr++) {
2084 UErrorCode status = U_ZERO_ERROR;
2085 UDateFormat* udfmt = udat_open(itemPtr->timeStyle, itemPtr->dateStyle, itemPtr->locale, zoneGMT, -1, NULL, 0, &status);
2086 if ( U_FAILURE(status) ) {
2087 log_err("udat_open(%d, %d, \"%s\",...) fails, status %s\n",
2088 (int)itemPtr->timeStyle, (int)itemPtr->dateStyle, itemPtr->locale, u_errorName(status));
2089 } else {
2090 UChar uget[kUbufStdMax];
2091 int32_t ugetlen = udat_format(udfmt, date2015Feb25, uget, kUbufStdMax, NULL, &status);
2092 if ( U_FAILURE(status) ) {
2093 log_err("udat_format for (%d, %d, \"%s\",...) fails, status %s\n",
2094 (int)itemPtr->timeStyle, (int)itemPtr->dateStyle, itemPtr->locale, u_errorName(status));
2095 } else {
2096 UChar uexpect[kUbufStdMax];
2097 int32_t uexpectlen = u_unescape(itemPtr->expect, uexpect, kUbufStdMax);
2098 if (ugetlen != uexpectlen || u_strncmp(uget, uexpect, uexpectlen) != 0) {
2099 char bexpect[kBbufStdMax];
2100 char bget[kBbufStdMax];
2101 u_austrcpy(bexpect, uexpect);
2102 u_austrcpy(bget, uget);
2103 log_err("udat_format for (%d, %d, \"%s\",...):\n expect %s\n get %s\n",
2104 (int)itemPtr->timeStyle, (int)itemPtr->dateStyle, itemPtr->locale, bexpect, bget);
2105 }
2106 }
2107 udat_close(udfmt);
2108 }
2109 }
2110}
2111
b331163b
A
2112/* defined above
2113static const UChar zoneGMT[] = { 0x47,0x4D,0x54,0 }; // "GMT"
2114static const UDate date2015Feb25 = 1424841000000.0; // Wednesday, February 25, 2015 at 5:10:00 AM GMT
2115*/
2116static const UChar patternHmm[] = { 0x48,0x3A,0x6D,0x6D,0 }; /* "H:mm" */
2117static const UChar formattedHmm[] = { 0x35,0x3A,0x31,0x30,0 }; /* "5:10" */
2118
2119enum { kUBufOverrideSepMax = 32, kBBufOverrideSepMax = 64 };
2120
2121static void TestApplyPatnOverridesTimeSep(void) {
2122 UErrorCode status;
2123 UDateFormat* udfmt;
2124 const char *locale = "da"; /* uses period for time separator */
2125 UChar ubuf[kUBufOverrideSepMax];
2126 int32_t ulen;
2127
2128 status = U_ZERO_ERROR;
2129 udfmt = udat_open(UDAT_PATTERN, UDAT_PATTERN, locale, zoneGMT, -1, patternHmm, -1, &status);
2130 if ( U_FAILURE(status) ) {
2131 log_err("udat_open(UDAT_PATTERN, UDAT_PATTERN, \"%s\",...) fails, status %s\n", locale, u_errorName(status));
2132 } else {
2133 ulen = udat_format(udfmt, date2015Feb25, ubuf, kUBufOverrideSepMax, NULL, &status);
2134 if ( U_FAILURE(status) ) {
2135 log_err("udat_format fails for UDAT_PATTERN \"%s\", status %s\n", locale, u_errorName(status));
2136 } else if (u_strcmp(ubuf, formattedHmm) != 0) {
2137 char bbuf[kBBufOverrideSepMax];
2138 u_strToUTF8(bbuf, kBBufOverrideSepMax, NULL, ubuf, ulen, &status);
2139 log_err("udat_format fails for UDAT_PATTERN \"%s\", expected 5:10, got %s\n", locale, bbuf);
2140 }
2141 udat_close(udfmt);
2142 }
2143
2144 status = U_ZERO_ERROR;
2145 udfmt = udat_open(UDAT_SHORT, UDAT_NONE, locale, zoneGMT, -1, NULL, 0, &status);
2146 if ( U_FAILURE(status) ) {
2147 log_err("udat_open(UDAT_SHORT, UDAT_NONE, \"%s\",...) fails, status %s\n", locale, u_errorName(status));
2148 } else {
2149 udat_applyPattern(udfmt, FALSE, patternHmm, -1);
2150 ulen = udat_format(udfmt, date2015Feb25, ubuf, kUBufOverrideSepMax, NULL, &status);
2151 if ( U_FAILURE(status) ) {
2152 log_err("udat_format fails for UDAT_SHORT \"%s\" + applyPattern, status %s\n", locale, u_errorName(status));
2153 } else if (u_strcmp(ubuf, formattedHmm) != 0) {
2154 char bbuf[kBBufOverrideSepMax];
2155 u_strToUTF8(bbuf, kBBufOverrideSepMax, NULL, ubuf, ulen, &status);
2156 log_err("udat_format fails for UDAT_SHORT \"%s\" + applyPattern, expected 5:10, got %s\n", locale, bbuf);
2157 }
2158 udat_close(udfmt);
2159 }
2160
2161}
2162
2ca993e8
A
2163#define UDATE_SECOND (1000.0)
2164#define UDATE_MINUTE (60.0*UDATE_SECOND)
2165#define UDATE_HOUR (60.0*UDATE_MINUTE)
2166
2167static const double dayOffsets[] = {
2168 0.0, /* 00:00:00 */
2169 UDATE_SECOND, /* 00:00:01 */
2170 UDATE_MINUTE, /* 00:01:00 */
2171 UDATE_HOUR, /* 01:00:00 */
2172 11.0*UDATE_HOUR + 59.0*UDATE_MINUTE, /* 11:59:00 */
2173 12.0*UDATE_HOUR, /* 12:00:00 */
2174 12.0*UDATE_HOUR + UDATE_SECOND, /* 12:00:01 */
2175 12.0*UDATE_HOUR + UDATE_MINUTE, /* 12:01:00 */
2176 13.0*UDATE_HOUR, /* 13:00:00 */
2177 23.0*UDATE_HOUR + 59.0*UDATE_MINUTE, /* 23:59:00 */
2178};
2179enum { kNumDayOffsets = UPRV_LENGTHOF(dayOffsets) };
2180
2181static const char* ja12HrFmt_hm[kNumDayOffsets] = { /* aK:mm */
2182 "\\u5348\\u524D0:00", /* "午前0:00" */
2183 "\\u5348\\u524D0:00",
2184 "\\u5348\\u524D0:01",
2185 "\\u5348\\u524D1:00",
2186 "\\u5348\\u524D11:59",
2187 "\\u5348\\u5F8C0:00", /* "午後0:00" */
2188 "\\u5348\\u5F8C0:00",
2189 "\\u5348\\u5F8C0:01", /* "午後0:01" */
2190 "\\u5348\\u5F8C1:00",
2191 "\\u5348\\u5F8C11:59",
2192};
2193
2194static const char* ja12HrFmt_h[kNumDayOffsets] = { /* aK時 */
2195 "\\u5348\\u524D0\\u6642", /* "午前0時" */
2196 "\\u5348\\u524D0\\u6642",
2197 "\\u5348\\u524D0\\u6642",
2198 "\\u5348\\u524D1\\u6642",
2199 "\\u5348\\u524D11\\u6642",
2200 "\\u5348\\u5F8C0\\u6642", /* "午後0時" */
2201 "\\u5348\\u5F8C0\\u6642",
2202 "\\u5348\\u5F8C0\\u6642", /* "午後0時" */
2203 "\\u5348\\u5F8C1\\u6642",
2204 "\\u5348\\u5F8C11\\u6642",
2205};
2206typedef struct {
2207 const char* locale;
2208 const char* skeleton;
2209 const char ** expected;
2210} Test12HrFmtItem;
2211
2212static const Test12HrFmtItem test12HrFmtItems[] = {
2213 { "ja", "hm", ja12HrFmt_hm },
2214 { "ja", "h", ja12HrFmt_h },
2215 { NULL, NULL, NULL } /* terminator */
2216};
2217
2218enum { kUBufMax = 128, };
2219static void Test12HrFormats(void) {
2220 const Test12HrFmtItem* itemPtr;
2221 for (itemPtr = test12HrFmtItems; itemPtr->locale != NULL; itemPtr++) {
2222 UErrorCode status = U_ZERO_ERROR;
2223 UCalendar* ucal = ucal_open(NULL, 0, itemPtr->locale, UCAL_DEFAULT, &status);
2224 if ( U_FAILURE(status) ) {
2225 log_data_err("ucal_open fails for locale %s: status %s (Are you missing data?)\n", itemPtr->locale, u_errorName(status));
2226 } else {
2227 ucal_clear(ucal);
2228 ucal_setDateTime(ucal, 2016, UCAL_JANUARY, 1, 0, 0, 0, &status);
2229 UDate baseDate = ucal_getMillis(ucal, &status);
2230 if ( U_FAILURE(status) ) {
2231 log_err("ucal_setDateTime or ucal_getMillis fails for locale %s: status %s\n", itemPtr->locale, u_errorName(status));
2232 } else {
2233 UDateTimePatternGenerator* udatpg = udatpg_open(itemPtr->locale, &status);
2234 if ( U_FAILURE(status) ) {
2235 log_data_err("udatpg_open fails for locale %s: status %s (Are you missing data?)\n", itemPtr->locale, u_errorName(status));
2236 } else {
2237 UChar ubuf1[kUbufMax], ubuf2[kUbufMax];
2238 int32_t ulen1 = u_unescape(itemPtr->skeleton, ubuf1, kUbufMax);
2239 int32_t ulen2 = udatpg_getBestPattern(udatpg, ubuf1, ulen1, ubuf2, kUbufMax, &status);
2240 if ( U_FAILURE(status) ) {
2241 log_err("udatpg_getBestPattern fails for locale %s, skeleton %s: status %s\n",
2242 itemPtr->locale, itemPtr->skeleton, u_errorName(status));
2243 } else {
2244 UDateFormat* udat = udat_open(UDAT_PATTERN, UDAT_PATTERN, itemPtr->locale, NULL, 0, ubuf2, ulen2, &status);
2245 if ( U_FAILURE(status) ) {
2246 log_data_err("udat_open fails for locale %s, skeleton %s: status %s (Are you missing data?)\n",
2247 itemPtr->locale, itemPtr->skeleton, u_errorName(status));
2248 } else {
2249 int32_t iDayOffset;
2250 for (iDayOffset = 0; iDayOffset < kNumDayOffsets; iDayOffset++) {
2251 status = U_ZERO_ERROR;
2252 ulen1 = udat_format(udat, baseDate + dayOffsets[iDayOffset], ubuf1, kUbufMax, NULL, &status);
2253 if ( U_FAILURE(status) ) {
2254 log_err("udat_format fails for locale %s, skeleton %s, iDayOffset %d: status %s\n",
2255 itemPtr->locale, itemPtr->skeleton, iDayOffset, u_errorName(status));
2256 } else {
2257 ulen2 = u_unescape(itemPtr->expected[iDayOffset], ubuf2, kUbufMax);
2258 if (ulen1 != ulen2 || u_strncmp(ubuf1, ubuf2, ulen2) != 0) {
2259 char bbuf1[kBbufMax], bbuf2[kBbufMax];
2260 u_austrncpy(bbuf1, ubuf1, ulen1);
2261 u_austrncpy(bbuf2, ubuf2, ulen2);
2262 log_err("udat_format fails for locale %s, skeleton %s, iDayOffset %d:\n expect %s\n get %s\n",
2263 itemPtr->locale, itemPtr->skeleton, iDayOffset, bbuf2, bbuf1);
2264 }
2265 }
2266
2267 }
2268 udat_close(udat);
2269 }
2270 }
2271 udatpg_close(udatpg);
2272 }
2273 }
2274 ucal_close(ucal);
2275 }
2276 }
2277}
2278
340931cb
A
2279static const UChar* skeletons12Hr[] = {
2280 u"h",
2281 u"j",
2282 u"hm",
2283 u"jm",
2284 u"hms",
2285 u"jms",
2286 u"hmz",
2287 u"jmz",
2288 u"Ehmm",
2289 u"Ejmm",
2290 NULL
2291};
2292
2293static const UChar* patterns12Hr_zh_buddhist[] = {
2294 u"ah时",
2295 u"ah时",
2296 u"ah:mm",
2297 u"ah:mm",
2298 u"ah:mm:ss",
2299 u"ah:mm:ss",
2300 u"z ah:mm",
2301 u"z ah:mm",
2302 u"EEE ah:mm",
2303 u"EEE ah:mm",
2304 NULL
2305};
2306
2307static const UChar* patterns12Hr_zhHant_buddhist[] = {
2308 u"ah時",
2309 u"ah時",
2310 u"ah:mm",
2311 u"ah:mm",
2312 u"ah:mm:ss",
2313 u"ah:mm:ss",
2314 u"z ah:mm", // as in gregorian/generic standard, gregorian availableFormats
2315 u"z ah:mm",
2316 u"EEE ah:mm",
2317 u"EEE ah:mm",
2318 NULL
2319};
2320
2321typedef struct {
2322 const char* locale;
2323 const UChar** skeletons;
2324 const UChar** patterns;
2325} Test12HrPatItem;
2326
2327static const Test12HrPatItem test12HrPatItems[] = {
2328 { "zh@calendar=buddhist", skeletons12Hr, patterns12Hr_zh_buddhist },
2329 { "zh_Hant@calendar=buddhist", skeletons12Hr, patterns12Hr_zhHant_buddhist },
2330 { NULL, NULL, NULL } /* terminator */
2331};
2332
2333static void Test12HrPatterns(void) { // Apple <rdar://problem/59940681>
2334 const Test12HrPatItem* itemPtr;
2335 for (itemPtr = test12HrPatItems; itemPtr->locale != NULL; itemPtr++) {
2336 UErrorCode status = U_ZERO_ERROR;
2337 UDateTimePatternGenerator* udatpg = udatpg_open(itemPtr->locale, &status);
2338 if ( U_FAILURE(status) ) {
2339 log_data_err("udatpg_open fails for locale %s: status %s (Are you missing data?)\n", itemPtr->locale, u_errorName(status));
2340 } else {
2341 const UChar** skeletonsPtr = itemPtr->skeletons;
2342 const UChar** patternsPtr = itemPtr->patterns;
2343 const UChar* skeleton;
2344 const UChar* expPatn;
2345 while ((skeleton = *skeletonsPtr++) != NULL && (expPatn = *patternsPtr++) != NULL) {
2346 UChar getPatn[kUbufMax];
2347 char bSkel[kBbufMax];
2348 u_austrcpy(bSkel, skeleton);
2349 int32_t getLen = udatpg_getBestPattern(udatpg, skeleton, -1, getPatn, kUbufMax, &status);
2350 if ( U_FAILURE(status) ) {
2351 log_err("udatpg_getBestPattern fails for locale %s, skeleton %s: status %s\n", itemPtr->locale, bSkel, u_errorName(status));
2352 } else if (u_strcmp(getPatn,expPatn) != 0) {
2353 char bExpPatn[kBbufMax], bGetPatn[kBbufMax];
2354 u_austrcpy(bExpPatn, expPatn);
2355 u_austrcpy(bGetPatn, getPatn);
2356 log_err("udatpg_getBestPattern error for locale %s, skeleton %s: expected %s, got %s\n", itemPtr->locale, bSkel, bExpPatn, bGetPatn);
2357 }
2358 }
2359 udatpg_close(udatpg);
2360 }
2361 }
2362}
2363
4f1e1a09 2364#if !U_PLATFORM_HAS_WIN32_API
b331163b
A
2365
2366typedef struct {
2367 const char* locale;
2368 UATimeUnitTimePattern patType;
2369 const char* expect; /* universal char subset + escaped Unicode chars */
2370} TimePatternItem;
2371static const TimePatternItem timePatternItems[] = {
2372 { "en", UATIMEUNITTIMEPAT_HM, "h:mm" },
2373 { "en", UATIMEUNITTIMEPAT_HMS, "h:mm:ss" },
2374 { "en", UATIMEUNITTIMEPAT_MS, "m:ss" },
2375 { "da", UATIMEUNITTIMEPAT_HM, "h.mm" },
2376 { "da", UATIMEUNITTIMEPAT_HMS, "h.mm.ss" },
2377 { "da", UATIMEUNITTIMEPAT_MS, "m.ss" },
2378 { NULL, 0, NULL }
2379};
2380
2381typedef struct {
2382 const char* locale;
2383 UATimeUnitStyle width;
2384 UATimeUnitListPattern patType;
2385 const char* expect; /* universal char subset + escaped Unicode chars */
2386} ListPatternItem;
2387static const ListPatternItem listPatternItems[] = {
2388 { "en", UATIMEUNITSTYLE_FULL, UATIMEUNITLISTPAT_TWO_ONLY, "{0}, {1}" },
2389 { "en", UATIMEUNITSTYLE_FULL, UATIMEUNITLISTPAT_END_PIECE, "{0}, {1}" },
2390 { "en", UATIMEUNITSTYLE_FULL, UATIMEUNITLISTPAT_MIDDLE_PIECE, "{0}, {1}" },
2391 { "en", UATIMEUNITSTYLE_FULL, UATIMEUNITLISTPAT_START_PIECE, "{0}, {1}" },
2392 { "en", UATIMEUNITSTYLE_NARROW, UATIMEUNITLISTPAT_TWO_ONLY, "{0} {1}" },
2393 { "en", UATIMEUNITSTYLE_NARROW, UATIMEUNITLISTPAT_END_PIECE, "{0} {1}" },
2394 { "en", UATIMEUNITSTYLE_NARROW, UATIMEUNITLISTPAT_MIDDLE_PIECE, "{0} {1}" },
2395 { "en", UATIMEUNITSTYLE_NARROW, UATIMEUNITLISTPAT_START_PIECE, "{0} {1}" },
2ca993e8 2396 { "en", UATIMEUNITSTYLE_SHORTER, UATIMEUNITLISTPAT_TWO_ONLY, "{0} {1}" },
b331163b
A
2397 { "fr", UATIMEUNITSTYLE_FULL, UATIMEUNITLISTPAT_TWO_ONLY, "{0} et {1}" },
2398 { "fr", UATIMEUNITSTYLE_FULL, UATIMEUNITLISTPAT_END_PIECE, "{0} et {1}" },
2399 { "fr", UATIMEUNITSTYLE_FULL, UATIMEUNITLISTPAT_MIDDLE_PIECE, "{0}, {1}" },
2400 { "fr", UATIMEUNITSTYLE_FULL, UATIMEUNITLISTPAT_START_PIECE, "{0}, {1}" },
2401 { "fr", UATIMEUNITSTYLE_NARROW, UATIMEUNITLISTPAT_TWO_ONLY, "{0} {1}" },
2402 { "fr", UATIMEUNITSTYLE_NARROW, UATIMEUNITLISTPAT_END_PIECE, "{0} {1}" },
2403 { "fr", UATIMEUNITSTYLE_NARROW, UATIMEUNITLISTPAT_MIDDLE_PIECE, "{0} {1}" },
2404 { "fr", UATIMEUNITSTYLE_NARROW, UATIMEUNITLISTPAT_START_PIECE, "{0} {1}" },
2ca993e8 2405 { "fr", UATIMEUNITSTYLE_SHORTER, UATIMEUNITLISTPAT_TWO_ONLY, "{0} {1}" },
b331163b
A
2406 { NULL, 0, 0, NULL }
2407};
2408
2409enum {kUBufTimeUnitLen = 128, kBBufTimeUnitLen = 256 };
2410
2411static void TestTimeUnitFormat(void) { /* Apple-specific */
2412 const TimePatternItem* timePatItemPtr;
2413 const ListPatternItem* listPatItemPtr;
2414 UChar uActual[kUBufTimeUnitLen];
2415 UChar uExpect[kUBufTimeUnitLen];
2416
2417 for (timePatItemPtr = timePatternItems; timePatItemPtr->locale != NULL; timePatItemPtr++) {
2418 UErrorCode status = U_ZERO_ERROR;
2419 int32_t ulenActual = uatmufmt_getTimePattern(timePatItemPtr->locale, timePatItemPtr->patType, uActual, kUBufTimeUnitLen, &status);
2420 if ( U_FAILURE(status) ) {
2421 log_err("uatmufmt_getTimePattern for locale %s, patType %d: status %s\n", timePatItemPtr->locale, (int)timePatItemPtr->patType, u_errorName(status));
2422 } else {
2423 int32_t ulenExpect = u_unescape(timePatItemPtr->expect, uExpect, kUBufTimeUnitLen);
2424 if (ulenActual != ulenExpect || u_strncmp(uActual, uExpect, ulenExpect) != 0) {
2425 char bActual[kBBufTimeUnitLen];
2426 u_strToUTF8(bActual, kBBufTimeUnitLen, NULL, uActual, ulenActual, &status);
2427 log_err("uatmufmt_getTimePattern for locale %s, patType %d: unexpected result %s\n", timePatItemPtr->locale, (int)timePatItemPtr->patType, bActual);
2428 }
2429 }
2430 }
2431
2432 for (listPatItemPtr = listPatternItems; listPatItemPtr->locale != NULL; listPatItemPtr++) {
2433 UErrorCode status = U_ZERO_ERROR;
2434 int32_t ulenActual = uatmufmt_getListPattern(listPatItemPtr->locale, listPatItemPtr->width, listPatItemPtr->patType, uActual, kUBufTimeUnitLen, &status);
2435 if ( U_FAILURE(status) ) {
2436 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));
2437 } else {
2438 int32_t ulenExpect = u_unescape(listPatItemPtr->expect, uExpect, kUBufTimeUnitLen);
2439 if (ulenActual != ulenExpect || u_strncmp(uActual, uExpect, ulenExpect) != 0) {
2440 char bActual[kBBufTimeUnitLen];
2441 u_strToUTF8(bActual, kBBufTimeUnitLen, NULL, uActual, ulenActual, &status);
2442 log_err("uatmufmt_getListPattern for locale %s, width %d, patType %d: unexpected result %s\n", listPatItemPtr->locale, (int)listPatItemPtr->width, (int)listPatItemPtr->patType, bActual);
2443 }
2444 }
2445 }
2446
2447}
3d1f044b
A
2448
2449typedef struct {
2450 const char* locale;
2451 UNumberFormatStyle numStyle;
2452 UATimeUnitStyle width;
2453 UATimeUnitField field;
2454 double value;
2455 const UChar* expect;
2456} TimeUnitWithNumStyleItem;
2457static const TimeUnitWithNumStyleItem tuNumStyleItems[] = {
2458 { "en_US", UNUM_PATTERN_DECIMAL/*0*/, UATIMEUNITSTYLE_FULL/*0*/, UATIMEUNITFIELD_SECOND/*6*/, 0.0, u"0 seconds" },
2459 { "en_US", UNUM_DECIMAL, UATIMEUNITSTYLE_FULL, UATIMEUNITFIELD_SECOND, 0.0, u"0 seconds" },
2460 { "en_US", UNUM_CURRENCY, UATIMEUNITSTYLE_FULL, UATIMEUNITFIELD_SECOND, 0.0, u"$0.00 seconds" },
2461 { "en_US", UNUM_PERCENT, UATIMEUNITSTYLE_FULL, UATIMEUNITFIELD_SECOND, 0.0, u"0% seconds" },
2462 { "en_US", UNUM_SCIENTIFIC/*4*/, UATIMEUNITSTYLE_FULL, UATIMEUNITFIELD_SECOND, 0.0, u"0E0 seconds" },
2463 { "en_US", UNUM_SPELLOUT/*5*/, UATIMEUNITSTYLE_FULL, UATIMEUNITFIELD_SECOND, 0.0, u"zero seconds" }, // uses RuleBasedNumberFormat, got U_UNSUPPORTED_ERROR
2464 { "en_US", UNUM_ORDINAL, UATIMEUNITSTYLE_FULL, UATIMEUNITFIELD_SECOND, 0.0, u"0th seconds" }, // uses RuleBasedNumberFormat, got U_UNSUPPORTED_ERROR
2465 { "en_US", UNUM_DURATION, UATIMEUNITSTYLE_FULL, UATIMEUNITFIELD_SECOND, 0.0, u"0 sec. seconds" }, // uses RuleBasedNumberFormat, got U_UNSUPPORTED_ERROR
2466 { "en_US", UNUM_NUMBERING_SYSTEM/*8*/, UATIMEUNITSTYLE_FULL, UATIMEUNITFIELD_SECOND, 0.0, u"௦ seconds" }, // uses RuleBasedNumberFormat, got U_UNSUPPORTED_ERROR
2467 // skip UNUM_PATTERN_RULEBASED/*9*/ // uses RuleBasedNumberFormat
2468 // { "en_US", UNUM_CURRENCY_ISO/*10*/, UATIMEUNITSTYLE_FULL, UATIMEUNITFIELD_SECOND, 0.0, u"USD 0.00 seconds" }, // currently produces u"USD 0.0 seconds0"
2469 { "en_US", UNUM_CURRENCY_PLURAL, UATIMEUNITSTYLE_FULL, UATIMEUNITFIELD_SECOND, 0.0, u"0.00 US dollars seconds" },
2470 { "en_US", UNUM_CURRENCY_ACCOUNTING, UATIMEUNITSTYLE_FULL, UATIMEUNITFIELD_SECOND, 0.0, u"$0.00 seconds" },
2471 { "en_US", UNUM_CASH_CURRENCY, UATIMEUNITSTYLE_FULL, UATIMEUNITFIELD_SECOND, 0.0, u"$0.00 seconds" },
2472 { "en_US", UNUM_DECIMAL_COMPACT_SHORT, UATIMEUNITSTYLE_FULL, UATIMEUNITFIELD_SECOND, 0.0, u"0 seconds" },
2473 { "en_US", UNUM_DECIMAL_COMPACT_LONG, UATIMEUNITSTYLE_FULL, UATIMEUNITFIELD_SECOND, 0.0, u"0 seconds" },
2474 { "en_US", UNUM_CURRENCY_STANDARD/*16*/,UATIMEUNITSTYLE_FULL, UATIMEUNITFIELD_SECOND, 0.0, u"$0.00 seconds" },
2475 { NULL, 0, 0, 0, 0.0, NULL }
2476};
2477
2478enum { kBBufMax = 196 };
2479
2480static void TestTimeUnitFormatWithNumStyle(void) { /* Apple-specific */
2481 const TimeUnitWithNumStyleItem* itemPtr;
2482 for (itemPtr = tuNumStyleItems; itemPtr->locale != NULL; itemPtr++) {
2483 UErrorCode status = U_ZERO_ERROR;
2484 UNumberFormat *numFormat = unum_open(itemPtr->numStyle, NULL, 0, itemPtr->locale, NULL, &status);
2485 if ( U_FAILURE(status) ) {
2486 log_data_err("unum_open for locale %s, style %d: status %s\n", itemPtr->locale, itemPtr->numStyle, u_errorName(status));
2487 } else {
2488 UATimeUnitFormat *tuFormat = uatmufmt_openWithNumberFormat(itemPtr->locale, itemPtr->width, numFormat, &status);
2489 if ( U_FAILURE(status) ) {
2490 log_data_err("uatmufmt_openWithNumberFormat for locale %s, numStyle %d, width %d: status %s\n", itemPtr->locale, itemPtr->numStyle, itemPtr->width, u_errorName(status));
2491 } else {
2492 UChar ubuf[kUBufMax] = {0};
2493 int32_t ulen = uatmufmt_format(tuFormat, itemPtr->value, itemPtr->field, ubuf, kUBufMax, &status);
2494 if ( U_FAILURE(status) ) {
2495 log_err("uatmufmt_format for locale %s, numStyle %d, width %d, field %d: status %s\n", itemPtr->locale, itemPtr->numStyle, itemPtr->width, itemPtr->field, u_errorName(status));
2496 } else if (u_strcmp(ubuf, itemPtr->expect) != 0) {
2497 char bbufExp[kBBufMax];
2498 char bbufGet[kBBufMax];
2499 u_strToUTF8(bbufExp, kBBufMax, NULL, itemPtr->expect, -1, &status);
2500 u_strToUTF8(bbufGet, kBBufMax, NULL, ubuf, ulen, &status);
2501 log_err("uatmufmt_format for locale %s, numStyle %d, width %d, field %d:\n expect %s\n get %s\n", itemPtr->locale, itemPtr->numStyle, itemPtr->width, itemPtr->field, bbufExp, bbufGet);
2502 }
2503 uatmufmt_close(tuFormat);
2504 }
2505 }
2506 }
2507}
2508
4f1e1a09 2509#endif
b331163b 2510
340931cb
A
2511typedef struct {
2512 UChar patternChar;
2513 UDateFormatField dateField;
2514 UCalendarDateFields calField;
2515} PatternCharToFieldsItem;
2516
2517static const PatternCharToFieldsItem patCharToFieldsItems[] = {
2518 { u'G', UDAT_ERA_FIELD, UCAL_ERA },
2519 { u'y', UDAT_YEAR_FIELD, UCAL_YEAR },
2520 { u'Y', UDAT_YEAR_WOY_FIELD, UCAL_YEAR_WOY },
2521 { u'Q', UDAT_QUARTER_FIELD, UCAL_MONTH },
2522 { u'H', UDAT_HOUR_OF_DAY0_FIELD, UCAL_HOUR_OF_DAY },
2523 { u'r', UDAT_RELATED_YEAR_FIELD, UCAL_EXTENDED_YEAR },
2524 { u'B', UDAT_FLEXIBLE_DAY_PERIOD_FIELD, UCAL_FIELD_COUNT },
2525 { u'$', UDAT_FIELD_COUNT, UCAL_FIELD_COUNT },
2526 { (UChar)0, (UDateFormatField)0, (UCalendarDateFields)0 } // terminator
2527};
2528
2529static void TestMapPatternCharToFields(void){ /* Apple <rdar://problem/62136559> */
2530 const PatternCharToFieldsItem* itemPtr;
2531 for ( itemPtr=patCharToFieldsItems; itemPtr->patternChar!=(UChar)0; itemPtr++) {
2532 UDateFormatField dateField = udat_patternCharToDateFormatField(itemPtr->patternChar);
2533 UCalendarDateFields calField = udat_toCalendarDateField(dateField);
2534 if (dateField != itemPtr->dateField || calField != itemPtr->calField) {
2535 log_err("for pattern char 0x%04X, expect dateField %d and got %d, expect calField %d and got %d\n",
2536 itemPtr->patternChar, itemPtr->dateField, dateField, itemPtr->calField, calField);
2537 }
2538 }
2539}
2540
b331163b
A
2541typedef enum RemapTesttype {
2542 REMAP_TESTTYPE_FULL = UDAT_FULL, // 0
2543 REMAP_TESTTYPE_LONG = UDAT_LONG, // 1
2544 REMAP_TESTTYPE_MEDIUM = UDAT_MEDIUM, // 2
2545 REMAP_TESTTYPE_SHORT = UDAT_SHORT, // 3
2546 REMAP_TESTTYPE_LONG_DF = UDAT_LONG + 4, // 5 long time, full date
2547 REMAP_TESTTYPE_SHORT_DS = UDAT_SHORT + 16, // 3 short time, short date
2548 REMAP_TESTTYPE_SKELETON = -1,
2549 REMAP_TESTTYPE_PATTERN = -2,
2550} RemapTesttype;
2551
2552typedef struct {
2553 const char * pattern;
2554 RemapTesttype testtype;
2555 uint32_t options;
2556} RemapPatternTestItem;
2557
2558static const RemapPatternTestItem remapPatItems[] = {
2559 { "full", REMAP_TESTTYPE_FULL, 0 },
2560 { "full", REMAP_TESTTYPE_FULL, UADATPG_FORCE_24_HOUR_CYCLE },
2561 { "full", REMAP_TESTTYPE_FULL, UADATPG_FORCE_12_HOUR_CYCLE },
2562 { "long", REMAP_TESTTYPE_LONG, 0 },
2563 { "long", REMAP_TESTTYPE_LONG, UADATPG_FORCE_24_HOUR_CYCLE },
2564 { "long", REMAP_TESTTYPE_LONG, UADATPG_FORCE_12_HOUR_CYCLE },
2565 { "medium", REMAP_TESTTYPE_MEDIUM, 0 },
2566 { "medium", REMAP_TESTTYPE_MEDIUM, UADATPG_FORCE_24_HOUR_CYCLE },
2567 { "medium", REMAP_TESTTYPE_MEDIUM, UADATPG_FORCE_12_HOUR_CYCLE },
2568 { "short", REMAP_TESTTYPE_SHORT, 0 },
2569 { "short", REMAP_TESTTYPE_SHORT, UADATPG_FORCE_24_HOUR_CYCLE },
2570 { "short", REMAP_TESTTYPE_SHORT, UADATPG_FORCE_12_HOUR_CYCLE },
2571 { "long_df", REMAP_TESTTYPE_LONG_DF, 0 },
2572 { "long_df", REMAP_TESTTYPE_LONG_DF, UADATPG_FORCE_24_HOUR_CYCLE },
2573 { "long_df", REMAP_TESTTYPE_LONG_DF, UADATPG_FORCE_12_HOUR_CYCLE },
2574 { "short_ds", REMAP_TESTTYPE_SHORT_DS, 0 },
2575 { "short_ds", REMAP_TESTTYPE_SHORT_DS, UADATPG_FORCE_24_HOUR_CYCLE },
2576 { "short_ds", REMAP_TESTTYPE_SHORT_DS, UADATPG_FORCE_12_HOUR_CYCLE },
2577
2578 { "jmmss", REMAP_TESTTYPE_SKELETON, 0 },
2579 { "jmmss", REMAP_TESTTYPE_SKELETON, UADATPG_FORCE_24_HOUR_CYCLE },
2580 { "jmmss", REMAP_TESTTYPE_SKELETON, UADATPG_FORCE_12_HOUR_CYCLE },
2581 { "jjmmss", REMAP_TESTTYPE_SKELETON, 0 },
2582 { "jjmmss", REMAP_TESTTYPE_SKELETON, UADATPG_FORCE_24_HOUR_CYCLE },
2583 { "jjmmss", REMAP_TESTTYPE_SKELETON, UADATPG_FORCE_24_HOUR_CYCLE | UDATPG_MATCH_HOUR_FIELD_LENGTH },
2584 { "jjmmss", REMAP_TESTTYPE_SKELETON, UADATPG_FORCE_12_HOUR_CYCLE },
2585 { "jjmmss", REMAP_TESTTYPE_SKELETON, UADATPG_FORCE_12_HOUR_CYCLE | UDATPG_MATCH_HOUR_FIELD_LENGTH },
2586 { "Jmm", REMAP_TESTTYPE_SKELETON, 0 },
2587 { "Jmm", REMAP_TESTTYPE_SKELETON, UADATPG_FORCE_24_HOUR_CYCLE },
2588 { "Jmm", REMAP_TESTTYPE_SKELETON, UADATPG_FORCE_12_HOUR_CYCLE },
2589 { "jmsv", REMAP_TESTTYPE_SKELETON, 0 },
2590 { "jmsv", REMAP_TESTTYPE_SKELETON, UADATPG_FORCE_24_HOUR_CYCLE },
2591 { "jmsv", REMAP_TESTTYPE_SKELETON, UADATPG_FORCE_12_HOUR_CYCLE },
2592 { "jmsz", REMAP_TESTTYPE_SKELETON, 0 },
2593 { "jmsz", REMAP_TESTTYPE_SKELETON, UADATPG_FORCE_24_HOUR_CYCLE },
2594 { "jmsz", REMAP_TESTTYPE_SKELETON, UADATPG_FORCE_12_HOUR_CYCLE },
2595
2596 { "h:mm:ss a", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_12_HOUR_CYCLE }, // 12=hour patterns
2597 { "h:mm:ss a", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_24_HOUR_CYCLE },
2598 { "a'xx'h:mm:ss d MMM y", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_12_HOUR_CYCLE },
2599 { "a'xx'h:mm:ss d MMM y", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_24_HOUR_CYCLE },
2600 { "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_12_HOUR_CYCLE },
2601 { "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_24_HOUR_CYCLE },
2602 { "EEE, d MMM y 'aha' a'xx'h:mm:ss", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_12_HOUR_CYCLE },
2603 { "EEE, d MMM y 'aha' a'xx'h:mm:ss", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_24_HOUR_CYCLE },
2604 { "yyMMddhhmmss", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_12_HOUR_CYCLE },
2605 { "yyMMddhhmmss", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_24_HOUR_CYCLE },
2606
2607 { "H:mm:ss", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_12_HOUR_CYCLE }, // 24=hour patterns
2608 { "H:mm:ss", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_24_HOUR_CYCLE },
2609 { "H:mm:ss d MMM y", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_12_HOUR_CYCLE },
2610 { "H:mm:ss d MMM y", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_24_HOUR_CYCLE },
2611 { "EEE, d MMM y 'aha' H:mm:ss 'hrs'", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_12_HOUR_CYCLE },
2612 { "EEE, d MMM y 'aha' H:mm:ss 'hrs'", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_24_HOUR_CYCLE },
2613 { "EEE, d MMM y 'aha' H'h'mm'm'ss", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_12_HOUR_CYCLE },
2614 { "EEE, d MMM y 'aha' H'h'mm'm'ss", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_24_HOUR_CYCLE },
0f5d89e8
A
2615
2616 // special cases per bugs
2617 { "uuuu-MM-dd HH:mm:ss '+0000'", REMAP_TESTTYPE_PATTERN, UADATPG_FORCE_12_HOUR_CYCLE }, // <rdar://problem/38826484>
2618
b331163b
A
2619 { NULL, (RemapTesttype)0, 0 }
2620};
2621
2622static const char * remapResults_root[] = {
2623 "HH:mm:ss zzzz", // full
2624 "HH:mm:ss zzzz", // force24
2625 "h:mm:ss a zzzz", // force12
2626 "HH:mm:ss z", // long
2627 "HH:mm:ss z", // force24
2628 "h:mm:ss a z", // force12
2629 "HH:mm:ss", // medium
2630 "HH:mm:ss", // force24
2631 "h:mm:ss a", // force12
2632 "HH:mm", // short
2633 "HH:mm", // force24
2634 "h:mm a", // force12
2635 "y MMMM d, EEEE HH:mm:ss z", // long_df
2636 "y MMMM d, EEEE HH:mm:ss z", // force24
2637 "y MMMM d, EEEE h:mm:ss a z", // force12
2638 "y-MM-dd HH:mm", // short_ds
2639 "y-MM-dd HH:mm", // force24
2640 "y-MM-dd h:mm a", // force12
2641
2642 "HH:mm:ss", // jmmss
2643 "HH:mm:ss", // force24
2644 "h:mm:ss a", // force12
2645 "HH:mm:ss", // jjmmss
2646 "HH:mm:ss", // force24
2647 "HH:mm:ss", // force24 | match hour field length
2648 "h:mm:ss a", // force12
2649 "hh:mm:ss a", // force12 | match hour field length
2650 "HH:mm", // Jmm
2651 "HH:mm", // force24
2652 "hh:mm", // force12
2653 "HH:mm:ss v", // jmsv
2654 "HH:mm:ss v", // force24
2655 "h:mm:ss a v", // force12
2656 "HH:mm:ss z", // jmsz
2657 "HH:mm:ss z", // force24
2658 "h:mm:ss a z", // force12
2659
2660 "h:mm:ss a", // "h:mm:ss"
2661 "HH:mm:ss", //
2662 "a'xx'h:mm:ss d MMM y", // "a'xx'h:mm:ss d MMM y"
2663 "HH:mm:ss d MMM y", //
2664 "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", // "EEE, d MMM y 'aha' h:mm:ss a 'hrs'"
2665 "EEE, d MMM y 'aha' HH:mm:ss 'hrs'", //
2666 "EEE, d MMM y 'aha' a'xx'h:mm:ss", // "EEE, d MMM y 'aha' a'xx'h:mm:ss"
2667 "EEE, d MMM y 'aha' HH:mm:ss", //
2668 "yyMMddhhmmss", // "yyMMddhhmmss"
2669 "yyMMddHHmmss", //
2670
2671 "h:mm:ss a", // "H:mm:ss"
2672 "H:mm:ss", //
2673 "h:mm:ss a d MMM y", // "H:mm:ss d MMM y"
2674 "H:mm:ss d MMM y", //
2675 "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", // "EEE, d MMM y 'aha' H:mm:ss 'hrs'"
2676 "EEE, d MMM y 'aha' H:mm:ss 'hrs'", //
2677 "EEE, d MMM y 'aha' h'h'mm'm'ss a", // "EEE, d MMM y 'aha' H'h'mm'm'ss"
2678 "EEE, d MMM y 'aha' H'h'mm'm'ss", //
0f5d89e8
A
2679
2680 "uuuu-MM-dd h:mm:ss a '+0000'", //
2681
b331163b
A
2682 NULL
2683};
2684
2685static const char * remapResults_en[] = {
2686 "h:mm:ss a zzzz", // full
2687 "HH:mm:ss zzzz", // force24
2688 "h:mm:ss a zzzz", // force12
2689 "h:mm:ss a z", // long
2690 "HH:mm:ss z", // force24
2691 "h:mm:ss a z", // force12
2692 "h:mm:ss a", // medium
2693 "HH:mm:ss", // force24
2694 "h:mm:ss a", // force12
2695 "h:mm a", // short
2696 "HH:mm", // force24
2697 "h:mm a", // force12
2698 "EEEE, MMMM d, y 'at' h:mm:ss a z", // long_df
2699 "EEEE, MMMM d, y 'at' HH:mm:ss z", // force24
2700 "EEEE, MMMM d, y 'at' h:mm:ss a z", // force12
2701 "M/d/yy, h:mm a", // short_ds
2702 "M/d/yy, HH:mm", // force24
2703 "M/d/yy, h:mm a", // force12
2704
2705 "h:mm:ss a", // jmmss
2706 "HH:mm:ss", // force24
2707 "h:mm:ss a", // force12
2708 "h:mm:ss a", // jjmmss
2709 "HH:mm:ss", // force24
2710 "HH:mm:ss", // force24 | match hour field length
2711 "h:mm:ss a", // force12
2712 "hh:mm:ss a", // force12 | match hour field length
2713 "hh:mm", // Jmm
2714 "HH:mm", // force24
2715 "hh:mm", // force12
2716 "h:mm:ss a v", // jmsv
2717 "HH:mm:ss v", // force24
2718 "h:mm:ss a v", // force12
2719 "h:mm:ss a z", // jmsz
2720 "HH:mm:ss z", // force24
2721 "h:mm:ss a z", // force12
2722
2723 "h:mm:ss a", // "h:mm:ss"
2724 "HH:mm:ss", //
2725 "a'xx'h:mm:ss d MMM y", // "a'xx'h:mm:ss d MMM y"
2726 "HH:mm:ss d MMM y", //
2727 "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", // "EEE, d MMM y 'aha' h:mm:ss a 'hrs'"
2728 "EEE, d MMM y 'aha' HH:mm:ss 'hrs'", //
2729 "EEE, d MMM y 'aha' a'xx'h:mm:ss", // "EEE, d MMM y 'aha' a'xx'h:mm:ss"
2730 "EEE, d MMM y 'aha' HH:mm:ss", //
2731 "yyMMddhhmmss", // "yyMMddhhmmss"
2732 "yyMMddHHmmss", //
2733
2734 "h:mm:ss a", // "H:mm:ss"
2735 "H:mm:ss", //
2736 "h:mm:ss a d MMM y", // "H:mm:ss d MMM y"
2737 "H:mm:ss d MMM y", //
2738 "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", // "EEE, d MMM y 'aha' H:mm:ss 'hrs'"
2739 "EEE, d MMM y 'aha' H:mm:ss 'hrs'", //
2740 "EEE, d MMM y 'aha' h'h'mm'm'ss a", // "EEE, d MMM y 'aha' H'h'mm'm'ss"
2741 "EEE, d MMM y 'aha' H'h'mm'm'ss", //
0f5d89e8
A
2742
2743 "uuuu-MM-dd h:mm:ss a '+0000'", //
2744
b331163b
A
2745 NULL
2746};
2747
2748static const char * remapResults_ja[] = {
2749 "H\\u6642mm\\u5206ss\\u79D2 zzzz", // full
2750 "H\\u6642mm\\u5206ss\\u79D2 zzzz", // force24
2751 "aK:mm:ss zzzz", // force12
2752 "H:mm:ss z", // long
2753 "H:mm:ss z", // force24
2754 "aK:mm:ss z", // force12
2755 "H:mm:ss", // medium
2756 "H:mm:ss", // force24
2757 "aK:mm:ss", // force12
2758 "H:mm", // short
2759 "H:mm", // force24
2760 "aK:mm", // force12
f3c0d7a5
A
2761 "y\\u5E74M\\u6708d\\u65E5 EEEE H:mm:ss z", // long_df
2762 "y\\u5E74M\\u6708d\\u65E5 EEEE H:mm:ss z", // force24
2763 "y\\u5E74M\\u6708d\\u65E5 EEEE aK:mm:ss z", // force12
b331163b
A
2764 "y/MM/dd H:mm", // short_ds
2765 "y/MM/dd H:mm", // force24
2766 "y/MM/dd aK:mm", // force12
2767
2768 "H:mm:ss", // jmmss
2769 "H:mm:ss", // force24
2770 "aK:mm:ss", // force12
2771 "H:mm:ss", // jjmmss
2772 "H:mm:ss", // force24
2773 "HH:mm:ss", // force24 | match hour field length
2774 "aK:mm:ss", // force12
2775 "aKK:mm:ss", // force12 | match hour field length
2776 "H:mm", // Jmm
2777 "H:mm", // force24
2778 "h:mm", // force12
2779 "H:mm:ss v", // jmsv
2780 "H:mm:ss v", // force24
2781 "aK:mm:ss v", // force12
2782 "H:mm:ss z", // jmsz
2783 "H:mm:ss z", // force24
2784 "aK:mm:ss z", // force12
2785
2786 "h:mm:ss a", // "h:mm:ss"
2787 "H:mm:ss", //
2788 "a'xx'h:mm:ss d MMM y", // "a'xx'h:mm:ss d MMM y"
2789 "H:mm:ss d MMM y", //
2790 "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", // "EEE, d MMM y 'aha' h:mm:ss a 'hrs'"
2791 "EEE, d MMM y 'aha' H:mm:ss 'hrs'", //
2792 "EEE, d MMM y 'aha' a'xx'h:mm:ss", // "EEE, d MMM y 'aha' a'xx'h:mm:ss"
2793 "EEE, d MMM y 'aha' H:mm:ss", //
2794 "yyMMddhhmmss", // "yyMMddhhmmss"
2795 "yyMMddHHmmss", //
2796
2797 "aK:mm:ss", // "H:mm:ss"
2798 "H:mm:ss", //
2799 "aK:mm:ss d MMM y", // "H:mm:ss d MMM y"
2800 "H:mm:ss d MMM y", //
2801 "EEE, d MMM y 'aha' aK:mm:ss 'hrs'", // "EEE, d MMM y 'aha' H:mm:ss 'hrs'"
2802 "EEE, d MMM y 'aha' H:mm:ss 'hrs'", //
2803 "EEE, d MMM y 'aha' aK'h'mm'm'ss", // "EEE, d MMM y 'aha' H'h'mm'm'ss"
2804 "EEE, d MMM y 'aha' H'h'mm'm'ss", //
0f5d89e8
A
2805
2806 "uuuu-MM-dd aK:mm:ss '+0000'", //
2807
b331163b
A
2808 NULL
2809};
2810
2811static const char * remapResults_ko[] = {
2812 "a h\\uC2DC m\\uBD84 s\\uCD08 zzzz", // full
2813 "H\\uC2DC m\\uBD84 s\\uCD08 zzzz", // force24
2814 "a h\\uC2DC m\\uBD84 s\\uCD08 zzzz", // force12
2815 "a h\\uC2DC m\\uBD84 s\\uCD08 z", // long
2816 "H\\uC2DC m\\uBD84 s\\uCD08 z", // force24
2817 "a h\\uC2DC m\\uBD84 s\\uCD08 z", // force12
2818 "a h:mm:ss", // medium
2819 "HH:mm:ss", // force24
2820 "a h:mm:ss", // force12
2821 "a h:mm", // short
2822 "HH:mm", // force24
2823 "a h:mm", // force12
2824 "y\\uB144 M\\uC6D4 d\\uC77C EEEE a h\\uC2DC m\\uBD84 s\\uCD08 z", // long_df
2825 "y\\uB144 M\\uC6D4 d\\uC77C EEEE H\\uC2DC m\\uBD84 s\\uCD08 z", // force24
2826 "y\\uB144 M\\uC6D4 d\\uC77C EEEE a h\\uC2DC m\\uBD84 s\\uCD08 z", // force12
2827 "y. M. d. a h:mm", // short_ds
2828 "y. M. d. HH:mm", // force24
2829 "y. M. d. a h:mm", // force12
2830
2831 "a h:mm:ss", // jmmss
2832 "HH:mm:ss", // force24
2833 "a h:mm:ss", // force12
2834 "a h:mm:ss", // jjmmss
2835 "HH:mm:ss", // force24
2836 "HH:mm:ss", // force24 | match hour field length
2837 "a h:mm:ss", // force12
2838 "a hh:mm:ss", // force12 | match hour field length
2839 "hh:mm", // Jmm
2840 "HH:mm", // force24
2841 "hh:mm", // force12
2842 "a h:mm:ss v", // jmsv
2843 "H\\uC2DC m\\uBD84 s\\uCD08 v", // force24
2844 "a h:mm:ss v", // force12
2845 "a h\\uC2DC m\\uBD84 s\\uCD08 z", // jmsz
2846 "H\\uC2DC m\\uBD84 s\\uCD08 z", // force24
2847 "a h\\uC2DC m\\uBD84 s\\uCD08 z", // force12
2848
2849 "h:mm:ss a", // "h:mm:ss"
2850 "HH:mm:ss", //
2851 "a'xx'h:mm:ss d MMM y", // "a'xx'h:mm:ss d MMM y"
2852 "HH:mm:ss d MMM y", //
2853 "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", // "EEE, d MMM y 'aha' h:mm:ss a 'hrs'"
2854 "EEE, d MMM y 'aha' HH:mm:ss 'hrs'", //
2855 "EEE, d MMM y 'aha' a'xx'h:mm:ss", // "EEE, d MMM y 'aha' a'xx'h:mm:ss"
2856 "EEE, d MMM y 'aha' HH:mm:ss", //
2857 "yyMMddhhmmss", // "yyMMddhhmmss"
2858 "yyMMddHHmmss", //
2859
2860 "a h:mm:ss", // "H:mm:ss"
2861 "H:mm:ss", //
2862 "a h:mm:ss d MMM y", // "H:mm:ss d MMM y"
2863 "H:mm:ss d MMM y", //
2864 "EEE, d MMM y 'aha' a h:mm:ss 'hrs'", // "EEE, d MMM y 'aha' H:mm:ss 'hrs'"
2865 "EEE, d MMM y 'aha' H:mm:ss 'hrs'", //
2866 "EEE, d MMM y 'aha' a h'h'mm'm'ss", // "EEE, d MMM y 'aha' H'h'mm'm'ss"
2867 "EEE, d MMM y 'aha' H'h'mm'm'ss", //
0f5d89e8
A
2868
2869 "uuuu-MM-dd a h:mm:ss '+0000'", //
2870
b331163b
A
2871 NULL
2872};
2873
2874static const char * remapResults_th[] = {
2875 "H \\u0E19\\u0E32\\u0E2C\\u0E34\\u0E01\\u0E32 mm \\u0E19\\u0E32\\u0E17\\u0E35 ss \\u0E27\\u0E34\\u0E19\\u0E32\\u0E17\\u0E35 zzzz", // full
2876 "H \\u0E19\\u0E32\\u0E2C\\u0E34\\u0E01\\u0E32 mm \\u0E19\\u0E32\\u0E17\\u0E35 ss \\u0E27\\u0E34\\u0E19\\u0E32\\u0E17\\u0E35 zzzz", // force24
2877 "h:mm:ss a zzzz", // force12
2878 "H \\u0E19\\u0E32\\u0E2C\\u0E34\\u0E01\\u0E32 mm \\u0E19\\u0E32\\u0E17\\u0E35 ss \\u0E27\\u0E34\\u0E19\\u0E32\\u0E17\\u0E35 z", // long
2879 "H \\u0E19\\u0E32\\u0E2C\\u0E34\\u0E01\\u0E32 mm \\u0E19\\u0E32\\u0E17\\u0E35 ss \\u0E27\\u0E34\\u0E19\\u0E32\\u0E17\\u0E35 z", // force24
2880 "h:mm:ss a z", // force12
2881 "HH:mm:ss", // medium
2882 "HH:mm:ss", // force24
2883 "h:mm:ss a", // force12
2884 "HH:mm", // short
2885 "HH:mm", // force24
2886 "h:mm a", // force12
2887 "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
2888 "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
2889 "EEEE\\u0E17\\u0E35\\u0E48 d MMMM G y h:mm:ss a z", // force12
2890 "d/M/yy HH:mm", // short_ds
2891 "d/M/yy HH:mm", // force24
2892 "d/M/yy h:mm a", // force12
2893
2894 "HH:mm:ss", // jmmss
2895 "HH:mm:ss", // force24
2896 "h:mm:ss a", // force12
2897 "HH:mm:ss", // jjmmss
2898 "HH:mm:ss", // force24
2899 "HH:mm:ss", // force24 | match hour field length
2900 "h:mm:ss a", // force12
2901 "hh:mm:ss a", // force12 | match hour field length
2902 "HH:mm", // Jmm
2903 "HH:mm", // force24
2904 "hh:mm", // force12
2905 "H \\u0E19\\u0E32\\u0E2C\\u0E34\\u0E01\\u0E32 mm \\u0E19\\u0E32\\u0E17\\u0E35 ss \\u0E27\\u0E34\\u0E19\\u0E32\\u0E17\\u0E35 v", // jmsv
2906 "H \\u0E19\\u0E32\\u0E2C\\u0E34\\u0E01\\u0E32 mm \\u0E19\\u0E32\\u0E17\\u0E35 ss \\u0E27\\u0E34\\u0E19\\u0E32\\u0E17\\u0E35 v", // force24
2907 "h:mm:ss a v", // force12
2908 "H \\u0E19\\u0E32\\u0E2C\\u0E34\\u0E01\\u0E32 mm \\u0E19\\u0E32\\u0E17\\u0E35 ss \\u0E27\\u0E34\\u0E19\\u0E32\\u0E17\\u0E35 z", // jmsz
2909 "H \\u0E19\\u0E32\\u0E2C\\u0E34\\u0E01\\u0E32 mm \\u0E19\\u0E32\\u0E17\\u0E35 ss \\u0E27\\u0E34\\u0E19\\u0E32\\u0E17\\u0E35 z", // force24
2910 "h:mm:ss a z", // force12
2911
2912 "h:mm:ss a", // "h:mm:ss"
2913 "HH:mm:ss", //
2914 "a'xx'h:mm:ss d MMM y", // "a'xx'h:mm:ss d MMM y"
2915 "HH:mm:ss d MMM y", //
2916 "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", // "EEE, d MMM y 'aha' h:mm:ss a 'hrs'"
2917 "EEE, d MMM y 'aha' HH:mm:ss 'hrs'", //
2918 "EEE, d MMM y 'aha' a'xx'h:mm:ss", // "EEE, d MMM y 'aha' a'xx'h:mm:ss"
2919 "EEE, d MMM y 'aha' HH:mm:ss", //
2920 "yyMMddhhmmss", // "yyMMddhhmmss"
2921 "yyMMddHHmmss", //
2922
2923 "h:mm:ss a", // "H:mm:ss"
2924 "H:mm:ss", //
2925 "h:mm:ss a d MMM y", // "H:mm:ss d MMM y"
2926 "H:mm:ss d MMM y", //
2927 "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", // "EEE, d MMM y 'aha' H:mm:ss 'hrs'"
2928 "EEE, d MMM y 'aha' H:mm:ss 'hrs'", //
2929 "EEE, d MMM y 'aha' h'h'mm'm'ss a", // "EEE, d MMM y 'aha' H'h'mm'm'ss"
2930 "EEE, d MMM y 'aha' H'h'mm'm'ss", //
0f5d89e8
A
2931
2932 "uuuu-MM-dd h:mm:ss a '+0000'", //
2933
b331163b
A
2934 NULL
2935};
2936
2937static const char * remapResults_hi[] = {
2938 "a h:mm:ss zzzz", // full
2939 "HH:mm:ss zzzz", // force24
2940 "a h:mm:ss zzzz", // force12
2941 "a h:mm:ss z", // long
2942 "HH:mm:ss z", // force24
2943 "a h:mm:ss z", // force12
2944 "a h:mm:ss", // medium
2945 "HH:mm:ss", // force24
2946 "a h:mm:ss", // force12
2947 "a h:mm", // short
2948 "HH:mm", // force24
2949 "a h:mm", // force12
2950 "EEEE, d MMMM y, a h:mm:ss z", // long_df
2951 "EEEE, d MMMM y, HH:mm:ss z", // force24
2952 "EEEE, d MMMM y, a h:mm:ss z", // force12
2953 "d/M/yy, a h:mm", // short_ds
2954 "d/M/yy, HH:mm", // force24
2955 "d/M/yy, a h:mm", // force12
2956
2957 "a h:mm:ss", // jmmss
2958 "HH:mm:ss", // force24
2959 "a h:mm:ss", // force12
2960 "a h:mm:ss", // jjmmss
2961 "HH:mm:ss", // force24
2962 "HH:mm:ss", // force24 | match hour field length
2963 "a h:mm:ss", // force12
2964 "a hh:mm:ss", // force12 | match hour field length
2965 "hh:mm", // Jmm
2966 "HH:mm", // force24
2967 "hh:mm", // force12
2968 "a h:mm:ss v", // jmsv
2969 "HH:mm:ss v", // force24
2970 "a h:mm:ss v", // force12
2971 "a h:mm:ss z", // jmsz
2972 "HH:mm:ss z", // force24
2973 "a h:mm:ss z", // force12
2974
2975 "h:mm:ss a", // "h:mm:ss"
2976 "HH:mm:ss", //
2977 "a'xx'h:mm:ss d MMM y", // "a'xx'h:mm:ss d MMM y"
2978 "HH:mm:ss d MMM y", //
2979 "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", // "EEE, d MMM y 'aha' h:mm:ss a 'hrs'"
2980 "EEE, d MMM y 'aha' HH:mm:ss 'hrs'", //
2981 "EEE, d MMM y 'aha' a'xx'h:mm:ss", // "EEE, d MMM y 'aha' a'xx'h:mm:ss"
2982 "EEE, d MMM y 'aha' HH:mm:ss", //
2983 "yyMMddhhmmss", // "yyMMddhhmmss"
2984 "yyMMddHHmmss", //
2985
2986 "a h:mm:ss", // "H:mm:ss"
2987 "H:mm:ss", //
2988 "a h:mm:ss d MMM y", // "H:mm:ss d MMM y"
2989 "H:mm:ss d MMM y", //
2990 "EEE, d MMM y 'aha' a h:mm:ss 'hrs'", // "EEE, d MMM y 'aha' H:mm:ss 'hrs'"
2991 "EEE, d MMM y 'aha' H:mm:ss 'hrs'", //
2992 "EEE, d MMM y 'aha' a h'h'mm'm'ss", // "EEE, d MMM y 'aha' H'h'mm'm'ss"
2993 "EEE, d MMM y 'aha' H'h'mm'm'ss", //
0f5d89e8
A
2994
2995 "uuuu-MM-dd a h:mm:ss '+0000'", //
2996
b331163b
A
2997 NULL
2998};
2999
f3c0d7a5
A
3000static const char * remapResults_ar[] = {
3001 "h:mm:ss\\u00A0a zzzz", // full
3002 "HH:mm:ss zzzz", // force24
3003 "h:mm:ss\\u00A0a zzzz", // force12
3004 "h:mm:ss\\u00A0a z", // long
3005 "HH:mm:ss z", // force24
3006 "h:mm:ss\\u00A0a z", // force12
3007 "h:mm:ss\\u00A0a", // medium
3008 "HH:mm:ss", // force24
3009 "h:mm:ss\\u00A0a", // force12
3010 "h:mm\\u00A0a", // short
3011 "HH:mm", // force24
3012 "h:mm\\u00A0a", // force12
3013 "EEEE\\u060C d MMMM\\u060C y\\u060C h:mm:ss\\u00A0a z", // long_df
3014 "EEEE\\u060C d MMMM\\u060C y\\u060C HH:mm:ss z", // force24
3015 "EEEE\\u060C d MMMM\\u060C y\\u060C h:mm:ss\\u00A0a z", // force12
3016 "d\\u200F/M\\u200F/y\\u060C h:mm\\u00A0a", // short_ds
3017 "d\\u200F/M\\u200F/y\\u060C HH:mm", // force24
3018 "d\\u200F/M\\u200F/y\\u060C h:mm\\u00A0a", // force12
3019
3020 "h:mm:ss\\u00A0a", // jmmss
3021 "HH:mm:ss", // force24
3022 "h:mm:ss\\u00A0a", // force12
3023 "h:mm:ss\\u00A0a", // jjmmss
3024 "HH:mm:ss", // force24
3025 "HH:mm:ss", // force24 | match hour field length
3026 "h:mm:ss\\u00A0a", // force12
3027 "hh:mm:ss\\u00A0a", // force12 | match hour field length
3028 "hh:mm", // Jmm
3029 "HH:mm", // force24
3030 "hh:mm", // force12
3031 "h:mm:ss\\u00A0a v", // jmsv
3032 "HH:mm:ss v", // force24
3033 "h:mm:ss\\u00A0a v", // force12
3034 "h:mm:ss\\u00A0a z", // jmsz
3035 "HH:mm:ss z", // force24
3036 "h:mm:ss\\u00A0a z", // force12
3037
3038 "h:mm:ss a", // "h:mm:ss"
3039 "HH:mm:ss", //
3040 "a'xx'h:mm:ss d MMM y", // "a'xx'h:mm:ss d MMM y"
3041 "HH:mm:ss d MMM y", //
3042 "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", // "EEE, d MMM y 'aha' h:mm:ss a 'hrs'"
3043 "EEE, d MMM y 'aha' HH:mm:ss 'hrs'", //
3044 "EEE, d MMM y 'aha' a'xx'h:mm:ss", // "EEE, d MMM y 'aha' a'xx'h:mm:ss"
3045 "EEE, d MMM y 'aha' HH:mm:ss", //
3046 "yyMMddhhmmss", // "yyMMddhhmmss"
3047 "yyMMddHHmmss", //
3048
3049 "h:mm:ssa", // "H:mm:ss" (should there be \\u00A0 before a?)
3050 "H:mm:ss", //
3051 "h:mm:ssa d MMM y", // "H:mm:ss d MMM y" (should there be \\u00A0 before a?)
3052 "H:mm:ss d MMM y", //
3053 "EEE, d MMM y 'aha' h:mm:ssa 'hrs'", // "EEE, d MMM y 'aha' H:mm:ss 'hrs'" (should there be \\u00A0 before a?)
3054 "EEE, d MMM y 'aha' H:mm:ss 'hrs'", //
3055 "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?)
3056 "EEE, d MMM y 'aha' H'h'mm'm'ss", //
0f5d89e8
A
3057
3058 "uuuu-MM-dd h:mm:ss\\u00A0a '+0000'", //
3059
3060 NULL
3061};
3062
3063static const char * remapResults_en_IL[] = {
3064 "H:mm:ss zzzz", // full
3065 "H:mm:ss zzzz", // force24
3066 "h:mm:ss a zzzz", // force12
3067 "H:mm:ss z", // long
3068 "H:mm:ss z", // force24
3069 "h:mm:ss a z", // force12
3070 "H:mm:ss", // medium
3071 "H:mm:ss", // force24
3072 "h:mm:ss a", // force12
3073 "H:mm", // short
3074 "H:mm", // force24
3075 "h:mm a", // force12
3076 "EEEE, d MMMM y 'at' H:mm:ss z", // long_df
3077 "EEEE, d MMMM y 'at' H:mm:ss z", // force24
3078 "EEEE, d MMMM y 'at' h:mm:ss a z", // force12
3079 "dd/MM/y, H:mm", // short_ds
3080 "dd/MM/y, H:mm", // force24
3081 "dd/MM/y, h:mm a", // force12
3082
3083 "H:mm:ss", // jmmss
3084 "H:mm:ss", // force24
3085 "h:mm:ss a", // force12
3086 "H:mm:ss", // jjmmss
3087 "H:mm:ss", // force24
3088 "HH:mm:ss", // force24 | match hour field length
3089 "h:mm:ss a", // force12
3090 "hh:mm:ss a", // force12 | match hour field length
3091 "H:mm", // Jmm
3092 "H:mm", // force24
3093 "h:mm", // force12
3094 "H:mm:ss v", // jmsv
3095 "H:mm:ss v", // force24
3096 "h:mm:ss a v", // force12
3097 "H:mm:ss z", // jmsz
3098 "H:mm:ss z", // force24
3099 "h:mm:ss a z", // force12
3100
3101 "h:mm:ss a", // "h:mm:ss"
3102 "H:mm:ss", //
3103 "a'xx'h:mm:ss d MMM y", // "a'xx'h:mm:ss d MMM y"
3104 "H:mm:ss d MMM y", //
3105 "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", // "EEE, d MMM y 'aha' h:mm:ss a 'hrs'"
3106 "EEE, d MMM y 'aha' H:mm:ss 'hrs'", //
3107 "EEE, d MMM y 'aha' a'xx'h:mm:ss", // "EEE, d MMM y 'aha' a'xx'h:mm:ss"
3108 "EEE, d MMM y 'aha' H:mm:ss", //
3109 "yyMMddhhmmss", // "yyMMddhhmmss"
3110 "yyMMddHHmmss", //
3111
3112 "h:mm:ss a", // "H:mm:ss"
3113 "H:mm:ss", //
3114 "h:mm:ss a d MMM y", // "H:mm:ss d MMM y"
3115 "H:mm:ss d MMM y", //
3116 "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", // "EEE, d MMM y 'aha' H:mm:ss 'hrs'"
3117 "EEE, d MMM y 'aha' H:mm:ss 'hrs'", //
3118 "EEE, d MMM y 'aha' h'h'mm'm'ss a", // "EEE, d MMM y 'aha' H'h'mm'm'ss"
3119 "EEE, d MMM y 'aha' H'h'mm'm'ss", //
3120
3121 "uuuu-MM-dd h:mm:ss a '+0000'", //
3122
f3c0d7a5
A
3123 NULL
3124};
3125
3d1f044b
A
3126static const char * remapResults_es_PR_japanese[] = { // rdar://52461062
3127 "h:mm:ss a zzzz", // full
3128 "HH:mm:ss zzzz", // force24
3129 "h:mm:ss a zzzz", // force12
3130 "h:mm:ss a z", // long
3131 "HH:mm:ss z", // force24
3132 "h:mm:ss a z", // force12
3133 "h:mm:ss a", // medium
3134 "HH:mm:ss", // force24
3135 "h:mm:ss a", // force12
3136 "h:mm a", // short
3137 "HH:mm", // force24
3138 "h:mm a", // force12
3139 "EEEE, d 'de' MMMM 'de' y G, h:mm:ss a z", // long_df
3140 "EEEE, d 'de' MMMM 'de' y G, HH:mm:ss z", // force24
3141 "EEEE, d 'de' MMMM 'de' y G, h:mm:ss a z", // force12
3142 "MM/dd/yy GGGGG h:mm a", // short_ds
3143 "MM/dd/yy GGGGG HH:mm", // force24
3144 "MM/dd/yy GGGGG h:mm a", // force12
3145
3146 "h:mm:ss a", // jmmss
3147 "HH:mm:ss", // force24
3148 "h:mm:ss a", // force12
3149 "h:mm:ss a", // jjmmss
3150 "HH:mm:ss", // force24
3151 "HH:mm:ss", // force24 | match hour field length
3152 "h:mm:ss a", // force12
3153 "hh:mm:ss a", // force12 | match hour field length
3154 "hh:mm", // Jmm
3155 "HH:mm", // force24
3156 "hh:mm", // force12
3157 "h:mm:ss a v", // jmsv
3158 "HH:mm:ss v", // force24
3159 "h:mm:ss a v", // force12
3160 "h:mm:ss a z", // jmsz
3161 "HH:mm:ss z", // force24
3162 "h:mm:ss a z", // force12
3163
3164 "h:mm:ss a", // "h:mm:ss"
3165 "HH:mm:ss", //
3166 "a'xx'h:mm:ss d MMM y", // "a'xx'h:mm:ss d MMM y"
3167 "HH:mm:ss d MMM y", //
3168 "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", // "EEE, d MMM y 'aha' h:mm:ss a 'hrs'"
3169 "EEE, d MMM y 'aha' HH:mm:ss 'hrs'", //
3170 "EEE, d MMM y 'aha' a'xx'h:mm:ss", // "EEE, d MMM y 'aha' a'xx'h:mm:ss"
3171 "EEE, d MMM y 'aha' HH:mm:ss", //
3172 "yyMMddhhmmss", // "yyMMddhhmmss"
3173 "yyMMddHHmmss", //
3174
3175 "h:mm:ss a", // "H:mm:ss"
3176 "H:mm:ss", //
3177 "h:mm:ss a d MMM y", // "H:mm:ss d MMM y"
3178 "H:mm:ss d MMM y", //
3179 "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", // "EEE, d MMM y 'aha' H:mm:ss 'hrs'"
3180 "EEE, d MMM y 'aha' H:mm:ss 'hrs'", //
3181 "EEE, d MMM y 'aha' h'h'mm'm'ss a", // "EEE, d MMM y 'aha' H'h'mm'm'ss"
3182 "EEE, d MMM y 'aha' H'h'mm'm'ss", //
3183
3184 "uuuu-MM-dd h:mm:ss a '+0000'", //
3185
3186 NULL
3187};
3188
1a147d09
A
3189static const char * remapResults_en_IN[] = { // rdar://56309604
3190 "h:mm:ss a zzzz", // full
3191 "HH:mm:ss zzzz", // force24
3192 "h:mm:ss a zzzz", // force12
3193 "h:mm:ss a z", // long
3194 "HH:mm:ss z", // force24
3195 "h:mm:ss a z", // force12
3196 "h:mm:ss a", // medium
3197 "HH:mm:ss", // force24
3198 "h:mm:ss a", // force12
3199 "h:mm a", // short
3200 "HH:mm", // force24
3201 "h:mm a", // force12
3202 "EEEE, d MMMM y 'at' h:mm:ss a z", // long_df
3203 "EEEE, d MMMM y 'at' HH:mm:ss z", // force24
3204 "EEEE, d MMMM y 'at' h:mm:ss a z", // force12
3205 "dd/MM/yy, h:mm a", // short_ds
3206 "dd/MM/yy, HH:mm", // force24
3207 "dd/MM/yy, h:mm a", // force12
3208
3209 "h:mm:ss a", // jmmss
3210 "HH:mm:ss", // force24
3211 "h:mm:ss a", // force12
3212 "h:mm:ss a", // jjmmss
3213 "HH:mm:ss", // force24
3214 "HH:mm:ss", // force24 | match hour field length
3215 "h:mm:ss a", // force12
3216 "hh:mm:ss a", // force12 | match hour field length
3217 "hh:mm", // Jmm
3218 "HH:mm", // force24
3219 "hh:mm", // force12
3220 "h:mm:ss a v", // jmsv
3221 "HH:mm:ss v", // force24
3222 "h:mm:ss a v", // force12
3223 "h:mm:ss a z", // jmsz
3224 "HH:mm:ss z", // force24
3225 "h:mm:ss a z", // force12
3226
3227 "h:mm:ss a", // "h:mm:ss"
3228 "HH:mm:ss", //
3229 "a'xx'h:mm:ss d MMM y", // "a'xx'h:mm:ss d MMM y"
3230 "HH:mm:ss d MMM y", //
3231 "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", // "EEE, d MMM y 'aha' h:mm:ss a 'hrs'"
3232 "EEE, d MMM y 'aha' HH:mm:ss 'hrs'", //
3233 "EEE, d MMM y 'aha' a'xx'h:mm:ss", // "EEE, d MMM y 'aha' a'xx'h:mm:ss"
3234 "EEE, d MMM y 'aha' HH:mm:ss", //
3235 "yyMMddhhmmss", // "yyMMddhhmmss"
3236 "yyMMddHHmmss", //
3237
3238 "h:mm:ss a", // "H:mm:ss"
3239 "H:mm:ss", //
3240 "h:mm:ss a d MMM y", // "H:mm:ss d MMM y"
3241 "H:mm:ss d MMM y", //
3242 "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", // "EEE, d MMM y 'aha' H:mm:ss 'hrs'"
3243 "EEE, d MMM y 'aha' H:mm:ss 'hrs'", //
3244 "EEE, d MMM y 'aha' h'h'mm'm'ss a", // "EEE, d MMM y 'aha' H'h'mm'm'ss"
3245 "EEE, d MMM y 'aha' H'h'mm'm'ss", //
3246
3247 "uuuu-MM-dd h:mm:ss a '+0000'", //
3248
3249 NULL
3250};
3251
3252static const char * remapResults_en_IN_japanese[] = { // rdar://56309604
3253 "h:mm:ss a zzzz", // full
3254 "HH:mm:ss zzzz", // force24
3255 "h:mm:ss a zzzz", // force12
3256 "h:mm:ss a z", // long
3257 "HH:mm:ss z", // force24
3258 "h:mm:ss a z", // force12
3259 "h:mm:ss a", // medium
3260 "HH:mm:ss", // force24
3261 "h:mm:ss a", // force12
3262 "h:mm a", // short
3263 "HH:mm", // force24
3264 "h:mm a", // force12
3265 "EEEE, d MMMM y G 'at' h:mm:ss a z", // long_df
3266 "EEEE, d MMMM y G 'at' HH:mm:ss z", // force24
3267 "EEEE, d MMMM y G 'at' h:mm:ss a z", // force12
3268 "dd/MM/y GGGGG, h:mm a", // short_ds
3269 "dd/MM/y GGGGG, HH:mm", // force24
3270 "dd/MM/y GGGGG, h:mm a", // force12
3271
3272 "h:mm:ss a", // jmmss
3273 "HH:mm:ss", // force24
3274 "h:mm:ss a", // force12
3275 "h:mm:ss a", // jjmmss
3276 "HH:mm:ss", // force24
3277 "HH:mm:ss", // force24 | match hour field length
3278 "h:mm:ss a", // force12
3279 "hh:mm:ss a", // force12 | match hour field length
3280 "hh:mm", // Jmm
3281 "HH:mm", // force24
3282 "hh:mm", // force12
3283 "h:mm:ss a v", // jmsv
3284 "HH:mm:ss v", // force24
3285 "h:mm:ss a v", // force12
3286 "h:mm:ss a z", // jmsz
3287 "HH:mm:ss z", // force24
3288 "h:mm:ss a z", // force12
3289
3290 "h:mm:ss a", // "h:mm:ss"
3291 "HH:mm:ss", //
3292 "a'xx'h:mm:ss d MMM y", // "a'xx'h:mm:ss d MMM y"
3293 "HH:mm:ss d MMM y", //
3294 "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", // "EEE, d MMM y 'aha' h:mm:ss a 'hrs'"
3295 "EEE, d MMM y 'aha' HH:mm:ss 'hrs'", //
3296 "EEE, d MMM y 'aha' a'xx'h:mm:ss", // "EEE, d MMM y 'aha' a'xx'h:mm:ss"
3297 "EEE, d MMM y 'aha' HH:mm:ss", //
3298 "yyMMddhhmmss", // "yyMMddhhmmss"
3299 "yyMMddHHmmss", //
3300
3301 "h:mm:ss a", // "H:mm:ss"
3302 "H:mm:ss", //
3303 "h:mm:ss a d MMM y", // "H:mm:ss d MMM y"
3304 "H:mm:ss d MMM y", //
3305 "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", // "EEE, d MMM y 'aha' H:mm:ss 'hrs'"
3306 "EEE, d MMM y 'aha' H:mm:ss 'hrs'", //
3307 "EEE, d MMM y 'aha' h'h'mm'm'ss a", // "EEE, d MMM y 'aha' H'h'mm'm'ss"
3308 "EEE, d MMM y 'aha' H'h'mm'm'ss", //
3309
3310 "uuuu-MM-dd h:mm:ss a '+0000'", //
3311
3312 NULL
3313};
3314
3315static const char * remapResults_en_BE[] = { // rdar://56309604
3316 "HH:mm:ss zzzz", // full
3317 "HH:mm:ss zzzz", // force24
3318 "h:mm:ss a zzzz", // force12
3319 "HH:mm:ss z", // long
3320 "HH:mm:ss z", // force24
3321 "h:mm:ss a z", // force12
3322 "HH:mm:ss", // medium
3323 "HH:mm:ss", // force24
3324 "h:mm:ss a", // force12
3325 "HH:mm", // short
3326 "HH:mm", // force24
3327 "h:mm a", // force12
3328 "EEEE, d MMMM y 'at' HH:mm:ss z", // long_df
3329 "EEEE, d MMMM y 'at' HH:mm:ss z", // force24
3330 "EEEE, d MMMM y 'at' h:mm:ss a z", // force12
3331 "dd/MM/y, HH:mm", // short_ds
3332 "dd/MM/y, HH:mm", // force24
3333 "dd/MM/y, h:mm a", // force12
3334
3335 "HH:mm:ss", // jmmss
3336 "HH:mm:ss", // force24
3337 "h:mm:ss a", // force12
3338 "HH:mm:ss", // jjmmss
3339 "HH:mm:ss", // force24
3340 "HH:mm:ss", // force24 | match hour field length
3341 "h:mm:ss a", // force12
3342 "hh:mm:ss a", // force12 | match hour field length
3343 "HH:mm", // Jmm
3344 "HH:mm", // force24
3345 "hh:mm", // force12
3346 "HH:mm:ss v", // jmsv
3347 "HH:mm:ss v", // force24
3348 "h:mm:ss a v", // force12
3349 "HH:mm:ss z", // jmsz
3350 "HH:mm:ss z", // force24
3351 "h:mm:ss a z", // force12
3352
3353 "h:mm:ss a", // "h:mm:ss" force12
3354 "HH:mm:ss", // force24
3355 "a'xx'h:mm:ss d MMM y", // "a'xx'h:mm:ss d MMM y" force12
3356 "HH:mm:ss d MMM y", // force24
3357 "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", // "EEE, d MMM y 'aha' h:mm:ss a 'hrs'" force12
3358 "EEE, d MMM y 'aha' HH:mm:ss 'hrs'", //
3359 "EEE, d MMM y 'aha' a'xx'h:mm:ss", // "EEE, d MMM y 'aha' a'xx'h:mm:ss"
3360 "EEE, d MMM y 'aha' HH:mm:ss", //
3361 "yyMMddhhmmss", // "yyMMddhhmmss" force12
3362 "yyMMddHHmmss", //
3363
3364 "h:mm:ss a", // "H:mm:ss"
3365 "H:mm:ss", //
3366 "h:mm:ss a d MMM y", // "H:mm:ss d MMM y"
3367 "H:mm:ss d MMM y", //
3368 "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", // "EEE, d MMM y 'aha' H:mm:ss 'hrs'"
3369 "EEE, d MMM y 'aha' H:mm:ss 'hrs'", //
3370 "EEE, d MMM y 'aha' h'h'mm'm'ss a", // "EEE, d MMM y 'aha' H'h'mm'm'ss"
3371 "EEE, d MMM y 'aha' H'h'mm'm'ss", //
3372
3373 "uuuu-MM-dd h:mm:ss a '+0000'", //
3374
3375 NULL
3376};
3377
3378static const char * remapResults_en_BE_japanese[] = { // rdar://56309604
3379 "HH:mm:ss zzzz", // full
3380 "HH:mm:ss zzzz", // force24
3381 "h:mm:ss a zzzz", // force12
3382 "HH:mm:ss z", // long
3383 "HH:mm:ss z", // force24
3384 "h:mm:ss a z", // force12
3385 "HH:mm:ss", // medium
3386 "HH:mm:ss", // force24
3387 "h:mm:ss a", // force12
3388 "HH:mm", // short
3389 "HH:mm", // force24
3390 "h:mm a", // force12
3391 "EEEE, d MMMM y G 'at' HH:mm:ss z", // long_df
3392 "EEEE, d MMMM y G 'at' HH:mm:ss z", // force24
3393 "EEEE, d MMMM y G 'at' h:mm:ss a z", // force12
3394 "dd/MM/y GGGGG, HH:mm", // short_ds
3395 "dd/MM/y GGGGG, HH:mm", // force24
3396 "dd/MM/y GGGGG, h:mm a", // force12
3397
3398 "HH:mm:ss", // jmmss
3399 "HH:mm:ss", // force24
3400 "h:mm:ss a", // force12
3401 "HH:mm:ss", // jjmmss
3402 "HH:mm:ss", // force24
3403 "HH:mm:ss", // force24 | match hour field length
3404 "h:mm:ss a", // force12
3405 "hh:mm:ss a", // force12 | match hour field length
3406 "HH:mm", // Jmm
3407 "HH:mm", // force24
3408 "hh:mm", // force12
3409 "HH:mm:ss v", // jmsv
3410 "HH:mm:ss v", // force24
3411 "h:mm:ss a v", // force12
3412 "HH:mm:ss z", // jmsz
3413 "HH:mm:ss z", // force24
3414 "h:mm:ss a z", // force12
3415
3416 "h:mm:ss a", // "h:mm:ss" force12
3417 "HH:mm:ss", // force24
3418 "a'xx'h:mm:ss d MMM y", // "a'xx'h:mm:ss d MMM y" force12
3419 "HH:mm:ss d MMM y", // force24
3420 "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", // "EEE, d MMM y 'aha' h:mm:ss a 'hrs'" force12
3421 "EEE, d MMM y 'aha' HH:mm:ss 'hrs'", //
3422 "EEE, d MMM y 'aha' a'xx'h:mm:ss", // "EEE, d MMM y 'aha' a'xx'h:mm:ss"
3423 "EEE, d MMM y 'aha' HH:mm:ss", //
3424 "yyMMddhhmmss", // "yyMMddhhmmss" force12
3425 "yyMMddHHmmss", //
3426
3427 "h:mm:ss a", // "H:mm:ss"
3428 "H:mm:ss", //
3429 "h:mm:ss a d MMM y", // "H:mm:ss d MMM y"
3430 "H:mm:ss d MMM y", //
3431 "EEE, d MMM y 'aha' h:mm:ss a 'hrs'", // "EEE, d MMM y 'aha' H:mm:ss 'hrs'"
3432 "EEE, d MMM y 'aha' H:mm:ss 'hrs'", //
3433 "EEE, d MMM y 'aha' h'h'mm'm'ss a", // "EEE, d MMM y 'aha' H'h'mm'm'ss"
3434 "EEE, d MMM y 'aha' H'h'mm'm'ss", //
3435
3436 "uuuu-MM-dd h:mm:ss a '+0000'", //
3437
3438 NULL
3439};
3440
b331163b
A
3441typedef struct {
3442 const char * locale;
3443 const char ** resultsPtr;
3444} RemapPatternLocaleResults;
3445
3446static const RemapPatternLocaleResults remapLocResults[] = {
3447 { "root", remapResults_root },
3448 { "en", remapResults_en },
3449 { "ja", remapResults_ja },
3450 { "ko", remapResults_ko },
3451 { "th", remapResults_th },
3452 { "hi", remapResults_hi },
f3c0d7a5 3453 { "ar", remapResults_ar },
0f5d89e8 3454 { "en_IL", remapResults_en_IL },
3d1f044b 3455 { "es_PR@calendar=japanese", remapResults_es_PR_japanese },
1a147d09
A
3456 { "en_IN", remapResults_en_IN },
3457 { "en_IN@calendar=japanese", remapResults_en_IN_japanese },
3458 { "en_BE", remapResults_en_BE },
3459 { "en_BE@calendar=japanese", remapResults_en_BE_japanese },
b331163b
A
3460 { NULL, NULL }
3461};
3462
3463enum { kUBufRemapMax = 64, kBBufRemapMax = 128 };
3464
3465static void TestRemapPatternWithOpts(void) { /* Apple-specific */
3466 const RemapPatternLocaleResults * locResPtr;
3467 for (locResPtr = remapLocResults; locResPtr->locale != NULL; locResPtr++) {
3468 UErrorCode status = U_ZERO_ERROR;
3469 UDateTimePatternGenerator* dtpg = udatpg_open(locResPtr->locale, &status);
3470 if ( U_FAILURE(status) ) {
3471 log_data_err("udatpg_open fails for locale %s, status %s (Are you missing data?)\n", locResPtr->locale, u_errorName(status));
3472 } else {
3473 const RemapPatternTestItem * testItemPtr = remapPatItems;
3474 const char ** expResultsPtr = locResPtr->resultsPtr;
3475 for (; testItemPtr->pattern != NULL && *expResultsPtr != NULL; testItemPtr++, expResultsPtr++) {
3476 UChar uskel[kUBufRemapMax];
3477 UChar upatn[kUBufRemapMax];
3478 UChar uget[kUBufRemapMax];
3479 UChar uexp[kUBufRemapMax];
3480 int32_t uelen, ulen = 0;
3481
3482 status = U_ZERO_ERROR;
3483 if (testItemPtr->testtype >= 0) {
3484 UDateFormatStyle timeStyle = (UDateFormatStyle)((int32_t)testItemPtr->testtype & 0x03);
3485 UDateFormatStyle dateStyle = (UDateFormatStyle)((((int32_t)testItemPtr->testtype >> 2) & 0x07) - 1);
3486 UDateFormat* dfmt = udat_open(timeStyle, dateStyle, locResPtr->locale, NULL, 0, NULL, 0, &status);
3487 if ( U_FAILURE(status) ) {
3488 log_data_err("udat_open fails for locale %s, status %s (Are you missing data?)\n", locResPtr->locale, u_errorName(status));
3489 continue;
3490 } else {
3491 ulen = udat_toPattern(dfmt, FALSE, upatn, kUBufRemapMax, &status);
3492 udat_close(dfmt);
3493 if ( U_FAILURE(status) ) {
3494 log_err("udat_toPattern fails for locale %s, status %s\n", locResPtr->locale, u_errorName(status));
3495 continue;
3496 }
3497 }
3498 } else if (testItemPtr->testtype == REMAP_TESTTYPE_SKELETON) {
3499 u_strFromUTF8(uskel, kUBufRemapMax, &ulen, testItemPtr->pattern, -1, &status);
3500 ulen = udatpg_getBestPatternWithOptions(dtpg, uskel, ulen, (UDateTimePatternMatchOptions)testItemPtr->options, upatn, kUBufRemapMax, &status);
3501 if ( U_FAILURE(status) ) {
3502 log_err("udatpg_getBestPatternWithOptions fails for locale %s, skeleton \"%s\": status %s\n", locResPtr->locale, testItemPtr->pattern, u_errorName(status));
3503 continue;
3504 }
3505 } else {
3506 ulen = u_unescape(testItemPtr->pattern, upatn, kUBufRemapMax);
3507 }
3508 uelen = u_unescape(*expResultsPtr, uexp, kUBufRemapMax);
3509 ulen = uadatpg_remapPatternWithOptions(dtpg, upatn, ulen, (UDateTimePatternMatchOptions)testItemPtr->options, uget, kUBufRemapMax, &status);
3510 if ( U_FAILURE(status) ) {
3511 log_err("uadatpg_remapPatternWithOptions fails for locale %s pattern \"%s\" opts %08X: status %s\n",
3512 locResPtr->locale, testItemPtr->pattern, testItemPtr->options, u_errorName(status));
3513 } else if (uelen != ulen || u_strncmp(uget, uexp, ulen) != 0) {
3514 char bebuf[kBBufRemapMax];
3515 char bbuf[kBBufRemapMax];
3516 UErrorCode tempStatus = U_ZERO_ERROR;
3517 u_strToUTF8(bebuf, kBBufRemapMax, NULL, uexp, uelen, &tempStatus);
3518 u_strToUTF8(bbuf, kBBufRemapMax, NULL, uget, ulen, &tempStatus);
3519 log_err("uadatpg_remapPatternWithOptions for locale %s pattern \"%s\" opts %08X: expect \"%s\", get \"%s\"\n",
3520 locResPtr->locale, testItemPtr->pattern, testItemPtr->options, bebuf, bbuf);
3521 }
3522 }
3523 udatpg_close(dtpg);
3524 }
3525 }
3526}
3527
3d1f044b
A
3528#if ADD_ALLOC_TEST
3529#include <stdio.h>
3530#include <unistd.h>
3531static const UChar* tzName = u"US/Pacific";
3532static const UDate udatToUse = 1290714600000.0; // Thurs, Nov. 25, 2010 11:50:00 AM PT
3533static const UChar* dateStrEST = u"Thursday, November 25, 2010 at 11:50:00 AM EST";
3534enum { kUCharsOutMax = 128, kBytesOutMax = 256, kRepeatCount = 100, SLEEPSECS = 6 };
3535
3536static void TestPerf(void) {
3537 UDateFormat *udatfmt;
3538 UErrorCode status = U_ZERO_ERROR;
3539 printf("\n# TestPerf start; sleeping %d seconds to check heap.\n", SLEEPSECS); sleep(SLEEPSECS);
3540 udatfmt = udat_open(UDAT_FULL, UDAT_FULL, "en_US", tzName, -1, NULL, 0, &status);
3541 if ( U_SUCCESS(status) ) {
3542 UChar outUChars[kUCharsOutMax];
3543 int32_t count, datlen, datlen2, parsePos;
3544 UDate dateParsed, dateParsed2;
3545
3546 datlen = udat_format(udatfmt, udatToUse, outUChars, kUCharsOutMax, NULL, &status);
3547 printf("# TestPerf after first open & format, status %d; sleeping %d seconds to check heap.\n", status, SLEEPSECS); sleep(SLEEPSECS);
3548
3549 for (count = kRepeatCount; count-- > 0;) {
3550 status = U_ZERO_ERROR;
3551 datlen2 = udat_format(udatfmt, udatToUse, outUChars, kUCharsOutMax, NULL, &status);
3552 if ( U_FAILURE(status) || datlen2 != datlen ) {
3553 printf("# TestPerf udat_format unexpected result.\n");
3554 break;
3555 }
3556 }
3557 printf("# TestPerf after many more format, status %d; sleeping %d seconds to check heap.\n", status, SLEEPSECS); sleep(SLEEPSECS);
3558
3559 udat_setLenient(udatfmt, TRUE);
3560 status = U_ZERO_ERROR;
3561 parsePos = 0;
3562 dateParsed = udat_parse(udatfmt, dateStrEST, -1, &parsePos, &status);
3563 printf("# TestPerf after first parse lenient diff style/zone, status %d; sleeping %d seconds to check heap.\n", status, SLEEPSECS); sleep(SLEEPSECS);
3564
3565 for (count = kRepeatCount; count-- > 0;) {
3566 status = U_ZERO_ERROR;
3567 parsePos = 0;
3568 dateParsed2 = udat_parse(udatfmt, dateStrEST, -1, &parsePos, &status);
3569 if ( U_FAILURE(status) || dateParsed2 != dateParsed ) {
3570 printf("# TestPerf udat_parse unexpected result.\n");
3571 break;
3572 }
3573 }
3574 printf("# TestPerf after many more parse, status %d; sleeping %d seconds to check heap.\n", status, SLEEPSECS); sleep(SLEEPSECS);
3575
3576 udat_close(udatfmt);
3577 printf("# TestPerf after udat_close; sleeping %d seconds to check heap.\n", SLEEPSECS); sleep(SLEEPSECS);
3578 }
3579}
3580#endif /* #if ADD_ALLOC_TEST */
3581
3582#if WRITE_HOUR_MISMATCH_ERRS
3583// WriteHourMismatchErrs stuff 52980140
3584#include <stdio.h>
3585#include <string.h>
3586#include <stdlib.h>
3587
3588static const char* langs[] = {
3589 "ar", "ca", "cs", "da", "de", "el", "en", "es", "fi", "fr", "he",
3590 "hi", "hr", "hu", "id", "it", "ja", "ko", "ms", "nb", "nl", "pl",
3591 "pt", "ro", "ru", "sk", "sv", "th", "tr", "uk", "vi", "zh" }; // handle "yue" separately
3592enum { kNlangs = sizeof(langs)/sizeof(langs[0]) };
3593
3594static const char* cals[] = {
3595 "buddhist",
3596 "chinese",
3597 "coptic",
3598 "ethiopic",
3599 "gregorian",
3600 "hebrew",
3601 "indian",
3602 "islamic-umalqura",
3603 "islamic",
3604 "japanese",
3605 "persian",
3606 NULL
3607};
3608
3609enum { kLBufMax = 63 };
3610
3611static int compKeys(const void* keyval, const void* baseval) {
3612 const char* keystr = (const char*)keyval;
3613 const char* basestr = *(const char**)baseval;
3614 return strcmp(keystr,basestr);
3615}
3616
3617static UBool useLocale(const char* locale) {
3618 if (strncmp(locale, "yue", 3) == 0) {
3619 return TRUE;
3620 }
3621 if (locale[2]==0 || locale[2]=='_') {
3622 char lang[3] = {0,0,0};
3623 strncpy(lang,locale,2);
3624 if (bsearch(&lang, langs, kNlangs, sizeof(char*), compKeys) != NULL) {
3625 return TRUE;
3626 }
3627 }
3628 return FALSE;
3629}
3630
3631static UBool patIsBad(const UChar* ubuf) {
3632 return (u_strchr(ubuf,0x251C)!=NULL || u_strchr(ubuf,0x2524)!=NULL || u_strstr(ubuf,u": ")!=NULL);
3633}
3634
3635
3636static void WriteHourMismatchErrs(void) { /* Apple-specific */
3637 int32_t iloc, nloc = uloc_countAvailable();
3638 int32_t errcnt = 0;
3639 printf("# uloc_countAvailable: %d\n", nloc);
3640 for (iloc = 0; iloc < nloc; iloc++) {
3641 const char* locale = uloc_getAvailable(iloc);
3642 if (useLocale(locale)) {
3643 const char** calsPtr = cals;
3644 const char* cal;
3645 while ((cal = *calsPtr++) != NULL) {
3646 char fullLocale[kLBufMax+1];
3647 UErrorCode status = U_ZERO_ERROR;
3648 strncpy(fullLocale, locale, kLBufMax);
3649 fullLocale[kLBufMax] = 0;
3650 uloc_setKeywordValue("calendar", cal, fullLocale, kLBufMax, &status);
3651 if ( U_SUCCESS(status) ) {
3652 fullLocale[kLBufMax] = 0;
3653 UDateFormat* udat = udat_open(UDAT_SHORT, UDAT_NONE, fullLocale, NULL, 0, NULL, 0, &status);
3654 UDateTimePatternGenerator* udatpg = udatpg_open(fullLocale, &status);
3655 if ( U_FAILURE(status) ) {
3656 printf("# udat_open/udatpg_open for locale %s: %s\n", fullLocale, u_errorName(status));
3657 } else {
3658 UChar ubufs[kUBufMax];
3659 UChar ubufp[kUBufMax];
3660 char bbufs[kBBufMax];
3661 char bbufpj[kBBufMax];
3662 char bbufpH[kBBufMax];
3663 char bbufph[kBBufMax];
3664 int32_t ulen;
3665 int8_t errors[4] = {0,0,0,0};
3666
3667 status = U_ZERO_ERROR;
3668 ulen = udat_toPattern(udat, FALSE, ubufs, kUBufMax, &status);
3669 u_strToUTF8(bbufs, kBBufMax, NULL, ubufs, ulen, &status);
3670 if ( U_FAILURE(status) ) {
3671 printf("# udat_toPattern for locale %s: %s\n", fullLocale, u_errorName(status));
3672 strcpy(bbufs, "****");
3673 errors[0] = 3;
3674 } else if (patIsBad(ubufs)) {
3675 errors[0] = 2;
3676 }
3677
3678 status = U_ZERO_ERROR;
3679 ulen = udatpg_getBestPattern(udatpg, u"jmm", 3, ubufp, kUBufMax, &status);
3680 u_strToUTF8(bbufpj, kBBufMax, NULL, ubufp, ulen, &status);
3681 if ( U_FAILURE(status) ) {
3682 printf("# udatpg_getBestPat jmm for locale %s: %s\n", fullLocale, u_errorName(status));
3683 strcpy(bbufpj, "****");
3684 errors[1] = 3;
3685 } else if (patIsBad(ubufp)) {
3686 errors[1] = 2;
3687 } else if (errors[0] == 0 && u_strcmp(ubufp,ubufs) != 0) {
3688 errors[0] = 1;
3689 }
3690
3691 status = U_ZERO_ERROR;
3692 ulen = udatpg_getBestPattern(udatpg, u"Hmm", 3, ubufp, kUBufMax, &status);
3693 u_strToUTF8(bbufpH, kBBufMax, NULL, ubufp, ulen, &status);
3694 if ( U_FAILURE(status) ) {
3695 printf("# udatpg_getBestPat Hmm for locale %s: %s\n", fullLocale, u_errorName(status));
3696 strcpy(bbufpH, "****");
3697 errors[2] = 3;
3698 } else if (patIsBad(ubufp)) {
3699 errors[2] = 2;
3700 }
3701
3702 status = U_ZERO_ERROR;
3703 ulen = udatpg_getBestPattern(udatpg, u"hmm", 3, ubufp, kUBufMax, &status);
3704 u_strToUTF8(bbufph, kBBufMax, NULL, ubufp, ulen, &status);
3705 if ( U_FAILURE(status) ) {
3706 printf("# udatpg_getBestPat hmm for locale %s: %s\n", fullLocale, u_errorName(status));
3707 strcpy(bbufph, "****");
3708 errors[3] = 3;
3709 } else if (patIsBad(ubufp)) {
3710 errors[3] = 2;
3711 }
3712
3713 if ( errors[0] || errors[1] || errors[2] || errors[3]) {
3714 printf("%-36s\tshr-%d %-8s\tjmm-%d %-18s\tHmm-%d %-18s\thmm-%d %-18s\n", fullLocale,
3715 errors[0], bbufs, errors[1], bbufpj, errors[2], bbufpH, errors[3], bbufph);
3716 errcnt++;
3717 }
3718
3719 udatpg_close(udatpg);
3720 udat_close(udat);
3721 }
3722 }
3723 }
3724 }
3725 }
3726 printf("# total err lines: %d\n", errcnt);
3727}
3728#endif /* #if WRITE_HOUR_MISMATCH_ERRS */
3729
340931cb
A
3730#if WRITE_COUNTRY_FALLBACK_RESULTS
3731// A utility program for printing out the results of our formatting code for vetting. The list of locales
3732// below is the top 100 non-default-language locales from internal statistics on system locales.
3733static void WriteCountryFallbackResults(void) { /* Apple <rdar://problem/26911014> */
3734 char* systemLanguages[] = {
3735 "en",
3736 "zh-Hans",
3737 "zh-Hant",
3738 "ja",
3739 "es",
3740 "fr",
3741 "de",
3742 "ru",
3743 "pt",
3744 "it",
3745 "ko",
3746 "tr",
3747 "nl",
3748 "ar",
3749 "th",
3750 "sv",
3751 "da",
3752 "vi",
3753 "nb",
3754 "pl",
3755 "fi",
3756 "id",
3757 "he",
3758 "el",
3759 "ro",
3760 "hu",
3761 "cs",
3762 "ca",
3763 "sk",
3764 "uk",
3765 "hr",
3766 "ms",
3767 "hi",
3768 };
3769 char* styleNames[] = {
3770 "full",
3771 "long",
3772 "medium",
3773 "short"
3774 };
3775
3776 UErrorCode err = U_ZERO_ERROR;
3777 UCalendar* cal = ucal_open(NULL, -1, "en_US", UCAL_GREGORIAN, &err);
3778 ucal_setDateTime(cal, 2017, UCAL_DECEMBER, 24, 20, 35, 15, &err);
3779 assertSuccess("Error creating test calendar", &err);
3780 const char* const* countries = uloc_getISOCountries();
3781
3782 printf("locale\tstyle\tafter\n");
3783 for (int32_t i = 0; i < (sizeof(systemLanguages) / sizeof(char*)); i++) {
3784 const char* language = systemLanguages[i];
3785 char errorMessage[200];
3786 err = U_ZERO_ERROR;
3787
3788 char locale[50];
3789// UChar defaultResults[4][200];
3790
3791 uloc_addLikelySubtags(language, locale, 50, &err);
3792// uloc_minimizeSubtags(locale, locale, 50, &err);
3793 if (U_FAILURE(err)) {
3794 continue;
3795 }
3796// for (UDateFormatStyle style = UDAT_FULL; style <= UDAT_SHORT; ++style) {
3797// err = U_ZERO_ERROR;
3798// UDateFormat* df = udat_open(/*style*/UDAT_NONE, style, locale, NULL, 0, NULL, 0, &err);
3799// UChar formattedDate[200];
3800//
3801// udat_formatCalendar(df, cal, formattedDate, 200, NULL, &err);
3802// assertSuccess("Error formatting date", &err);
3803//
3804// printf("%s\t%s\t%s\t%s\n", locale, "D", styleNames[style], austrdup(formattedDate));
3805// u_strcpy(defaultResults[style], formattedDate);
3806//
3807// udat_close(df);
3808// }
3809
3810 for (int32_t j = 0; countries[j] != NULL; j++) {
3811 sprintf(locale, "%s_%s", language, countries[j]);
3812
3813// UBool hasResourceBundle = FALSE;
3814// UResourceBundle* bundle = ures_open(NULL, locale, &err);
3815// hasResourceBundle = err != U_USING_FALLBACK_WARNING;
3816// ures_close(bundle);
3817
3818 for (UDateFormatStyle style = UDAT_FULL; style <= UDAT_SHORT; ++style) {
3819 err = U_ZERO_ERROR;
3820 UDateFormat* df = udat_open(/*style*/UDAT_NONE, style, locale, NULL, 0, NULL, 0, &err);
3821 UChar formattedDate[200];
3822
3823 udat_formatCalendar(df, cal, formattedDate, 200, NULL, &err);
3824 assertSuccess("Error formatting date", &err);
3825
3826// if (u_strcmp(defaultResults[style], formattedDate) != 0) {
3827 printf("%s\t%s\t%s\n", locale, styleNames[style], austrdup(formattedDate));
3828// }
3829
3830 udat_close(df);
3831 }
3832 }
3833 }
3834 ucal_close(cal);
3835}
3836#endif /*WRITE_COUNTRY_FALLBACK_RESULTS*/
3837
3838UBool stringsEqualWithoutBidiMarks(const UChar* s1, const UChar* s2) {
3839 while (*s1 != u'\0' || *s2 != u'\0') {
3840 if (*s1 == *s2) {
3841 ++s1;
3842 ++s2;
3843 } else if (*s1 == u'\u200f') {
3844 ++s1;
3845 } else if (*s2 == u'\u200f') {
3846 ++s2;
3847 } else {
3848 return FALSE;
3849 }
3850 }
3851 return TRUE;
3852}
3853
3854static void TestCountryFallback(void) { /* Apple <rdar://problem/26911014> */
3855 // The columns in the table below are as follows:
3856 // 1: The test locale ID. The locale for which we're testing the date formats.
3857 // 2: Long date locale. The full and long date formats for the test locale should match this locale.
3858 // 3: Medium date locale. The medium date format for the test locale should match this locale. If this starts with
3859 // a *, compare against the SHORT date format from this locale (without the *, of course)
3860 // 4: Short date locale. The short date format for the test locale should match this locale.
3861 char* testData[] = {
3862 // The following locales were previously handled by adding resource bundles. If the short or medium date formats
3863 // in the resources don't match what the algorithmic solution would produce, that's called out in the comments.
3864 // If the full or long formats are different, or there's no fallback resource we can match, the whole line
3865 // is commented out.
3866 "en_AD", "en_150", "ca_AD", "ca_AD",
3867 "en_AR", "en_001", "es_AR", "en_001", // short date pattern for es_AR is different?
3868// "en_BR", "en_001", "en_001", "en_001", // short date pattern is different from both pt_BR and en_001
3869 "en_CL", "en_001", "es_CL", "es_CL",
3870 "en_CN", "en", "en", "zh_CN",
3871// "en_CO", "en_001", "*es_CO", "es_CO", // medium date pattern is wrong?
3872// "en_DE", "de_DE", "de_DE", "de_DE", // medium date pattern is wrong?
3873 "en_ER", "en_001", "en_001", "en_001", // short date pattern for ti_ER is different?
3874 "en_ES", "en_150", "en_150", "es_ES",
3875 "en_GH", "en_001", "en_001", "en_001", // short date pattern for ak_GH is different?
3876 "en_GR", "en_150", "el_GR", "el_GR",
3877 "en_HK", "en_001", "en_001", "zh_HK",
3878 "en_IS", "en_150", "en_150", "is_IS",
3879 "en_IT", "en_150", "en_150", "it_IT",
3880 "en_JP", "en", "en", "ja_JP",
3881// "en_KR", "en", "en", "ko_KR", // short date pattern is different?
3882 "en_LU", "en_150", "fr_LU", "fr_LU",
3883 "en_ME", "en_150", "sr_ME", "sr_ME",
3884 "en_MO", "en_001", "en_001", "en_001", // short and medium date patterns for zh_MO are different?
3885// "en_MT", "en_150", "en_150", "mt_MT", // several patterns are different from both en_150 and mt_MT
3886 "en_MX", "en_001", "es_MX", "es_MX",
3887 "en_MY", "en_001", "en_001", "en_001", // short date pattern for ms_MY is different?
3888 "en_NL", "en_150", "en_150", "en_150", // short date pattern for nl_NL is different?
3889 "en_PH", "en", "fil_PH", "fil_PH",
3890 "en_RO", "en_150", "en_150", "ro_RO",
3891 "en_RS", "en_150", "sr_RS", "sr_RS",
3892// "en_TR", "en_150", "en_150", "tr_TR", // long date pattern for en_150 is different
3893 "en_TW", "en", "en", "zh_TW",
3894// "en_ZW", "en_001", "en_001", "sn_ZW", // all date patterns are different from en_001 and sn_ZW
3895 "es_US", "es_419", "en_US", "en_US",
3896
3897 // The following locales are specifically mentioned in Radars (some of these have resource bundles too):
3898 "fr_US", "fr", "fr", "en_US", // rdar://problem/54886964
3899// "en_TH", "en_001", "en_001", "en_001", // rdar://problem/29299919 (the en_TH resource has era fields, even in Gregorian calendar, and they're in a different place than for the Buddhist calendar)
3900// "en_BG", "en_150", "en_150", "en_150", // rdar://problem/29299919 (all date patterns for bg_BG have "'г'." at the end, short date pattern also doesn't match en_150)
3901 "fr_BG", "fr", "fr", "fr", // rdar://64135398
3902 "en_LI", "en_150", "de_LI", "de_LI", // rdar://problem/29299919
3903 "en_MC", "en_150", "fr_MC", "fr_MC", // rdar://problem/29299919
3904 "en_MD", "en_150", "ro_MD", "ro_MD", // rdar://problem/29299919
3905 "en_VA", "en_150", "it_VA", "it_VA", // rdar://problem/29299919
3906 "fr_GB", "fr", "fr", "en_GB", // rdar://problem/36020946
3907 "fr_CN", "fr", "fr", "zh_CN", // rdar://problem/50083902
3908 "es_IE", "es", "es", "en_IE", // rdar://problem/58733843
3909 "de_US", "de", "*en_US", "en_US", // rdar://problem/31169349 (I think we no longer address this Radar...)
3910// "en_CZ", "en_150", "cs_CZ", "cs_CZ", // rdar://problem/57625632 (Long date format doesn't match en_150)
3911
3912 // Special for en_SA, date formats should match those for en_001, other items match en
3913 "en_SA", "en_001@calendar=islamic-umalqura", "en_001@calendar=islamic-umalqura", "en_001@calendar=islamic-umalqura",
3914
3915 // Tests for situations where the default calendar and/or numbering system is different depending on whether you
3916 // fall back by language or by country:
3917 "ar_US", "ar", "ar", "ar",
3918 "ar_DE", "ar", "ar", "ar", // rdar://67971515
3919 "ar_FR", "ar", "ar", "ar", // rdar://67971515
3920 "en_EG", "en_001", "en_001", "en_001", // rdar://69523017
3921
3922 // Tests for situations where the original locale ID specifies a script:
3923 // this one doesn't fall back to ar_SA because even the "short" date format in arSA is non-numeric
3924 "sr_Cyrl_SA", "sr_Cyrl@calendar=islamic-umalqura", "sr_Cyrl@calendar=islamic-umalqura", "sr_Cyrl@calendar=islamic-umalqura",
3925 "ru_Cyrl_BA", "ru_Cyrl", "bs_Cyrl_BA", "bs_Cyrl_BA",
3926
3927 // And these are just a few additional arbitrary combinations:
3928 "ja_US", "ja", "*en_US", "en_US",
3929 "fr_DE", "fr", "de_DE", "de_DE",
3930 "de_FR", "de", "*fr_FR", "fr_FR",
3931 "es_TW", "es", "es", "zh_TW",
3932 "en_BH", "en_001", "en_001", "en_001",
3933 // Test to make sure that nothing goes wrong if language and country fallback both lead to the same resource
3934 // (This won't happen for any "real" locales, because ICU has resources for all of them, but we can fake it with
3935 // a nonexistent country code such as QQ.)
3936 "en_QQ", "en", "en", "en"
3937 };
3938
3939 for (int32_t i = 0; i < (sizeof(testData) / sizeof(char*)); i += 4) {
3940 const char* testLocale = testData[i];
3941 const char* longDateLocale = testData[i + 1];
3942 const char* mediumDateLocale = testData[i + 2];
3943 const char* shortDateLocale = testData[i + 3];
3944 char errorMessage[200];
3945 UErrorCode err = U_ZERO_ERROR;
3946
3947 // Check that the date formatting patterns for the test locale are the same as those for the fallback locale.
3948 for (UDateFormatStyle style = UDAT_FULL; style <= UDAT_SHORT; ++style) {
3949 err = U_ZERO_ERROR;
3950 UDateFormat* testFormatter = udat_open(UDAT_NONE, style, testLocale, NULL, 0, NULL, 0, &err);
3951 const char* comparisonLocale = longDateLocale;
3952 if (style == UDAT_MEDIUM) {
3953 comparisonLocale = mediumDateLocale;
3954 } else if (style == UDAT_SHORT) {
3955 comparisonLocale = shortDateLocale;
3956 }
3957 UDateFormat* comparisonFormatter = NULL;
3958 if (comparisonLocale[0] == '*') {
3959 // if the comparison locale starts with a *, strip off the * and retrieve the SHORT date format
3960 // from that locale regardless of what style we're actually on (should only happen when
3961 // style is UDAT_MEDIUM)
3962 comparisonFormatter = udat_open(UDAT_NONE, UDAT_SHORT, &(comparisonLocale[1]), NULL, 0, NULL, 0, &err);
3963 } else {
3964 comparisonFormatter = udat_open(UDAT_NONE, style, comparisonLocale, NULL, 0, NULL, 0, &err);
3965 }
3966
3967 sprintf(errorMessage, "Error creating formatters for %s and %s", testLocale, comparisonLocale);
3968 if (assertSuccess(errorMessage, &err)) {
3969 UChar testPattern[100];
3970 UChar comparisonPattern[100];
3971
3972 udat_toPattern(testFormatter, FALSE, testPattern, 100, &err);
3973 udat_toPattern(comparisonFormatter, FALSE, comparisonPattern, 100, &err);
3974
3975 if (assertSuccess("Error getting date format patterns", &err)) {
3976 sprintf(errorMessage, "In %s, formatting pattern for style %d doesn't match: expected %s, got %s", testLocale, style, austrdup(comparisonPattern), austrdup(testPattern));
3977 assertTrue(errorMessage, stringsEqualWithoutBidiMarks(comparisonPattern, testPattern));
3978 }
3979
3980 const UNumberFormat* testNF = udat_getNumberFormat(testFormatter);
3981 const UNumberFormat* comparisonNF = udat_getNumberFormat(comparisonFormatter);
3982 UChar testZeroDigit[5];
3983 UChar comparisonZeroDigit[5];
3984 unum_getSymbol(testNF, UNUM_ZERO_DIGIT_SYMBOL, testZeroDigit, 5, &err);
3985 unum_getSymbol(comparisonNF, UNUM_ZERO_DIGIT_SYMBOL, comparisonZeroDigit, 5, &err);
3986
3987 if (assertSuccess("Error getting zero digits", &err)) {
3988 sprintf(errorMessage, "In %s, zero digits for style %d don't match: ", testLocale, style);
3989 assertUEquals(errorMessage, comparisonZeroDigit, testZeroDigit);
3990 }
3991 }
3992 udat_close(testFormatter);
3993 udat_close(comparisonFormatter);
3994 }
3995
3996 // The TestCountryFallback test for number formatting also checks to make sure that we still fall back by
3997 // language for certain number formatting symbols. The time and date+time patterns should continue to fall back
3998 // by language, but we don't test that here for two reasons: a) There's no way to explicitly get the date+time
3999 // pattern by itself, and b) even though time patterns technically fall back by language, there's extra logic
4000 // to synthesize a time pattern in cases where there's no resource bundle for the requested locale and the
4001 // requested country has a different time cycle than the default country for the requested language.
4002 // Accounting for both of these would require changing this test to compare the results against hard-coded
4003 // pattern strings, which I don't want to do yet. --rtg 4/30/20
4004 // (NOTE: I might need to change the comment above when I fix rdar://problem/62242807)
4005 }
4006}
b75a7d8f 4007#endif /* #if !UCONFIG_NO_FORMATTING */