1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
4 * COPYRIGHT:
5 * Copyright (c) 1997-2016, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 ********************************************************************/
8 /********************************************************************************
9 *
10 * File CDATTST.C
11 *
12 * Modification History:
13 * Name Description
14 * Madhu Katragadda Creation
15 *********************************************************************************
16 */
17
18 /* C API TEST FOR DATE FORMAT */
19
20 #include "unicode/utypes.h"
21
22 #if !UCONFIG_NO_FORMATTING
23
24 #include "unicode/uloc.h"
25 #include "unicode/udat.h"
26 #include "unicode/udatpg.h"
27 #include "unicode/ucal.h"
28 #include "unicode/unum.h"
29 #include "unicode/ustring.h"
30 #include "unicode/ufieldpositer.h"
31 #include "cintltst.h"
32 #include "cdattst.h"
33 #include "cformtst.h"
34 #include "cmemory.h"
35
36 #include <math.h>
37 #include <stdbool.h>
38
39 static void TestExtremeDates(void);
40 static void TestAllLocales(void);
41 static void TestRelativeCrash(void);
42 static void TestContext(void);
43 static void TestCalendarDateParse(void);
44 static void TestParseErrorReturnValue(void);
45 static void TestFormatForFields(void);
46 static void TestForceGannenNumbering(void);
47 static void TestMapDateToCalFields(void);
48 static void TestNarrowQuarters(void);
49 static void TestExtraneousCharacters(void);
50
51 void addDateForTest(TestNode** root);
52
53 #define TESTCASE(x) addTest(root, &x, "tsformat/cdattst/" #x)
54
addDateForTest(TestNode ** root)55 void addDateForTest(TestNode** root)
56 {
57 TESTCASE(TestDateFormat);
58 TESTCASE(TestRelativeDateFormat);
59 TESTCASE(TestSymbols);
60 TESTCASE(TestDateFormatCalendar);
61 TESTCASE(TestExtremeDates);
62 TESTCASE(TestAllLocales);
63 TESTCASE(TestRelativeCrash);
64 TESTCASE(TestContext);
65 TESTCASE(TestCalendarDateParse);
66 TESTCASE(TestOverrideNumberFormat);
67 TESTCASE(TestParseErrorReturnValue);
68 TESTCASE(TestFormatForFields);
69 TESTCASE(TestForceGannenNumbering);
70 TESTCASE(TestMapDateToCalFields);
71 TESTCASE(TestNarrowQuarters);
72 TESTCASE(TestExtraneousCharacters);
73 }
74 /* Testing the DateFormat API */
TestDateFormat()75 static void TestDateFormat()
76 {
77 UDateFormat *def, *fr, *it, *de, *def1, *fr_pat;
78 UDateFormat *any;
79 UDateFormat *copy;
80 UErrorCode status = U_ZERO_ERROR;
81 UChar* result = NULL;
82 const UCalendar *cal;
83 const UNumberFormat *numformat1, *numformat2;
84 UNumberFormat *adoptNF;
85 UChar temp[80];
86 int32_t numlocales;
87 UDate d1;
88 int i;
89 int32_t resultlength;
90 int32_t resultlengthneeded;
91 int32_t parsepos;
92 UDate d = 837039928046.0;
93 double num = -10456.37;
94 /*const char* str="yyyy.MM.dd G 'at' hh:mm:ss z";
95 const char t[]="2/3/76 2:50 AM";*/
96 /*Testing udat_open() to open a dateformat */
97
98 ctest_setTimeZone(NULL, &status);
99
100 log_verbose("\nTesting udat_open() with various parameters\n");
101 fr = udat_open(UDAT_FULL, UDAT_DEFAULT, "fr_FR", NULL,0, NULL, 0,&status);
102 if(U_FAILURE(status))
103 {
104 log_data_err("FAIL: error in creating the dateformat using full time style with french locale -> %s (Are you missing data?)\n",
105 myErrorName(status) );
106 return;
107 }
108 /* this is supposed to open default date format, but later on it treats it like it is "en_US"
109 - very bad if you try to run the tests on machine where default locale is NOT "en_US" */
110 /* def = udat_open(UDAT_SHORT, UDAT_SHORT, NULL, NULL, 0, &status); */
111 def = udat_open(UDAT_SHORT, UDAT_SHORT, "en_US", NULL, 0,NULL, 0, &status);
112 if(U_FAILURE(status))
113 {
114 log_err("FAIL: error in creating the dateformat using short date and time style\n %s\n",
115 myErrorName(status) );
116 return;
117 }
118 it = udat_open(UDAT_DEFAULT, UDAT_MEDIUM, "it_IT", NULL, 0, NULL, 0,&status);
119 if(U_FAILURE(status))
120 {
121 log_err("FAIL: error in creating the dateformat using medium date style with italian locale\n %s\n",
122 myErrorName(status) );
123 return;
124 }
125 de = udat_open(UDAT_LONG, UDAT_LONG, "de_DE", NULL, 0, NULL, 0,&status);
126 if(U_FAILURE(status))
127 {
128 log_err("FAIL: error in creating the dateformat using long time and date styles with german locale\n %s\n",
129 myErrorName(status));
130 return;
131 }
132 /*creating a default dateformat */
133 def1 = udat_open(UDAT_SHORT, UDAT_SHORT, NULL, NULL, 0,NULL, 0, &status);
134 if(U_FAILURE(status))
135 {
136 log_err("FAIL: error in creating the dateformat using short date and time style\n %s\n",
137 myErrorName(status) );
138 return;
139 }
140
141
142 /*Testing udat_getAvailable() and udat_countAvailable()*/
143 log_verbose("\nTesting getAvailableLocales and countAvailable()\n");
144 numlocales=udat_countAvailable();
145 /* use something sensible w/o hardcoding the count */
146 if(numlocales < 0)
147 log_data_err("FAIL: error in countAvailable\n");
148 log_verbose("The number of locales for which date/time formatting patterns are available is %d\n", numlocales);
149
150 for(i=0;i<numlocales;i++) {
151 UErrorCode subStatus = U_ZERO_ERROR;
152 log_verbose("Testing open of %s\n", udat_getAvailable(i));
153 any = udat_open(UDAT_SHORT, UDAT_SHORT, udat_getAvailable(i), NULL ,0, NULL, 0, &subStatus);
154 if(U_FAILURE(subStatus)) {
155 log_data_err("FAIL: date format %s (getAvailable(%d)) is not instantiable: %s\n", udat_getAvailable(i), i, u_errorName(subStatus));
156 }
157 udat_close(any);
158 }
159
160 /*Testing udat_clone()*/
161 log_verbose("\nTesting the udat_clone() function of date format\n");
162 copy=udat_clone(def, &status);
163 if(U_FAILURE(status)){
164 log_err("Error in creating the clone using udat_clone: %s\n", myErrorName(status) );
165 }
166 /*if(def != copy)
167 log_err("Error in udat_clone");*/ /*how should i check for equality???? */
168
169 /*Testing udat_format()*/
170 log_verbose("\nTesting the udat_format() function of date format\n");
171 u_strcpy(temp, u"7/10/96, 4:05\u202FPM");
172 /*format using def */
173 resultlength=0;
174 resultlengthneeded=udat_format(def, d, NULL, resultlength, NULL, &status);
175 if(status==U_BUFFER_OVERFLOW_ERROR)
176 {
177 status=U_ZERO_ERROR;
178 resultlength=resultlengthneeded+1;
179 if(result != NULL) {
180 free(result);
181 result = NULL;
182 }
183 result=(UChar*)malloc(sizeof(UChar) * resultlength);
184 udat_format(def, d, result, resultlength, NULL, &status);
185 }
186 if(U_FAILURE(status) || !result)
187 {
188 log_err("FAIL: Error in formatting using udat_format(.....) %s\n", myErrorName(status) );
189 return;
190 }
191 else
192 log_verbose("PASS: formatting successful\n");
193 if(u_strcmp(result, temp)==0)
194 log_verbose("PASS: Date Format for US locale successful using udat_format()\n");
195 else {
196 char xbuf[2048];
197 char gbuf[2048];
198 u_austrcpy(xbuf, temp);
199 u_austrcpy(gbuf, result);
200 log_err("FAIL: Date Format for US locale failed using udat_format() - expected %s got %s\n", xbuf, gbuf);
201 }
202 /*format using fr */
203
204 u_unescape("10 juil. 1996, 16:05:28 heure d\\u2019\\u00E9t\\u00E9 du Pacifique nord-am\\u00E9ricain", temp, 80);
205 if(result != NULL) {
206 free(result);
207 result = NULL;
208 }
209 result=myDateFormat(fr, d);
210 if(u_strcmp(result, temp)==0) {
211 log_verbose("PASS: Date Format for french locale successful using udat_format()\n");
212 } else {
213 char xbuf[2048];
214 char gbuf[2048];
215 u_austrcpy(xbuf, temp);
216 u_austrcpy(gbuf, result);
217 log_data_err("FAIL: Date Format for french locale failed using udat_format() - expected %s got %s\n", xbuf, gbuf);
218 }
219
220 /*format using it */
221 u_uastrcpy(temp, "10 lug 1996, 16:05:28");
222
223 {
224 UChar *fmtted;
225 char g[100];
226 char x[100];
227
228 fmtted = myDateFormat(it,d);
229 u_austrcpy(g, fmtted);
230 u_austrcpy(x, temp);
231 if(u_strcmp(fmtted, temp)==0) {
232 log_verbose("PASS: Date Format for italian locale successful uisng udat_format() - wanted %s, got %s\n", x, g);
233 } else {
234 log_data_err("FAIL: Date Format for italian locale failed using udat_format() - wanted %s, got %s\n", x, g);
235 }
236 }
237
238 /*Testing parsing using udat_parse()*/
239 log_verbose("\nTesting parsing using udat_parse()\n");
240 u_strcpy(temp, u"2/3/76, 2:50\u202FAM");
241 parsepos=0;
242 status=U_ZERO_ERROR;
243
244 d1=udat_parse(def, temp, u_strlen(temp), &parsepos, &status);
245 if(U_FAILURE(status))
246 {
247 log_err("FAIL: Error in parsing using udat_parse(.....) %s\n", myErrorName(status) );
248 }
249 else
250 log_verbose("PASS: parsing successful\n");
251 /*format it back and check for equality */
252
253
254 if(u_strcmp(myDateFormat(def, d1),temp)!=0)
255 log_err("FAIL: error in parsing\n");
256
257 /*Testing parsing using udat_parse()*/
258 log_verbose("\nTesting parsing using udat_parse()\n");
259 u_uastrcpy(temp,"2/Don't parse this part");
260 status=U_ZERO_ERROR;
261
262 d1=udat_parse(def, temp, u_strlen(temp), NULL, &status);
263 if(status != U_PARSE_ERROR)
264 {
265 log_err("FAIL: udat_parse(\"bad string\") passed when it should have failed\n");
266 }
267 else
268 log_verbose("PASS: parsing successful\n");
269
270
271
272 /*Testing udat_openPattern() */
273 status=U_ZERO_ERROR;
274 log_verbose("\nTesting the udat_openPattern with a specified pattern\n");
275 /*for french locale */
276 fr_pat=udat_open(UDAT_PATTERN, UDAT_PATTERN,"fr_FR",NULL,0,temp, u_strlen(temp), &status);
277 if(U_FAILURE(status))
278 {
279 log_err("FAIL: Error in creating a date format using udat_openPattern \n %s\n",
280 myErrorName(status) );
281 }
282 else
283 log_verbose("PASS: creating dateformat using udat_openPattern() successful\n");
284
285
286 /*Testing applyPattern and toPattern */
287 log_verbose("\nTesting applyPattern and toPattern()\n");
288 udat_applyPattern(def1, false, temp, u_strlen(temp));
289 log_verbose("Extracting the pattern\n");
290
291 resultlength=0;
292 resultlengthneeded=udat_toPattern(def1, false, NULL, resultlength, &status);
293 if(status==U_BUFFER_OVERFLOW_ERROR)
294 {
295 status=U_ZERO_ERROR;
296 resultlength=resultlengthneeded + 1;
297 result=(UChar*)malloc(sizeof(UChar) * resultlength);
298 udat_toPattern(def1, false, result, resultlength, &status);
299 }
300 if(U_FAILURE(status))
301 {
302 log_err("FAIL: error in extracting the pattern from UNumberFormat\n %s\n",
303 myErrorName(status) );
304 }
305 if(u_strcmp(result, temp)!=0)
306 log_err("FAIL: Error in extracting the pattern\n");
307 else
308 log_verbose("PASS: applyPattern and toPattern work fine\n");
309
310 if(result != NULL) {
311 free(result);
312 result = NULL;
313 }
314
315
316 /*Testing getter and setter functions*/
317 /*isLenient and setLenient()*/
318 log_verbose("\nTesting the isLenient and setLenient properties\n");
319 udat_setLenient(fr, udat_isLenient(it));
320 if(udat_isLenient(fr) != udat_isLenient(it))
321 log_err("ERROR: setLenient() failed\n");
322 else
323 log_verbose("PASS: setLenient() successful\n");
324
325
326 /*Test get2DigitYearStart set2DigitYearStart */
327 log_verbose("\nTesting the get and set 2DigitYearStart properties\n");
328 d1= udat_get2DigitYearStart(fr_pat,&status);
329 if(U_FAILURE(status)) {
330 log_err("ERROR: udat_get2DigitYearStart failed %s\n", myErrorName(status) );
331 }
332 status = U_ZERO_ERROR;
333 udat_set2DigitYearStart(def1 ,d1, &status);
334 if(U_FAILURE(status)) {
335 log_err("ERROR: udat_set2DigitYearStart failed %s\n", myErrorName(status) );
336 }
337 if(udat_get2DigitYearStart(fr_pat, &status) != udat_get2DigitYearStart(def1, &status))
338 log_err("FAIL: error in set2DigitYearStart\n");
339 else
340 log_verbose("PASS: set2DigitYearStart successful\n");
341 /*try setting it to another value */
342 udat_set2DigitYearStart(de, 2000.0, &status);
343 if(U_FAILURE(status)){
344 log_verbose("ERROR: udat_set2DigitYearStart failed %s\n", myErrorName(status) );
345 }
346 if(udat_get2DigitYearStart(de, &status) != 2000)
347 log_err("FAIL: error in set2DigitYearStart\n");
348 else
349 log_verbose("PASS: set2DigitYearStart successful\n");
350
351
352
353 /*Test getNumberFormat() and setNumberFormat() */
354 log_verbose("\nTesting the get and set NumberFormat properties of date format\n");
355 numformat1=udat_getNumberFormat(fr_pat);
356 udat_setNumberFormat(def1, numformat1);
357 numformat2=udat_getNumberFormat(def1);
358 if(u_strcmp(myNumformat(numformat1, num), myNumformat(numformat2, num)) !=0)
359 log_err("FAIL: error in setNumberFormat or getNumberFormat()\n");
360 else
361 log_verbose("PASS:setNumberFormat and getNumberFormat successful\n");
362
363 /*Test getNumberFormat() and adoptNumberFormat() */
364 log_verbose("\nTesting the get and adopt NumberFormat properties of date format\n");
365 adoptNF= unum_open(UNUM_DEFAULT, NULL, 0, NULL, NULL, &status);
366 udat_adoptNumberFormat(def1, adoptNF);
367 numformat2=udat_getNumberFormat(def1);
368 if(u_strcmp(myNumformat(adoptNF, num), myNumformat(numformat2, num)) !=0)
369 log_err("FAIL: error in adoptNumberFormat or getNumberFormat()\n");
370 else
371 log_verbose("PASS:adoptNumberFormat and getNumberFormat successful\n");
372
373 /*try setting the number format to another format */
374 numformat1=udat_getNumberFormat(def);
375 udat_setNumberFormat(def1, numformat1);
376 numformat2=udat_getNumberFormat(def1);
377 if(u_strcmp(myNumformat(numformat1, num), myNumformat(numformat2, num)) !=0)
378 log_err("FAIL: error in setNumberFormat or getNumberFormat()\n");
379 else
380 log_verbose("PASS: setNumberFormat and getNumberFormat successful\n");
381
382
383
384 /*Test getCalendar and setCalendar*/
385 log_verbose("\nTesting the udat_getCalendar() and udat_setCalendar() properties\n");
386 cal=udat_getCalendar(fr_pat);
387
388
389 udat_setCalendar(def1, cal);
390 if(!ucal_equivalentTo(udat_getCalendar(fr_pat), udat_getCalendar(def1)))
391 log_err("FAIL: Error in setting and getting the calendar\n");
392 else
393 log_verbose("PASS: getting and setting calendar successful\n");
394
395 if(result!=NULL) {
396 free(result);
397 }
398
399 /*Closing the UDateForamt */
400 udat_close(def);
401 udat_close(fr);
402 udat_close(it);
403 udat_close(de);
404 udat_close(def1);
405 udat_close(fr_pat);
406 udat_close(copy);
407
408 ctest_resetTimeZone();
409 }
410
411 /*
412 Test combined relative date formatting (relative date + non-relative time).
413 This is a bit tricky since we can't have static test data for comparison, the
414 relative date formatting is relative to the time the tests are run. We generate
415 the data for comparison dynamically. However, the tests could fail if they are
416 run right at midnight Pacific time and the call to ucal_getNow() is before midnight
417 while the calls to udat_format are after midnight or span midnight.
418 */
419 static const UDate dayInterval = 24.0*60.0*60.0*1000.0;
420 static const UChar trdfZone[] = { 0x0055, 0x0053, 0x002F, 0x0050, 0x0061, 0x0063, 0x0069, 0x0066, 0x0069, 0x0063, 0 }; /* US/Pacific */
421 static const char trdfLocale[] = "en_US";
422 static const UChar minutesPatn[] = { 0x006D, 0x006D, 0 }; /* "mm" */
423 static const UChar monthLongPatn[] = { 0x004D, 0x004D, 0x004D, 0x004D, 0 }; /* "MMMM" */
424 static const UChar monthMediumPatn[] = { 0x004D, 0x004D, 0x004D, 0 }; /* "MMM" */
425 static const UChar monthShortPatn[] = { 0x004D, 0 }; /* "M" */
426 static const UDateFormatStyle dateStylesList[] = { UDAT_FULL, UDAT_LONG, UDAT_MEDIUM, UDAT_SHORT, UDAT_NONE };
427 static const UChar *monthPatnsList[] = { monthLongPatn, monthLongPatn, monthMediumPatn, monthShortPatn, NULL };
428 static const UChar newTimePatn[] = { 0x0048, 0x0048, 0x002C, 0x006D, 0x006D, 0 }; /* "HH,mm" */
429 static const UChar minutesStr[] = { 0x0034, 0x0039, 0 }; /* "49", minutes string to search for in output */
430 enum { kDateOrTimeOutMax = 96, kDateAndTimeOutMax = 192 };
431
432 static const UDate minutesTolerance = 2 * 60.0 * 1000.0;
433 static const UDate daysTolerance = 2 * 24.0 * 60.0 * 60.0 * 1000.0;
434
TestRelativeDateFormat()435 static void TestRelativeDateFormat()
436 {
437 UDate today = 0.0;
438 const UDateFormatStyle * stylePtr;
439 const UChar ** monthPtnPtr;
440 UErrorCode status = U_ZERO_ERROR;
441 UCalendar * ucal = ucal_open(trdfZone, -1, trdfLocale, UCAL_GREGORIAN, &status);
442 if ( U_SUCCESS(status) ) {
443 int32_t year, month, day;
444 ucal_setMillis(ucal, ucal_getNow(), &status);
445 year = ucal_get(ucal, UCAL_YEAR, &status);
446 month = ucal_get(ucal, UCAL_MONTH, &status);
447 day = ucal_get(ucal, UCAL_DATE, &status);
448 ucal_setDateTime(ucal, year, month, day, 18, 49, 0, &status); /* set to today at 18:49:00 */
449 today = ucal_getMillis(ucal, &status);
450 ucal_close(ucal);
451 }
452 if ( U_FAILURE(status) || today == 0.0 ) {
453 log_data_err("Generate UDate for a specified time today fails, error %s - (Are you missing data?)\n", myErrorName(status) );
454 return;
455 }
456 for (stylePtr = dateStylesList, monthPtnPtr = monthPatnsList; *stylePtr != UDAT_NONE; ++stylePtr, ++monthPtnPtr) {
457 UDateFormat* fmtRelDateTime;
458 UDateFormat* fmtRelDate;
459 UDateFormat* fmtTime;
460 int32_t dayOffset, limit;
461 UFieldPosition fp;
462 UChar strDateTime[kDateAndTimeOutMax];
463 UChar strDate[kDateOrTimeOutMax];
464 UChar strTime[kDateOrTimeOutMax];
465 UChar * strPtr;
466 int32_t dtpatLen;
467
468 fmtRelDateTime = udat_open(UDAT_SHORT, *stylePtr | UDAT_RELATIVE, trdfLocale, trdfZone, -1, NULL, 0, &status);
469 if ( U_FAILURE(status) ) {
470 log_data_err("udat_open timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s (Are you missing data?)\n", *stylePtr, myErrorName(status) );
471 continue;
472 }
473 fmtRelDate = udat_open(UDAT_NONE, *stylePtr | UDAT_RELATIVE, trdfLocale, trdfZone, -1, NULL, 0, &status);
474 if ( U_FAILURE(status) ) {
475 log_err("udat_open timeStyle NONE dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
476 udat_close(fmtRelDateTime);
477 continue;
478 }
479 fmtTime = udat_open(UDAT_SHORT, UDAT_NONE, trdfLocale, trdfZone, -1, NULL, 0, &status);
480 if ( U_FAILURE(status) ) {
481 log_err("udat_open timeStyle SHORT dateStyle NONE fails, error %s\n", myErrorName(status) );
482 udat_close(fmtRelDateTime);
483 udat_close(fmtRelDate);
484 continue;
485 }
486
487 dtpatLen = udat_toPatternRelativeDate(fmtRelDateTime, strDate, kDateAndTimeOutMax, &status);
488 if ( U_FAILURE(status) ) {
489 log_err("udat_toPatternRelativeDate timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
490 status = U_ZERO_ERROR;
491 } else if ( u_strstr(strDate, *monthPtnPtr) == NULL || dtpatLen != u_strlen(strDate) ) {
492 log_err("udat_toPatternRelativeDate timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) date pattern incorrect\n", *stylePtr );
493 }
494 dtpatLen = udat_toPatternRelativeTime(fmtRelDateTime, strTime, kDateAndTimeOutMax, &status);
495 if ( U_FAILURE(status) ) {
496 log_err("udat_toPatternRelativeTime timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
497 status = U_ZERO_ERROR;
498 } else if ( u_strstr(strTime, minutesPatn) == NULL || dtpatLen != u_strlen(strTime) ) {
499 log_err("udat_toPatternRelativeTime timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) time pattern incorrect\n", *stylePtr );
500 }
501 dtpatLen = udat_toPattern(fmtRelDateTime, false, strDateTime, kDateAndTimeOutMax, &status);
502 if ( U_FAILURE(status) ) {
503 log_err("udat_toPattern timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
504 status = U_ZERO_ERROR;
505 } else if ( u_strstr(strDateTime, strDate) == NULL || u_strstr(strDateTime, strTime) == NULL || dtpatLen != u_strlen(strDateTime) ) {
506 log_err("udat_toPattern timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) dateTime pattern incorrect\n", *stylePtr );
507 }
508 udat_applyPatternRelative(fmtRelDateTime, strDate, u_strlen(strDate), newTimePatn, u_strlen(newTimePatn), &status);
509 if ( U_FAILURE(status) ) {
510 log_err("udat_applyPatternRelative timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
511 status = U_ZERO_ERROR;
512 } else {
513 udat_toPattern(fmtRelDateTime, false, strDateTime, kDateAndTimeOutMax, &status);
514 if ( U_FAILURE(status) ) {
515 log_err("udat_toPattern timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
516 status = U_ZERO_ERROR;
517 } else if ( u_strstr(strDateTime, newTimePatn) == NULL ) {
518 log_err("udat_applyPatternRelative timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) didn't update time pattern\n", *stylePtr );
519 }
520 }
521 udat_applyPatternRelative(fmtRelDateTime, strDate, u_strlen(strDate), strTime, u_strlen(strTime), &status); /* restore original */
522
523 fp.field = UDAT_MINUTE_FIELD;
524 for (dayOffset = -2, limit = 2; dayOffset <= limit; ++dayOffset) {
525 UDate dateToUse = today + (float)dayOffset*dayInterval;
526
527 udat_format(fmtRelDateTime, dateToUse, strDateTime, kDateAndTimeOutMax, &fp, &status);
528 if ( U_FAILURE(status) ) {
529 log_err("udat_format timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
530 status = U_ZERO_ERROR;
531 } else {
532 int32_t parsePos = 0;
533 UDate dateResult = udat_parse(fmtRelDateTime, strDateTime, -1, &parsePos, &status);
534 UDate dateDiff = (dateResult >= dateToUse)? dateResult - dateToUse: dateToUse - dateResult;
535 if ( U_FAILURE(status) || dateDiff > minutesTolerance ) {
536 log_err("udat_parse timeStyle SHORT dateStyle (%d | UDAT_RELATIVE) fails, error %s, expect approx %.1f, got %.1f, parsePos %d\n",
537 *stylePtr, myErrorName(status), dateToUse, dateResult, parsePos );
538 status = U_ZERO_ERROR;
539 }
540
541 udat_format(fmtRelDate, dateToUse, strDate, kDateOrTimeOutMax, NULL, &status);
542 if ( U_FAILURE(status) ) {
543 log_err("udat_format timeStyle NONE dateStyle (%d | UDAT_RELATIVE) fails, error %s\n", *stylePtr, myErrorName(status) );
544 status = U_ZERO_ERROR;
545 } else if ( u_strstr(strDateTime, strDate) == NULL ) {
546 log_err("relative date string not found in udat_format timeStyle SHORT dateStyle (%d | UDAT_RELATIVE)\n", *stylePtr );
547 } else {
548 parsePos = 0;
549 dateResult = udat_parse(fmtRelDate, strDate, -1, &parsePos, &status);
550 dateDiff = (dateResult >= dateToUse)? dateResult - dateToUse: dateToUse - dateResult;
551 if ( U_FAILURE(status) || dateDiff > daysTolerance ) {
552 log_err("udat_parse timeStyle NONE dateStyle (%d | UDAT_RELATIVE) fails, error %s, expect approx %.1f, got %.1f, parsePos %d\n",
553 *stylePtr, myErrorName(status), dateToUse, dateResult, parsePos );
554 status = U_ZERO_ERROR;
555 }
556 }
557
558 udat_format(fmtTime, dateToUse, strTime, kDateOrTimeOutMax, NULL, &status);
559 if ( U_FAILURE(status) ) {
560 log_err("udat_format timeStyle SHORT dateStyle NONE fails, error %s\n", myErrorName(status) );
561 status = U_ZERO_ERROR;
562 } else if ( u_strstr(strDateTime, strTime) == NULL ) {
563 log_err("time string not found in udat_format timeStyle SHORT dateStyle (%d | UDAT_RELATIVE)\n", *stylePtr );
564 }
565
566 strPtr = u_strstr(strDateTime, minutesStr);
567 if ( strPtr != NULL ) {
568 int32_t beginIndex = (int32_t)(strPtr - strDateTime);
569 if ( fp.beginIndex != beginIndex ) {
570 log_err("UFieldPosition beginIndex %d, expected %d, in udat_format timeStyle SHORT dateStyle (%d | UDAT_RELATIVE)\n", fp.beginIndex, beginIndex, *stylePtr );
571 }
572 } else {
573 log_err("minutes string not found in udat_format timeStyle SHORT dateStyle (%d | UDAT_RELATIVE)\n", *stylePtr );
574 }
575 }
576 }
577
578 udat_close(fmtRelDateTime);
579 udat_close(fmtRelDate);
580 udat_close(fmtTime);
581 }
582 }
583
584 /*Testing udat_getSymbols() and udat_setSymbols() and udat_countSymbols()*/
TestSymbols()585 static void TestSymbols()
586 {
587 UDateFormat *def, *fr, *zhChiCal, *esMX;
588 UErrorCode status = U_ZERO_ERROR;
589 UChar *value=NULL;
590 UChar *result = NULL;
591 int32_t resultlength;
592 int32_t resultlengthout;
593 UChar *pattern;
594
595
596 /*creating a dateformat with french locale */
597 log_verbose("\ncreating a date format with french locale\n");
598 fr = udat_open(UDAT_FULL, UDAT_DEFAULT, "fr_FR", NULL, 0, NULL, 0, &status);
599 if(U_FAILURE(status))
600 {
601 log_data_err("error in creating the dateformat using full time style with french locale -> %s (Are you missing data?)\n",
602 myErrorName(status) );
603 return;
604 }
605 /*creating a default dateformat */
606 log_verbose("\ncreating a date format with default locale\n");
607 /* this is supposed to open default date format, but later on it treats it like it is "en_US"
608 - very bad if you try to run the tests on machine where default locale is NOT "en_US" */
609 /* def = udat_open(UDAT_DEFAULT,UDAT_DEFAULT ,NULL, NULL, 0, &status); */
610 def = udat_open(UDAT_DEFAULT,UDAT_DEFAULT ,"en_US", NULL, 0, NULL, 0, &status);
611 if(U_FAILURE(status))
612 {
613 log_err("error in creating the dateformat using short date and time style\n %s\n",
614 myErrorName(status) );
615 return;
616 }
617 /*creating a dateformat with zh locale */
618 log_verbose("\ncreating a date format with zh locale for chinese calendar\n");
619 zhChiCal = udat_open(UDAT_NONE, UDAT_FULL, "zh@calendar=chinese", NULL, 0, NULL, 0, &status);
620 if(U_FAILURE(status))
621 {
622 log_data_err("error in creating the dateformat using full date, no time, locale zh@calendar=chinese -> %s (Are you missing data?)\n",
623 myErrorName(status) );
624 return;
625 }
626 /*creating a dateformat with es_MX locale */
627 log_verbose("\ncreating a date format with es_MX locale\n");
628 esMX = udat_open(UDAT_SHORT, UDAT_NONE, "es_MX", NULL, 0, NULL, 0, &status);
629 if(U_FAILURE(status))
630 {
631 log_data_err("error in creating the dateformat using no date, short time, locale es_MX -> %s (Are you missing data?)\n",
632 myErrorName(status) );
633 return;
634 }
635
636 /*Testing countSymbols, getSymbols and setSymbols*/
637 log_verbose("\nTesting countSymbols\n");
638 /*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 */
639 if(udat_countSymbols(def, UDAT_ERAS)!=2 || udat_countSymbols(def, UDAT_MONTHS)!=12 ||
640 udat_countSymbols(def, UDAT_SHORT_MONTHS)!=12 || udat_countSymbols(def, UDAT_WEEKDAYS)!=8 ||
641 udat_countSymbols(def, UDAT_SHORT_WEEKDAYS)!=8 || udat_countSymbols(def, UDAT_AM_PMS)!=2 ||
642 udat_countSymbols(def, UDAT_QUARTERS) != 4 || udat_countSymbols(def, UDAT_SHORT_QUARTERS) != 4 ||
643 udat_countSymbols(def, UDAT_LOCALIZED_CHARS)!=1 || udat_countSymbols(def, UDAT_SHORTER_WEEKDAYS)!=8 ||
644 udat_countSymbols(zhChiCal, UDAT_CYCLIC_YEARS_NARROW)!=60 || udat_countSymbols(zhChiCal, UDAT_ZODIAC_NAMES_NARROW)!=12)
645 {
646 log_err("FAIL: error in udat_countSymbols\n");
647 }
648 else
649 log_verbose("PASS: udat_countSymbols() successful\n");
650
651 /*testing getSymbols*/
652 log_verbose("\nTesting getSymbols\n");
653 pattern=(UChar*)malloc(sizeof(UChar) * 10);
654 u_uastrcpy(pattern, "jeudi");
655 resultlength=0;
656 resultlengthout=udat_getSymbols(fr, UDAT_WEEKDAYS, 5 , NULL, resultlength, &status);
657 if(status==U_BUFFER_OVERFLOW_ERROR)
658 {
659 status=U_ZERO_ERROR;
660 resultlength=resultlengthout+1;
661 if(result != NULL) {
662 free(result);
663 result = NULL;
664 }
665 result=(UChar*)malloc(sizeof(UChar) * resultlength);
666 udat_getSymbols(fr, UDAT_WEEKDAYS, 5, result, resultlength, &status);
667
668 }
669 if(U_FAILURE(status))
670 {
671 log_err("FAIL: Error in udat_getSymbols().... %s\n", myErrorName(status) );
672 }
673 else
674 log_verbose("PASS: getSymbols successful\n");
675
676 if(u_strcmp(result, pattern)==0)
677 log_verbose("PASS: getSymbols retrieved the right value\n");
678 else
679 log_data_err("FAIL: getSymbols retrieved the wrong value\n");
680
681 /*run series of tests to test getsymbols regressively*/
682 log_verbose("\nTesting getSymbols() regressively\n");
683 VerifygetSymbols(fr, UDAT_WEEKDAYS, 1, "dimanche");
684 VerifygetSymbols(def, UDAT_WEEKDAYS, 1, "Sunday");
685 VerifygetSymbols(fr, UDAT_SHORT_WEEKDAYS, 7, "sam.");
686 VerifygetSymbols(fr, UDAT_SHORTER_WEEKDAYS, 7, "sa");
687 VerifygetSymbols(def, UDAT_SHORT_WEEKDAYS, 7, "Sat");
688 VerifygetSymbols(def, UDAT_MONTHS, 11, "December");
689 VerifygetSymbols(def, UDAT_MONTHS, 0, "January");
690 VerifygetSymbols(fr, UDAT_ERAS, 0, "av. J.-C.");
691 VerifygetSymbols(def, UDAT_AM_PMS, 0, "AM");
692 VerifygetSymbols(def, UDAT_AM_PMS, 1, "PM");
693 VerifygetSymbols(fr, UDAT_SHORT_MONTHS, 0, "janv.");
694 VerifygetSymbols(def, UDAT_SHORT_MONTHS, 11, "Dec");
695 VerifygetSymbols(fr, UDAT_QUARTERS, 0, "1er trimestre");
696 VerifygetSymbols(def, UDAT_QUARTERS, 3, "4th quarter");
697 VerifygetSymbols(fr, UDAT_SHORT_QUARTERS, 1, "T2");
698 VerifygetSymbols(def, UDAT_SHORT_QUARTERS, 2, "Q3");
699 VerifygetSymbols(esMX, UDAT_STANDALONE_NARROW_QUARTERS, 1, "2T");
700 VerifygetSymbols(def, UDAT_NARROW_QUARTERS, 2, "3");
701 VerifygetSymbols(zhChiCal, UDAT_CYCLIC_YEARS_ABBREVIATED, 0, "\\u7532\\u5B50");
702 VerifygetSymbols(zhChiCal, UDAT_CYCLIC_YEARS_NARROW, 59, "\\u7678\\u4EA5");
703 VerifygetSymbols(zhChiCal, UDAT_ZODIAC_NAMES_ABBREVIATED, 0, "\\u9F20");
704 VerifygetSymbols(zhChiCal, UDAT_ZODIAC_NAMES_WIDE, 11, "\\u732A");
705 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
706 VerifygetSymbols(def,UDAT_LOCALIZED_CHARS, 0, "GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB:");
707 #else
708 VerifygetSymbols(def,UDAT_LOCALIZED_CHARS, 0, "GyMdkHmsSEDFwWahKzYeugAZvcLQqVUOXxrbB");
709 #endif
710
711
712 if(result != NULL) {
713 free(result);
714 result = NULL;
715 }
716 free(pattern);
717
718 log_verbose("\nTesting setSymbols\n");
719 /*applying the pattern so that setSymbolss works */
720 resultlength=0;
721 resultlengthout=udat_toPattern(fr, false, NULL, resultlength, &status);
722 if(status==U_BUFFER_OVERFLOW_ERROR)
723 {
724 status=U_ZERO_ERROR;
725 resultlength=resultlengthout + 1;
726 pattern=(UChar*)malloc(sizeof(UChar) * resultlength);
727 udat_toPattern(fr, false, pattern, resultlength, &status);
728 }
729 if(U_FAILURE(status))
730 {
731 log_err("FAIL: error in extracting the pattern from UNumberFormat\n %s\n",
732 myErrorName(status) );
733 }
734
735 udat_applyPattern(def, false, pattern, u_strlen(pattern));
736 resultlength=0;
737 resultlengthout=udat_toPattern(def, false, NULL, resultlength,&status);
738 if(status==U_BUFFER_OVERFLOW_ERROR)
739 {
740 status=U_ZERO_ERROR;
741 resultlength=resultlengthout + 1;
742 if(result != NULL) {
743 free(result);
744 result = NULL;
745 }
746 result=(UChar*)malloc(sizeof(UChar) * resultlength);
747 udat_toPattern(fr, false,result, resultlength, &status);
748 }
749 if(U_FAILURE(status))
750 {
751 log_err("FAIL: error in extracting the pattern from UNumberFormat\n %s\n",
752 myErrorName(status) );
753 }
754 if(u_strcmp(result, pattern)==0)
755 log_verbose("Pattern applied properly\n");
756 else
757 log_err("pattern could not be applied properly\n");
758
759 free(pattern);
760 /*testing set symbols */
761 resultlength=0;
762 resultlengthout=udat_getSymbols(fr, UDAT_MONTHS, 11 , NULL, resultlength, &status);
763 if(status==U_BUFFER_OVERFLOW_ERROR){
764 status=U_ZERO_ERROR;
765 resultlength=resultlengthout+1;
766 if(result != NULL) {
767 free(result);
768 result = NULL;
769 }
770 result=(UChar*)malloc(sizeof(UChar) * resultlength);
771 udat_getSymbols(fr, UDAT_MONTHS, 11, result, resultlength, &status);
772
773 }
774 if(U_FAILURE(status))
775 log_err("FAIL: error in getSymbols() %s\n", myErrorName(status) );
776 resultlength=resultlengthout+1;
777
778 udat_setSymbols(def, UDAT_MONTHS, 11, result, resultlength, &status);
779 if(U_FAILURE(status))
780 {
781 log_err("FAIL: Error in udat_setSymbols() : %s\n", myErrorName(status) );
782 }
783 else
784 log_verbose("PASS: SetSymbols successful\n");
785
786 resultlength=0;
787 resultlengthout=udat_getSymbols(def, UDAT_MONTHS, 11, NULL, resultlength, &status);
788 if(status==U_BUFFER_OVERFLOW_ERROR){
789 status=U_ZERO_ERROR;
790 resultlength=resultlengthout+1;
791 value=(UChar*)malloc(sizeof(UChar) * resultlength);
792 udat_getSymbols(def, UDAT_MONTHS, 11, value, resultlength, &status);
793 }
794 if(U_FAILURE(status))
795 log_err("FAIL: error in retrieving the value using getSymbols i.e roundtrip\n");
796
797 if(u_strcmp(result, value)!=0)
798 log_data_err("FAIL: Error in setting and getting symbols\n");
799 else
800 log_verbose("PASS: setSymbols successful\n");
801
802
803 /*run series of tests to test setSymbols regressively*/
804 log_verbose("\nTesting setSymbols regressively\n");
805 VerifysetSymbols(def, UDAT_ERAS, 0, "BeforeChrist");
806 VerifysetSymbols(def, UDAT_ERA_NAMES, 1, "AnnoDomini");
807 VerifysetSymbols(def, UDAT_WEEKDAYS, 1, "Sundayweek");
808 VerifysetSymbols(def, UDAT_SHORT_WEEKDAYS, 7, "Satweek");
809 VerifysetSymbols(def, UDAT_NARROW_WEEKDAYS, 4, "M");
810 VerifysetSymbols(def, UDAT_STANDALONE_WEEKDAYS, 1, "Sonntagweek");
811 VerifysetSymbols(def, UDAT_STANDALONE_SHORT_WEEKDAYS, 7, "Sams");
812 VerifysetSymbols(def, UDAT_STANDALONE_NARROW_WEEKDAYS, 4, "V");
813 VerifysetSymbols(fr, UDAT_MONTHS, 11, "december");
814 VerifysetSymbols(fr, UDAT_SHORT_MONTHS, 0, "Jan");
815 VerifysetSymbols(fr, UDAT_NARROW_MONTHS, 1, "R");
816 VerifysetSymbols(fr, UDAT_STANDALONE_MONTHS, 11, "dezember");
817 VerifysetSymbols(fr, UDAT_STANDALONE_SHORT_MONTHS, 7, "Aug");
818 VerifysetSymbols(fr, UDAT_STANDALONE_NARROW_MONTHS, 2, "M");
819 VerifysetSymbols(fr, UDAT_QUARTERS, 0, "1. Quart");
820 VerifysetSymbols(fr, UDAT_SHORT_QUARTERS, 1, "QQ2");
821 VerifysetSymbols(fr, UDAT_NARROW_QUARTERS, 1, "!2");
822 VerifysetSymbols(fr, UDAT_STANDALONE_QUARTERS, 2, "3rd Quar.");
823 VerifysetSymbols(fr, UDAT_STANDALONE_SHORT_QUARTERS, 3, "4QQ");
824 VerifysetSymbols(fr, UDAT_STANDALONE_NARROW_QUARTERS, 3, "!4");
825 VerifysetSymbols(zhChiCal, UDAT_CYCLIC_YEARS_ABBREVIATED, 1, "yi-chou");
826 VerifysetSymbols(zhChiCal, UDAT_ZODIAC_NAMES_ABBREVIATED, 1, "Ox");
827
828
829 /*run series of tests to test get and setSymbols regressively*/
830 log_verbose("\nTesting get and set symbols regressively\n");
831 VerifygetsetSymbols(fr, def, UDAT_WEEKDAYS, 1);
832 VerifygetsetSymbols(fr, def, UDAT_WEEKDAYS, 7);
833 VerifygetsetSymbols(fr, def, UDAT_SHORT_WEEKDAYS, 1);
834 VerifygetsetSymbols(fr, def, UDAT_SHORT_WEEKDAYS, 7);
835 VerifygetsetSymbols(fr, def, UDAT_MONTHS, 0);
836 VerifygetsetSymbols(fr, def, UDAT_SHORT_MONTHS, 0);
837 VerifygetsetSymbols(fr, def, UDAT_ERAS,1);
838 VerifygetsetSymbols(fr, def, UDAT_LOCALIZED_CHARS, 0);
839 VerifygetsetSymbols(fr, def, UDAT_AM_PMS, 1);
840
841
842 /*closing*/
843
844 udat_close(fr);
845 udat_close(def);
846 udat_close(zhChiCal);
847 udat_close(esMX);
848 if(result != NULL) {
849 free(result);
850 result = NULL;
851 }
852 free(value);
853
854 }
855
856 /**
857 * Test DateFormat(Calendar) API
858 */
TestDateFormatCalendar()859 static void TestDateFormatCalendar() {
860 UDateFormat *date=0, *time=0, *full=0;
861 UCalendar *cal=0;
862 UChar buf[256];
863 char cbuf[256];
864 int32_t pos;
865 UDate when;
866 UErrorCode ec = U_ZERO_ERROR;
867 UChar buf1[256];
868 int32_t len1;
869 const char *expected;
870 UChar uExpected[32];
871
872 ctest_setTimeZone(NULL, &ec);
873
874 /* Create a formatter for date fields. */
875 date = udat_open(UDAT_NONE, UDAT_SHORT, "en_US", NULL, 0, NULL, 0, &ec);
876 if (U_FAILURE(ec)) {
877 log_data_err("FAIL: udat_open(NONE, SHORT, en_US) failed with %s (Are you missing data?)\n",
878 u_errorName(ec));
879 goto FAIL;
880 }
881
882 /* Create a formatter for time fields. */
883 time = udat_open(UDAT_SHORT, UDAT_NONE, "en_US", NULL, 0, NULL, 0, &ec);
884 if (U_FAILURE(ec)) {
885 log_err("FAIL: udat_open(SHORT, NONE, en_US) failed with %s\n",
886 u_errorName(ec));
887 goto FAIL;
888 }
889
890 /* Create a full format for output */
891 full = udat_open(UDAT_FULL, UDAT_FULL, "en_US", NULL, 0, NULL, 0, &ec);
892 if (U_FAILURE(ec)) {
893 log_err("FAIL: udat_open(FULL, FULL, en_US) failed with %s\n",
894 u_errorName(ec));
895 goto FAIL;
896 }
897
898 /* Create a calendar */
899 cal = ucal_open(NULL, 0, "en_US", UCAL_GREGORIAN, &ec);
900 if (U_FAILURE(ec)) {
901 log_err("FAIL: ucal_open(en_US) failed with %s\n",
902 u_errorName(ec));
903 goto FAIL;
904 }
905
906 /* Parse the date */
907 ucal_clear(cal);
908 u_uastrcpy(buf, "4/5/2001");
909 pos = 0;
910 udat_parseCalendar(date, cal, buf, -1, &pos, &ec);
911 if (U_FAILURE(ec)) {
912 log_err("FAIL: udat_parseCalendar(4/5/2001) failed at %d with %s\n",
913 pos, u_errorName(ec));
914 goto FAIL;
915 }
916
917 /* Check if formatCalendar matches the original date */
918 len1 = udat_formatCalendar(date, cal, buf1, UPRV_LENGTHOF(buf1), NULL, &ec);
919 if (U_FAILURE(ec)) {
920 log_err("FAIL: udat_formatCalendar(4/5/2001) failed with %s\n",
921 u_errorName(ec));
922 goto FAIL;
923 }
924 expected = "4/5/01";
925 u_uastrcpy(uExpected, expected);
926 if (u_strlen(uExpected) != len1 || u_strncmp(uExpected, buf1, len1) != 0) {
927 log_err("FAIL: udat_formatCalendar(4/5/2001), expected: %s", expected);
928 }
929
930 /* Parse the time */
931 u_uastrcpy(buf, "5:45 PM");
932 pos = 0;
933 udat_parseCalendar(time, cal, buf, -1, &pos, &ec);
934 if (U_FAILURE(ec)) {
935 log_err("FAIL: udat_parseCalendar(17:45) failed at %d with %s\n",
936 pos, u_errorName(ec));
937 goto FAIL;
938 }
939
940 /* Check if formatCalendar matches the original time */
941 len1 = udat_formatCalendar(time, cal, buf1, UPRV_LENGTHOF(buf1), NULL, &ec);
942 if (U_FAILURE(ec)) {
943 log_err("FAIL: udat_formatCalendar(17:45) failed with %s\n",
944 u_errorName(ec));
945 goto FAIL;
946 }
947 u_strcpy(uExpected, u"5:45\u202FPM");
948 u_austrcpy(cbuf, uExpected);
949 if (u_strlen(uExpected) != len1 || u_strncmp(uExpected, buf1, len1) != 0) {
950 log_err("FAIL: udat_formatCalendar(17:45), expected: %s", cbuf);
951 }
952
953 /* Check result */
954 when = ucal_getMillis(cal, &ec);
955 if (U_FAILURE(ec)) {
956 log_err("FAIL: ucal_getMillis() failed with %s\n", u_errorName(ec));
957 goto FAIL;
958 }
959 udat_format(full, when, buf, sizeof(buf), NULL, &ec);
960 if (U_FAILURE(ec)) {
961 log_err("FAIL: udat_format() failed with %s\n", u_errorName(ec));
962 goto FAIL;
963 }
964 u_austrcpy(cbuf, buf);
965 /* Thursday, April 5, 2001 5:45:00 PM PDT 986517900000 */
966 if (when == 986517900000.0) {
967 log_verbose("Ok: Parsed result: %s\n", cbuf);
968 } else {
969 log_err("FAIL: Parsed result: %s, exp 4/5/2001 5:45 PM\n", cbuf);
970 }
971
972 FAIL:
973 udat_close(date);
974 udat_close(time);
975 udat_close(full);
976 ucal_close(cal);
977
978 ctest_resetTimeZone();
979 }
980
981
982
983 /**
984 * Test parsing two digit year against "YY" vs. "YYYY" patterns
985 */
TestCalendarDateParse()986 static void TestCalendarDateParse() {
987
988 int32_t result;
989 UErrorCode ec = U_ZERO_ERROR;
990 UDateFormat* simpleDateFormat = 0;
991 int32_t parsePos = 0;
992 int32_t twoDigitCenturyStart = 75;
993 int32_t currentTwoDigitYear = 0;
994 int32_t startCentury = 0;
995 UCalendar* tempCal = 0;
996 UCalendar* calendar = 0;
997
998 U_STRING_DECL(pattern, "yyyy", 4);
999 U_STRING_DECL(pattern2, "yy", 2);
1000 U_STRING_DECL(text, "75", 2);
1001
1002 U_STRING_INIT(pattern, "yyyy", 4);
1003 U_STRING_INIT(pattern2, "yy", 2);
1004 U_STRING_INIT(text, "75", 2);
1005
1006 simpleDateFormat = udat_open(UDAT_FULL, UDAT_FULL, "en-GB", 0, 0, 0, 0, &ec);
1007 if (U_FAILURE(ec)) {
1008 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));
1009 return;
1010 }
1011 udat_applyPattern(simpleDateFormat, 0, pattern, u_strlen(pattern));
1012 udat_setLenient(simpleDateFormat, 0);
1013
1014 currentTwoDigitYear = getCurrentYear() % 100;
1015 startCentury = getCurrentYear() - currentTwoDigitYear;
1016 if (twoDigitCenturyStart > currentTwoDigitYear) {
1017 startCentury -= 100;
1018 }
1019 tempCal = ucal_open(NULL, -1, NULL, UCAL_GREGORIAN, &ec);
1020 ucal_setMillis(tempCal, 0, &ec);
1021 ucal_setDateTime(tempCal, startCentury + twoDigitCenturyStart, UCAL_JANUARY, 1, 0, 0, 0, &ec);
1022 udat_set2DigitYearStart(simpleDateFormat, ucal_getMillis(tempCal, &ec), &ec);
1023
1024 calendar = ucal_open(NULL, -1, NULL, UCAL_GREGORIAN, &ec);
1025 ucal_setMillis(calendar, 0, &ec);
1026 ucal_setDateTime(calendar, twoDigitCenturyStart, UCAL_JANUARY, 1, 0, 0, 0, &ec);
1027
1028 udat_parseCalendar(simpleDateFormat, calendar, text, u_strlen(text), &parsePos, &ec);
1029
1030 /* Check result */
1031 result = ucal_get(calendar, UCAL_YEAR, &ec);
1032 if (U_FAILURE(ec)) {
1033 log_err("FAIL: ucal_get(UCAL_YEAR) failed with %s\n", u_errorName(ec));
1034 goto FAIL;
1035 }
1036
1037 if (result != 75) {
1038 log_err("FAIL: parsed incorrect year: %d\n", result);
1039 goto FAIL;
1040 }
1041
1042 parsePos = 0;
1043 udat_applyPattern(simpleDateFormat, 0, pattern2, u_strlen(pattern2));
1044 udat_parseCalendar(simpleDateFormat, calendar, text, u_strlen(text), &parsePos, &ec);
1045
1046 /* Check result */
1047 result = ucal_get(calendar, UCAL_YEAR, &ec);
1048 if (U_FAILURE(ec)) {
1049 log_err("FAIL: ucal_get(UCAL_YEAR) failed with %s\n", u_errorName(ec));
1050 goto FAIL;
1051 }
1052
1053 if (result != 1975) {
1054 log_err("FAIL: parsed incorrect year: %d\n", result);
1055 goto FAIL;
1056 }
1057
1058 FAIL:
1059 udat_close(simpleDateFormat);
1060 udat_close(tempCal);
1061 udat_close(calendar);
1062 }
1063
1064
1065 /*INTERNAL FUNCTIONS USED*/
getCurrentYear()1066 static int getCurrentYear() {
1067 static int currentYear = 0;
1068 if (currentYear == 0) {
1069 UErrorCode status = U_ZERO_ERROR;
1070 UCalendar *cal = ucal_open(NULL, -1, NULL, UCAL_GREGORIAN, &status);
1071 if (!U_FAILURE(status)) {
1072 /* Get the current year from the default UCalendar */
1073 currentYear = ucal_get(cal, UCAL_YEAR, &status);
1074 ucal_close(cal);
1075 }
1076 }
1077
1078 return currentYear;
1079 }
1080
1081 /* N.B.: use idx instead of index to avoid 'shadow' warnings in strict mode. */
VerifygetSymbols(UDateFormat * datfor,UDateFormatSymbolType type,int32_t idx,const char * expected)1082 static void VerifygetSymbols(UDateFormat* datfor, UDateFormatSymbolType type, int32_t idx, const char* expected)
1083 {
1084 UChar *pattern=NULL;
1085 UErrorCode status = U_ZERO_ERROR;
1086 UChar *result=NULL;
1087 int32_t resultlength, resultlengthout;
1088 int32_t patternSize = (int32_t)strlen(expected) + 1;
1089
1090 pattern=(UChar*)malloc(sizeof(UChar) * patternSize);
1091 u_unescape(expected, pattern, patternSize);
1092 resultlength=0;
1093 resultlengthout=udat_getSymbols(datfor, type, idx , NULL, resultlength, &status);
1094 if(status==U_BUFFER_OVERFLOW_ERROR)
1095 {
1096 status=U_ZERO_ERROR;
1097 resultlength=resultlengthout+1;
1098 result=(UChar*)malloc(sizeof(UChar) * resultlength);
1099 udat_getSymbols(datfor, type, idx, result, resultlength, &status);
1100
1101 }
1102 if(U_FAILURE(status))
1103 {
1104 log_err("FAIL: Error in udat_getSymbols()... %s\n", myErrorName(status) );
1105 return;
1106 }
1107 if(u_strcmp(result, pattern)==0)
1108 log_verbose("PASS: getSymbols retrieved the right value\n");
1109 else{
1110 log_data_err("FAIL: getSymbols retrieved the wrong value\n Expected %s Got %s\n", expected,
1111 aescstrdup(result,-1) );
1112 }
1113 free(result);
1114 free(pattern);
1115 }
1116
VerifysetSymbols(UDateFormat * datfor,UDateFormatSymbolType type,int32_t idx,const char * expected)1117 static void VerifysetSymbols(UDateFormat* datfor, UDateFormatSymbolType type, int32_t idx, const char* expected)
1118 {
1119 UChar *result=NULL;
1120 UChar *value=NULL;
1121 int32_t resultlength, resultlengthout;
1122 UErrorCode status = U_ZERO_ERROR;
1123 int32_t valueLen, valueSize = (int32_t)strlen(expected) + 1;
1124
1125 value=(UChar*)malloc(sizeof(UChar) * valueSize);
1126 valueLen = u_unescape(expected, value, valueSize);
1127 udat_setSymbols(datfor, type, idx, value, valueLen, &status);
1128 if(U_FAILURE(status))
1129 {
1130 log_err("FAIL: Error in udat_setSymbols() %s\n", myErrorName(status) );
1131 return;
1132 }
1133
1134 resultlength=0;
1135 resultlengthout=udat_getSymbols(datfor, type, idx, NULL, resultlength, &status);
1136 if(status==U_BUFFER_OVERFLOW_ERROR){
1137 status=U_ZERO_ERROR;
1138 resultlength=resultlengthout+1;
1139 result=(UChar*)malloc(sizeof(UChar) * resultlength);
1140 udat_getSymbols(datfor, type, idx, result, resultlength, &status);
1141 }
1142 if(U_FAILURE(status)){
1143 log_err("FAIL: error in retrieving the value using getSymbols after setting it previously\n %s\n",
1144 myErrorName(status) );
1145 return;
1146 }
1147
1148 if(u_strcmp(result, value)!=0){
1149 log_err("FAIL:Error in setting and then getting symbols\n Expected %s Got %s\n", expected,
1150 aescstrdup(result,-1) );
1151 }
1152 else
1153 log_verbose("PASS: setSymbols successful\n");
1154
1155 free(value);
1156 free(result);
1157 }
1158
1159
VerifygetsetSymbols(UDateFormat * from,UDateFormat * to,UDateFormatSymbolType type,int32_t idx)1160 static void VerifygetsetSymbols(UDateFormat* from, UDateFormat* to, UDateFormatSymbolType type, int32_t idx)
1161 {
1162 UChar *result=NULL;
1163 UChar *value=NULL;
1164 int32_t resultlength, resultlengthout;
1165 UErrorCode status = U_ZERO_ERROR;
1166
1167 resultlength=0;
1168 resultlengthout=udat_getSymbols(from, type, idx , NULL, resultlength, &status);
1169 if(status==U_BUFFER_OVERFLOW_ERROR){
1170 status=U_ZERO_ERROR;
1171 resultlength=resultlengthout+1;
1172 result=(UChar*)malloc(sizeof(UChar) * resultlength);
1173 udat_getSymbols(from, type, idx, result, resultlength, &status);
1174 }
1175 if(U_FAILURE(status)){
1176 log_err("FAIL: error in getSymbols() %s\n", myErrorName(status) );
1177 return;
1178 }
1179
1180 resultlength=resultlengthout+1;
1181 udat_setSymbols(to, type, idx, result, resultlength, &status);
1182 if(U_FAILURE(status))
1183 {
1184 log_err("FAIL: Error in udat_setSymbols() : %s\n", myErrorName(status) );
1185 return;
1186 }
1187
1188 resultlength=0;
1189 resultlengthout=udat_getSymbols(to, type, idx, NULL, resultlength, &status);
1190 if(status==U_BUFFER_OVERFLOW_ERROR){
1191 status=U_ZERO_ERROR;
1192 resultlength=resultlengthout+1;
1193 value=(UChar*)malloc(sizeof(UChar) * resultlength);
1194 udat_getSymbols(to, type, idx, value, resultlength, &status);
1195 }
1196 if(U_FAILURE(status)){
1197 log_err("FAIL: error in retrieving the value using getSymbols i.e roundtrip\n %s\n",
1198 myErrorName(status) );
1199 return;
1200 }
1201
1202 if(u_strcmp(result, value)!=0){
1203 log_data_err("FAIL:Error in setting and then getting symbols\n Expected %s Got %s\n", austrdup(result),
1204 austrdup(value) );
1205 }
1206 else
1207 log_verbose("PASS: setSymbols successful\n");
1208
1209 free(value);
1210 free(result);
1211 }
1212
1213
myNumformat(const UNumberFormat * numfor,double d)1214 static UChar* myNumformat(const UNumberFormat* numfor, double d)
1215 {
1216 UChar *result2=NULL;
1217 int32_t resultlength, resultlengthneeded;
1218 UErrorCode status = U_ZERO_ERROR;
1219
1220 resultlength=0;
1221 resultlengthneeded=unum_formatDouble(numfor, d, NULL, resultlength, NULL, &status);
1222 if(status==U_BUFFER_OVERFLOW_ERROR)
1223 {
1224 status=U_ZERO_ERROR;
1225 resultlength=resultlengthneeded+1;
1226 /*result2=(UChar*)malloc(sizeof(UChar) * resultlength);*/ /* this leaks */
1227 result2=(UChar*)ctst_malloc(sizeof(UChar) * resultlength); /*this won't*/
1228 unum_formatDouble(numfor, d, result2, resultlength, NULL, &status);
1229 }
1230 if(U_FAILURE(status))
1231 {
1232 log_err("FAIL: Error in formatting using unum_format(.....) %s\n", myErrorName(status) );
1233 return 0;
1234 }
1235
1236 return result2;
1237 }
1238
1239 /**
1240 * The search depth for TestExtremeDates. The total number of
1241 * dates that will be tested is (2^EXTREME_DATES_DEPTH) - 1.
1242 */
1243 #define EXTREME_DATES_DEPTH 8
1244
1245 /**
1246 * Support for TestExtremeDates (below).
1247 *
1248 * Test a single date to see whether udat_format handles it properly.
1249 */
_aux1ExtremeDates(UDateFormat * fmt,UDate date,UChar * buf,int32_t buflen,char * cbuf,UErrorCode * ec)1250 static UBool _aux1ExtremeDates(UDateFormat* fmt, UDate date,
1251 UChar* buf, int32_t buflen, char* cbuf,
1252 UErrorCode* ec) {
1253 int32_t len = udat_format(fmt, date, buf, buflen, 0, ec);
1254 if (!assertSuccess("udat_format", ec)) return false;
1255 u_austrncpy(cbuf, buf, buflen);
1256 if (len < 4) {
1257 log_err("FAIL: udat_format(%g) => \"%s\"\n", date, cbuf);
1258 } else {
1259 log_verbose("udat_format(%g) => \"%s\"\n", date, cbuf);
1260 }
1261 return true;
1262 }
1263
1264 /**
1265 * Support for TestExtremeDates (below).
1266 *
1267 * Recursively test between 'small' and 'large', up to the depth
1268 * limit specified by EXTREME_DATES_DEPTH.
1269 */
_aux2ExtremeDates(UDateFormat * fmt,UDate small,UDate large,UChar * buf,int32_t buflen,char * cbuf,int32_t count,UErrorCode * ec)1270 static UBool _aux2ExtremeDates(UDateFormat* fmt, UDate small, UDate large,
1271 UChar* buf, int32_t buflen, char* cbuf,
1272 int32_t count,
1273 UErrorCode* ec) {
1274 /* Logarithmic midpoint; see below */
1275 UDate mid = (UDate) exp((log(small) + log(large)) / 2);
1276 if (count == EXTREME_DATES_DEPTH) {
1277 return true;
1278 }
1279 return
1280 _aux1ExtremeDates(fmt, mid, buf, buflen, cbuf, ec) &&
1281 _aux2ExtremeDates(fmt, small, mid, buf, buflen, cbuf, count+1, ec) &&
1282 _aux2ExtremeDates(fmt, mid, large, buf, buflen, cbuf, count+1, ec);
1283 }
1284
1285 /**
1286 * http://www.jtcsv.com/cgibin/icu-bugs?findid=3659
1287 *
1288 * For certain large dates, udat_format crashes on MacOS. This test
1289 * attempts to reproduce this problem by doing a recursive logarithmic*
1290 * binary search of a predefined interval (from 'small' to 'large').
1291 *
1292 * The limit of the search is given by EXTREME_DATES_DEPTH, above.
1293 *
1294 * *The search has to be logarithmic, not linear. A linear search of the
1295 * range 0..10^30, for example, will find 0.5*10^30, then 0.25*10^30 and
1296 * 0.75*10^30, etc. A logarithmic search will find 10^15, then 10^7.5
1297 * and 10^22.5, etc.
1298 */
TestExtremeDates()1299 static void TestExtremeDates() {
1300 UDateFormat *fmt;
1301 UErrorCode ec;
1302 UChar buf[256];
1303 char cbuf[256];
1304 const double small = 1000; /* 1 sec */
1305 const double large = 1e+30; /* well beyond usable UDate range */
1306
1307 /* There is no need to test larger values from 1e+30 to 1e+300;
1308 the failures occur around 1e+27, and never above 1e+30. */
1309
1310 ec = U_ZERO_ERROR;
1311 fmt = udat_open(UDAT_LONG, UDAT_LONG, "en_US",
1312 0, 0, 0, 0, &ec);
1313 if (U_FAILURE(ec)) {
1314 log_data_err("FAIL: udat_open (%s) (Are you missing data?)\n", u_errorName(ec));
1315 return;
1316 }
1317
1318 _aux2ExtremeDates(fmt, small, large, buf, UPRV_LENGTHOF(buf), cbuf, 0, &ec);
1319
1320 udat_close(fmt);
1321 }
1322
TestAllLocales(void)1323 static void TestAllLocales(void) {
1324 int32_t idx, dateIdx, timeIdx, localeCount;
1325 static const UDateFormatStyle style[] = {
1326 UDAT_FULL, UDAT_LONG, UDAT_MEDIUM, UDAT_SHORT
1327 };
1328 localeCount = uloc_countAvailable();
1329 for (idx = 0; idx < localeCount; idx++) {
1330 for (dateIdx = 0; dateIdx < UPRV_LENGTHOF(style); dateIdx++) {
1331 for (timeIdx = 0; timeIdx < UPRV_LENGTHOF(style); timeIdx++) {
1332 UErrorCode status = U_ZERO_ERROR;
1333 udat_close(udat_open(style[dateIdx], style[timeIdx],
1334 uloc_getAvailable(idx), NULL, 0, NULL, 0, &status));
1335 if (U_FAILURE(status)) {
1336 log_err("FAIL: udat_open(%s) failed with (%s) dateIdx=%d, timeIdx=%d\n",
1337 uloc_getAvailable(idx), u_errorName(status), dateIdx, timeIdx);
1338 }
1339 }
1340 }
1341 }
1342 }
1343
TestRelativeCrash(void)1344 static void TestRelativeCrash(void) {
1345 static const UChar tzName[] = { 0x0055, 0x0053, 0x002F, 0x0050, 0x0061, 0x0063, 0x0069, 0x0066, 0x0069, 0x0063, 0 };
1346 static const UDate aDate = -631152000000.0;
1347
1348 UErrorCode status = U_ZERO_ERROR;
1349 UErrorCode expectStatus = U_ILLEGAL_ARGUMENT_ERROR;
1350 UDateFormat icudf;
1351
1352 icudf = udat_open(UDAT_NONE, UDAT_SHORT_RELATIVE, "en", tzName, -1, NULL, 0, &status);
1353 if ( U_SUCCESS(status) ) {
1354 const char *what = "???";
1355 {
1356 UErrorCode subStatus = U_ZERO_ERROR;
1357 what = "udat_set2DigitYearStart";
1358 log_verbose("Trying %s on a relative date..\n", what);
1359 udat_set2DigitYearStart(icudf, aDate, &subStatus);
1360 if(subStatus == expectStatus) {
1361 log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
1362 } else {
1363 log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
1364 }
1365 }
1366 {
1367 /* clone works polymorphically. try it anyways */
1368 UErrorCode subStatus = U_ZERO_ERROR;
1369 UDateFormat *oth;
1370 what = "clone";
1371 log_verbose("Trying %s on a relative date..\n", what);
1372 oth = udat_clone(icudf, &subStatus);
1373 if(subStatus == U_ZERO_ERROR) {
1374 log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
1375 udat_close(oth); /* ? */
1376 } else {
1377 log_err("FAIL: didn't crash on %s, but got %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
1378 }
1379 }
1380 {
1381 UErrorCode subStatus = U_ZERO_ERROR;
1382 what = "udat_get2DigitYearStart";
1383 log_verbose("Trying %s on a relative date..\n", what);
1384 udat_get2DigitYearStart(icudf, &subStatus);
1385 if(subStatus == expectStatus) {
1386 log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
1387 } else {
1388 log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
1389 }
1390 }
1391 {
1392 /* Now udat_toPattern works for relative date formatters, unless localized is true */
1393 UErrorCode subStatus = U_ZERO_ERROR;
1394 what = "udat_toPattern";
1395 log_verbose("Trying %s on a relative date..\n", what);
1396 udat_toPattern(icudf, true,NULL,0, &subStatus);
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));
1401 }
1402 }
1403 {
1404 UErrorCode subStatus = U_ZERO_ERROR;
1405 what = "udat_applyPattern";
1406 log_verbose("Trying %s on a relative date..\n", what);
1407 udat_applyPattern(icudf, false,tzName,-1);
1408 subStatus = U_ILLEGAL_ARGUMENT_ERROR; /* what it should be, if this took an errorcode. */
1409 if(subStatus == expectStatus) {
1410 log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
1411 } else {
1412 log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
1413 }
1414 }
1415 {
1416 UChar erabuf[32];
1417 UErrorCode subStatus = U_ZERO_ERROR;
1418 what = "udat_getSymbols";
1419 log_verbose("Trying %s on a relative date..\n", what);
1420 udat_getSymbols(icudf, UDAT_ERAS,0,erabuf,UPRV_LENGTHOF(erabuf), &subStatus);
1421 if(subStatus == U_ZERO_ERROR) {
1422 log_verbose("Success: %s returned %s.\n", what, u_errorName(subStatus));
1423 } else {
1424 log_err("FAIL: didn't crash on %s, but got %s instead of U_ZERO_ERROR.\n", what, u_errorName(subStatus));
1425 }
1426 }
1427 {
1428 UErrorCode subStatus = U_ZERO_ERROR;
1429 UChar symbolValue = 0x0041;
1430 what = "udat_setSymbols";
1431 log_verbose("Trying %s on a relative date..\n", what);
1432 udat_setSymbols(icudf, UDAT_ERAS,0,&symbolValue,1, &subStatus); /* bogus values */
1433 if(subStatus == expectStatus) {
1434 log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
1435 } else {
1436 log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
1437 }
1438 }
1439 {
1440 UErrorCode subStatus = U_ZERO_ERROR;
1441 what = "udat_countSymbols";
1442 log_verbose("Trying %s on a relative date..\n", what);
1443 udat_countSymbols(icudf, UDAT_ERAS);
1444 subStatus = U_ILLEGAL_ARGUMENT_ERROR; /* should have an errorcode. */
1445 if(subStatus == expectStatus) {
1446 log_verbose("Success: did not crash on %s, but got %s.\n", what, u_errorName(subStatus));
1447 } else {
1448 log_err("FAIL: didn't crash on %s, but got success %s instead of %s. \n", what, u_errorName(subStatus), u_errorName(expectStatus));
1449 }
1450 }
1451
1452 udat_close(icudf);
1453 } else {
1454 log_data_err("FAIL: err calling udat_open() ->%s (Are you missing data?)\n", u_errorName(status));
1455 }
1456 }
1457
1458 static const UChar skeleton_yMMMM[] = { 0x79,0x4D,0x4D,0x4D,0x4D,0 }; /* "yMMMM"; fr maps to "MMMM y", cs maps to "LLLL y" */
1459 static const UChar july2008_frDefault[] = { 0x6A,0x75,0x69,0x6C,0x6C,0x65,0x74,0x20,0x32,0x30,0x30,0x38,0 }; /* "juillet 2008" */
1460 static const UChar july2008_frTitle[] = { 0x4A,0x75,0x69,0x6C,0x6C,0x65,0x74,0x20,0x32,0x30,0x30,0x38,0 }; /* "Juillet 2008" sentence-begin, standalone */
1461 static const UChar july2008_csDefault[] = { 0x10D,0x65,0x72,0x76,0x65,0x6E,0x65,0x63,0x20,0x32,0x30,0x30,0x38,0 }; /* "c(hacek)ervenec 2008" */
1462 static const UChar july2008_csTitle[] = { 0x10C,0x65,0x72,0x76,0x65,0x6E,0x65,0x63,0x20,0x32,0x30,0x30,0x38,0 }; /* "C(hacek)ervenec 2008" sentence-begin, uiListOrMenu */
1463
1464 typedef struct {
1465 const char * locale;
1466 const UChar * skeleton;
1467 UDisplayContext capitalizationContext;
1468 const UChar * expectedFormat;
1469 } TestContextItem;
1470
1471 static const TestContextItem textContextItems[] = {
1472 { "fr", skeleton_yMMMM, UDISPCTX_CAPITALIZATION_NONE, july2008_frDefault },
1473 #if !UCONFIG_NO_BREAK_ITERATION
1474 { "fr", skeleton_yMMMM, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, july2008_frDefault },
1475 { "fr", skeleton_yMMMM, UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, july2008_frTitle },
1476 { "fr", skeleton_yMMMM, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, july2008_frDefault },
1477 { "fr", skeleton_yMMMM, UDISPCTX_CAPITALIZATION_FOR_STANDALONE, july2008_frTitle },
1478 #endif
1479 { "cs", skeleton_yMMMM, UDISPCTX_CAPITALIZATION_NONE, july2008_csDefault },
1480 #if !UCONFIG_NO_BREAK_ITERATION
1481 { "cs", skeleton_yMMMM, UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, july2008_csDefault },
1482 { "cs", skeleton_yMMMM, UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, july2008_csTitle },
1483 { "cs", skeleton_yMMMM, UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, july2008_csTitle },
1484 { "cs", skeleton_yMMMM, UDISPCTX_CAPITALIZATION_FOR_STANDALONE, july2008_csDefault },
1485 #endif
1486 { NULL, NULL, (UDisplayContext)0, NULL }
1487 };
1488
1489 static const UChar today_enDefault[] = { 0x74,0x6F,0x64,0x61,0x79,0 }; /* "today" */
1490 static const UChar today_enTitle[] = { 0x54,0x6F,0x64,0x61,0x79,0 }; /* "Today" sentence-begin, uiListOrMenu, standalone */
1491 static const UChar yesterday_enDefault[] = { 0x79,0x65,0x73,0x74,0x65,0x72,0x64,0x61,0x79,0 }; /* "yesterday" */
1492 static const UChar yesterday_enTitle[] = { 0x59,0x65,0x73,0x74,0x65,0x72,0x64,0x61,0x79,0 }; /* "Yesterday" sentence-begin, uiListOrMenu, standalone */
1493 static const UChar today_nbDefault[] = { 0x69,0x20,0x64,0x61,0x67,0 }; /* "i dag" */
1494 static const UChar today_nbTitle[] = { 0x49,0x20,0x64,0x61,0x67,0 }; /* "I dag" sentence-begin, standalone */
1495 static const UChar yesterday_nbDefault[] = { 0x69,0x20,0x67,0xE5,0x72,0 };
1496 static const UChar yesterday_nbTitle[] = { 0x49,0x20,0x67,0xE5,0x72,0 };
1497
1498 typedef struct {
1499 const char * locale;
1500 UDisplayContext capitalizationContext;
1501 const UChar * expectedFormatToday;
1502 const UChar * expectedFormatYesterday;
1503 } TestRelativeContextItem;
1504
1505 static const TestRelativeContextItem textContextRelativeItems[] = {
1506 { "en", UDISPCTX_CAPITALIZATION_NONE, today_enDefault, yesterday_enDefault },
1507 #if !UCONFIG_NO_BREAK_ITERATION
1508 { "en", UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, today_enDefault, yesterday_enDefault },
1509 { "en", UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, today_enTitle, yesterday_enTitle },
1510 { "en", UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, today_enTitle, yesterday_enTitle },
1511 { "en", UDISPCTX_CAPITALIZATION_FOR_STANDALONE, today_enTitle, yesterday_enTitle },
1512 #endif
1513 { "nb", UDISPCTX_CAPITALIZATION_NONE, today_nbDefault, yesterday_nbDefault },
1514 #if !UCONFIG_NO_BREAK_ITERATION
1515 { "nb", UDISPCTX_CAPITALIZATION_FOR_MIDDLE_OF_SENTENCE, today_nbDefault, yesterday_nbDefault },
1516 { "nb", UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE, today_nbTitle, yesterday_nbTitle },
1517 { "nb", UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU, today_nbDefault, yesterday_nbDefault },
1518 { "nb", UDISPCTX_CAPITALIZATION_FOR_STANDALONE, today_nbTitle, yesterday_nbTitle },
1519 #endif
1520 { NULL, (UDisplayContext)0, NULL, NULL }
1521 };
1522
1523 static const UChar zoneGMT[] = { 0x47,0x4D,0x54,0 }; /* "GMT" */
1524 static const UDate july022008 = 1215000000000.0;
1525 enum { kUbufMax = 64, kBbufMax = 3*kUbufMax };
1526
TestContext(void)1527 static void TestContext(void) {
1528 const TestContextItem* textContextItemPtr;
1529 const TestRelativeContextItem* textRelContextItemPtr;
1530 for (textContextItemPtr = textContextItems; textContextItemPtr->locale != NULL; ++textContextItemPtr) {
1531 UErrorCode status = U_ZERO_ERROR;
1532 UDateTimePatternGenerator* udtpg = udatpg_open(textContextItemPtr->locale, &status);
1533 if ( U_SUCCESS(status) ) {
1534 UChar ubuf[kUbufMax];
1535 int32_t len = udatpg_getBestPattern(udtpg, textContextItemPtr->skeleton, -1, ubuf, kUbufMax, &status);
1536 if ( U_SUCCESS(status) ) {
1537 UDateFormat* udfmt = udat_open(UDAT_PATTERN, UDAT_PATTERN, textContextItemPtr->locale, zoneGMT, -1, ubuf, len, &status);
1538 if ( U_SUCCESS(status) ) {
1539 udat_setContext(udfmt, textContextItemPtr->capitalizationContext, &status);
1540 if ( U_SUCCESS(status) ) {
1541 UDisplayContext getContext;
1542 len = udat_format(udfmt, july022008, ubuf, kUbufMax, NULL, &status);
1543 if ( U_FAILURE(status) ) {
1544 log_err("FAIL: udat_format for locale %s, capitalizationContext %d, status %s\n",
1545 textContextItemPtr->locale, (int)textContextItemPtr->capitalizationContext, u_errorName(status) );
1546 status = U_ZERO_ERROR;
1547 } else if (u_strncmp(ubuf, textContextItemPtr->expectedFormat, kUbufMax) != 0) {
1548 char bbuf1[kBbufMax];
1549 char bbuf2[kBbufMax];
1550 log_err("FAIL: udat_format for locale %s, capitalizationContext %d, expected %s, got %s\n",
1551 textContextItemPtr->locale, (int)textContextItemPtr->capitalizationContext,
1552 u_austrncpy(bbuf1,textContextItemPtr->expectedFormat,kUbufMax), u_austrncpy(bbuf2,ubuf,kUbufMax) );
1553 }
1554 getContext = udat_getContext(udfmt, UDISPCTX_TYPE_CAPITALIZATION, &status);
1555 if ( U_FAILURE(status) ) {
1556 log_err("FAIL: udat_getContext for locale %s, capitalizationContext %d, status %s\n",
1557 textContextItemPtr->locale, (int)textContextItemPtr->capitalizationContext, u_errorName(status) );
1558 } else if (getContext != textContextItemPtr->capitalizationContext) {
1559 log_err("FAIL: udat_getContext for locale %s, capitalizationContext %d, got context %d\n",
1560 textContextItemPtr->locale, (int)textContextItemPtr->capitalizationContext, (int)getContext );
1561 }
1562 } else {
1563 log_err("FAIL: udat_setContext for locale %s, capitalizationContext %d, status %s\n",
1564 textContextItemPtr->locale, (int)textContextItemPtr->capitalizationContext, u_errorName(status) );
1565 }
1566 udat_close(udfmt);
1567 } else {
1568 log_data_err("FAIL: udat_open for locale %s, status %s\n", textContextItemPtr->locale, u_errorName(status) );
1569 }
1570 } else {
1571 log_err("FAIL: udatpg_getBestPattern for locale %s, status %s\n", textContextItemPtr->locale, u_errorName(status) );
1572 }
1573 udatpg_close(udtpg);
1574 } else {
1575 log_data_err("FAIL: udatpg_open for locale %s, status %s\n", textContextItemPtr->locale, u_errorName(status) );
1576 }
1577 }
1578 for (textRelContextItemPtr = textContextRelativeItems; textRelContextItemPtr->locale != NULL; ++textRelContextItemPtr) {
1579 UErrorCode status = U_ZERO_ERROR;
1580 UCalendar* ucal = ucal_open(zoneGMT, -1, "root", UCAL_GREGORIAN, &status);
1581 if ( U_SUCCESS(status) ) {
1582 UDateFormat* udfmt = udat_open(UDAT_NONE, UDAT_LONG_RELATIVE, textRelContextItemPtr->locale, zoneGMT, -1, NULL, 0, &status);
1583 if ( U_SUCCESS(status) ) {
1584 udat_setContext(udfmt, textRelContextItemPtr->capitalizationContext, &status);
1585 if ( U_SUCCESS(status) ) {
1586 UDate yesterday, today = ucal_getNow();
1587 UChar ubuf[kUbufMax];
1588 char bbuf1[kBbufMax];
1589 char bbuf2[kBbufMax];
1590 int32_t len = udat_format(udfmt, today, ubuf, kUbufMax, NULL, &status);
1591 (void)len;
1592 if ( U_FAILURE(status) ) {
1593 log_err("FAIL: udat_format today for locale %s, capitalizationContext %d, status %s\n",
1594 textRelContextItemPtr->locale, (int)textRelContextItemPtr->capitalizationContext, u_errorName(status) );
1595 } else if (u_strncmp(ubuf, textRelContextItemPtr->expectedFormatToday, kUbufMax) != 0) {
1596 log_err("FAIL: udat_format today for locale %s, capitalizationContext %d, expected %s, got %s\n",
1597 textRelContextItemPtr->locale, (int)textRelContextItemPtr->capitalizationContext,
1598 u_austrncpy(bbuf1,textRelContextItemPtr->expectedFormatToday,kUbufMax), u_austrncpy(bbuf2,ubuf,kUbufMax) );
1599 }
1600 status = U_ZERO_ERROR;
1601 ucal_setMillis(ucal, today, &status);
1602 ucal_add(ucal, UCAL_DATE, -1, &status);
1603 yesterday = ucal_getMillis(ucal, &status);
1604 if ( U_SUCCESS(status) ) {
1605 len = udat_format(udfmt, yesterday, ubuf, kUbufMax, NULL, &status);
1606 if ( U_FAILURE(status) ) {
1607 log_err("FAIL: udat_format yesterday for locale %s, capitalizationContext %d, status %s\n",
1608 textRelContextItemPtr->locale, (int)textRelContextItemPtr->capitalizationContext, u_errorName(status) );
1609 } else if (u_strncmp(ubuf, textRelContextItemPtr->expectedFormatYesterday, kUbufMax) != 0) {
1610 log_err("FAIL: udat_format yesterday for locale %s, capitalizationContext %d, expected %s, got %s\n",
1611 textRelContextItemPtr->locale, (int)textRelContextItemPtr->capitalizationContext,
1612 u_austrncpy(bbuf1,textRelContextItemPtr->expectedFormatYesterday,kUbufMax), u_austrncpy(bbuf2,ubuf,kUbufMax) );
1613 }
1614 }
1615 } else {
1616 log_err("FAIL: udat_setContext relative for locale %s, capitalizationContext %d, status %s\n",
1617 textRelContextItemPtr->locale, (int)textRelContextItemPtr->capitalizationContext, u_errorName(status) );
1618 }
1619 udat_close(udfmt);
1620 } else {
1621 log_data_err("FAIL: udat_open relative for locale %s, status %s\n", textRelContextItemPtr->locale, u_errorName(status) );
1622 }
1623 ucal_close(ucal);
1624 } else {
1625 log_data_err("FAIL: ucal_open for locale root, status %s\n", u_errorName(status) );
1626 }
1627 }
1628 }
1629
1630
1631 // overrideNumberFormat[i][0] is to tell which field to set,
1632 // overrideNumberFormat[i][1] is the expected result
1633 static const char * overrideNumberFormat[][2] = {
1634 {"", "\\u521D\\u4E03 \\u521D\\u4E8C"},
1635 {"d", "07 \\u521D\\u4E8C"},
1636 {"do", "07 \\u521D\\u4E8C"},
1637 {"Md", "\\u521D\\u4E03 \\u521D\\u4E8C"},
1638 {"MdMMd", "\\u521D\\u4E03 \\u521D\\u4E8C"},
1639 {"mixed", "\\u521D\\u4E03 \\u521D\\u4E8C"}
1640 };
1641
TestOverrideNumberFormat(void)1642 static void TestOverrideNumberFormat(void) {
1643 UErrorCode status = U_ZERO_ERROR;
1644 UChar pattern[50];
1645 UChar expected[50];
1646 UChar fields[50];
1647 char bbuf1[kBbufMax];
1648 char bbuf2[kBbufMax];
1649 const char* localeString = "zh@numbers=hanidays";
1650 UDateFormat* fmt;
1651 const UNumberFormat* getter_result;
1652 int32_t i;
1653
1654 u_uastrcpy(fields, "d");
1655 u_uastrcpy(pattern,"MM d");
1656
1657 fmt=udat_open(UDAT_PATTERN, UDAT_PATTERN, "en_US", zoneGMT, -1, pattern, u_strlen(pattern), &status);
1658 if (!assertSuccess("udat_open()", &status)) {
1659 return;
1660 }
1661
1662 // loop 5 times to check getter/setter
1663 for (i = 0; i < 5; i++){
1664 status = U_ZERO_ERROR;
1665 UNumberFormat* overrideFmt;
1666 overrideFmt = unum_open(UNUM_DEFAULT, NULL, 0, localeString, NULL, &status);
1667 assertSuccess("unum_open()", &status);
1668 udat_adoptNumberFormatForFields(fmt, fields, overrideFmt, &status);
1669 overrideFmt = NULL; // no longer valid
1670 assertSuccess("udat_setNumberFormatForField()", &status);
1671
1672 getter_result = udat_getNumberFormatForField(fmt, 0x0064 /*'d'*/);
1673 if(getter_result == NULL) {
1674 log_err("FAIL: udat_getNumberFormatForField did not return a valid pointer\n");
1675 }
1676 }
1677 {
1678 status = U_ZERO_ERROR;
1679 UNumberFormat* overrideFmt;
1680 overrideFmt = unum_open(UNUM_DEFAULT, NULL, 0, localeString, NULL, &status);
1681 assertSuccess("unum_open()", &status);
1682 if (U_SUCCESS(status)) {
1683 udat_setNumberFormat(fmt, overrideFmt); // test the same override NF will not crash
1684 }
1685 unum_close(overrideFmt);
1686 }
1687 udat_close(fmt);
1688
1689 for (i=0; i<UPRV_LENGTHOF(overrideNumberFormat); i++){
1690 status = U_ZERO_ERROR;
1691 UChar ubuf[kUbufMax];
1692 UDateFormat* fmt2;
1693 UNumberFormat* overrideFmt2;
1694
1695 fmt2 =udat_open(UDAT_PATTERN, UDAT_PATTERN,"en_US", zoneGMT, -1, pattern, u_strlen(pattern), &status);
1696 assertSuccess("udat_open() with en_US", &status);
1697
1698 overrideFmt2 = unum_open(UNUM_DEFAULT, NULL, 0, localeString, NULL, &status);
1699 assertSuccess("unum_open() in loop", &status);
1700
1701 if (U_FAILURE(status)) {
1702 continue;
1703 }
1704
1705 u_uastrcpy(fields, overrideNumberFormat[i][0]);
1706 u_unescape(overrideNumberFormat[i][1], expected, UPRV_LENGTHOF(expected));
1707
1708 if ( strcmp(overrideNumberFormat[i][0], "") == 0 ) { // use the one w/o field
1709 udat_adoptNumberFormat(fmt2, overrideFmt2);
1710 } else if ( strcmp(overrideNumberFormat[i][0], "mixed") == 0 ) { // set 1 field at first but then full override, both(M & d) should be override
1711 const char* singleLocale = "en@numbers=hebr";
1712 UNumberFormat* singleOverrideFmt;
1713 u_uastrcpy(fields, "d");
1714
1715 singleOverrideFmt = unum_open(UNUM_DEFAULT, NULL, 0, singleLocale, NULL, &status);
1716 assertSuccess("unum_open() in mixed", &status);
1717
1718 udat_adoptNumberFormatForFields(fmt2, fields, singleOverrideFmt, &status);
1719 assertSuccess("udat_setNumberFormatForField() in mixed", &status);
1720
1721 udat_adoptNumberFormat(fmt2, overrideFmt2);
1722 } else if ( strcmp(overrideNumberFormat[i][0], "do") == 0 ) { // o is an invalid field
1723 udat_adoptNumberFormatForFields(fmt2, fields, overrideFmt2, &status);
1724 if(status == U_INVALID_FORMAT_ERROR) {
1725 udat_close(fmt2);
1726 status = U_ZERO_ERROR;
1727 continue;
1728 }
1729 } else {
1730 udat_adoptNumberFormatForFields(fmt2, fields, overrideFmt2, &status);
1731 assertSuccess("udat_setNumberFormatForField() in loop", &status);
1732 }
1733
1734 udat_format(fmt2, july022008, ubuf, kUbufMax, NULL, &status);
1735 assertSuccess("udat_format() july022008", &status);
1736
1737 if (u_strncmp(ubuf, expected, kUbufMax) != 0)
1738 log_err("fail: udat_format for locale, expected %s, got %s\n",
1739 u_austrncpy(bbuf1,expected,kUbufMax), u_austrncpy(bbuf2,ubuf,kUbufMax) );
1740
1741 udat_close(fmt2);
1742 }
1743 }
1744
1745 /*
1746 * Ticket #11523
1747 * udat_parse and udat_parseCalendar should have the same error code when given the same invalid input.
1748 */
TestParseErrorReturnValue(void)1749 static void TestParseErrorReturnValue(void) {
1750 UErrorCode status = U_ZERO_ERROR;
1751 UErrorCode expectStatus = U_PARSE_ERROR;
1752 UDateFormat* df;
1753 UCalendar* cal;
1754
1755 df = udat_open(UDAT_DEFAULT, UDAT_DEFAULT, NULL, NULL, -1, NULL, -1, &status);
1756 if (!assertSuccessCheck("udat_open()", &status, true)) {
1757 return;
1758 }
1759
1760 cal = ucal_open(NULL, 0, "en_US", UCAL_GREGORIAN, &status);
1761 if (!assertSuccess("ucal_open()", &status)) {
1762 return;
1763 }
1764
1765 udat_parse(df, NULL, -1, NULL, &status);
1766 if (status != expectStatus) {
1767 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));
1768 }
1769
1770 status = U_ZERO_ERROR;
1771 udat_parseCalendar(df, cal, NULL, -1, NULL, &status);
1772 if (status != expectStatus) {
1773 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));
1774 }
1775
1776 ucal_close(cal);
1777 udat_close(df);
1778 }
1779
1780 /*
1781 * Ticket #11553
1782 * Test new udat_formatForFields, udat_formatCalendarForFields (and UFieldPositionIterator)
1783 */
1784 static const char localeForFields[] = "en_US";
1785 /* zoneGMT[]defined above */
1786 static const UDate date2015Feb25 = 1424841000000.0; /* Wednesday, February 25, 2015 at 5:10:00 AM GMT */
1787 static const UChar patNoFields[] = { 0x0027, 0x0078, 0x0078, 0x0078, 0x0027, 0 }; /* "'xxx'" */
1788
1789 typedef struct {
1790 int32_t field;
1791 int32_t beginPos;
1792 int32_t endPos;
1793 } FieldsData;
1794 static const FieldsData expectedFields[] = {
1795 { UDAT_DAY_OF_WEEK_FIELD /* 9*/, 0, 9 },
1796 { UDAT_MONTH_FIELD /* 2*/, 11, 19 },
1797 { UDAT_DATE_FIELD /* 3*/, 20, 22 },
1798 { UDAT_YEAR_FIELD /* 1*/, 24, 28 },
1799 { UDAT_HOUR1_FIELD /*15*/, 32, 33 },
1800 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
1801 { UDAT_TIME_SEPARATOR_FIELD /*35*/, 33, 34 },
1802 #endif
1803 { UDAT_MINUTE_FIELD /* 6*/, 34, 36 },
1804 #if UDAT_HAS_PATTERN_CHAR_FOR_TIME_SEPARATOR
1805 { UDAT_TIME_SEPARATOR_FIELD /*35*/, 36, 37 },
1806 #endif
1807 { UDAT_SECOND_FIELD /* 7*/, 37, 39 },
1808 { UDAT_AM_PM_FIELD /*14*/, 40, 42 },
1809 { UDAT_TIMEZONE_FIELD /*17*/, 43, 46 },
1810 { -1, -1, -1 },
1811 };
1812
1813 enum {kUBufFieldsLen = 128, kBBufFieldsLen = 256 };
1814
TestFormatForFields(void)1815 static void TestFormatForFields(void) {
1816 UErrorCode status = U_ZERO_ERROR;
1817 UFieldPositionIterator* fpositer = ufieldpositer_open(&status);
1818 if ( U_FAILURE(status) ) {
1819 log_err("ufieldpositer_open fails, status %s\n", u_errorName(status));
1820 } else {
1821 UDateFormat* udfmt = udat_open(UDAT_LONG, UDAT_FULL, localeForFields, zoneGMT, -1, NULL, 0, &status);
1822 UCalendar* ucal = ucal_open(zoneGMT, -1, localeForFields, UCAL_DEFAULT, &status);
1823 if ( U_FAILURE(status) ) {
1824 log_data_err("udat_open or ucal_open fails for locale %s, status %s (Are you missing data?)\n", localeForFields, u_errorName(status));
1825 } else {
1826 int32_t ulen, field, beginPos, endPos;
1827 UChar ubuf[kUBufFieldsLen];
1828 const FieldsData * fptr;
1829
1830 status = U_ZERO_ERROR;
1831 ulen = udat_formatForFields(udfmt, date2015Feb25, ubuf, kUBufFieldsLen, fpositer, &status);
1832 if ( U_FAILURE(status) ) {
1833 log_err("udat_formatForFields fails, status %s\n", u_errorName(status));
1834 } else {
1835 for (fptr = expectedFields; ; fptr++) {
1836 field = ufieldpositer_next(fpositer, &beginPos, &endPos);
1837 if (field != fptr->field || (field >= 0 && (beginPos != fptr->beginPos || endPos != fptr->endPos))) {
1838 if (fptr->field >= 0) {
1839 log_err("udat_formatForFields as \"%s\"; expect field %d range %d-%d, get field %d range %d-%d\n",
1840 aescstrdup(ubuf, ulen), fptr->field, fptr->beginPos, fptr->endPos, field, beginPos, endPos);
1841 } else {
1842 log_err("udat_formatForFields as \"%s\"; expect field < 0, get field %d range %d-%d\n",
1843 aescstrdup(ubuf, ulen), field, beginPos, endPos);
1844 }
1845 break;
1846 }
1847 if (field < 0) {
1848 break;
1849 }
1850 }
1851 }
1852
1853 ucal_setMillis(ucal, date2015Feb25, &status);
1854 status = U_ZERO_ERROR;
1855 ulen = udat_formatCalendarForFields(udfmt, ucal, ubuf, kUBufFieldsLen, fpositer, &status);
1856 if ( U_FAILURE(status) ) {
1857 log_err("udat_formatCalendarForFields fails, status %s\n", u_errorName(status));
1858 } else {
1859 for (fptr = expectedFields; ; fptr++) {
1860 field = ufieldpositer_next(fpositer, &beginPos, &endPos);
1861 if (field != fptr->field || (field >= 0 && (beginPos != fptr->beginPos || endPos != fptr->endPos))) {
1862 if (fptr->field >= 0) {
1863 log_err("udat_formatFudat_formatCalendarForFieldsorFields as \"%s\"; expect field %d range %d-%d, get field %d range %d-%d\n",
1864 aescstrdup(ubuf, ulen), fptr->field, fptr->beginPos, fptr->endPos, field, beginPos, endPos);
1865 } else {
1866 log_err("udat_formatCalendarForFields as \"%s\"; expect field < 0, get field %d range %d-%d\n",
1867 aescstrdup(ubuf, ulen), field, beginPos, endPos);
1868 }
1869 break;
1870 }
1871 if (field < 0) {
1872 break;
1873 }
1874 }
1875 }
1876
1877 udat_applyPattern(udfmt, false, patNoFields, -1);
1878 status = U_ZERO_ERROR;
1879 ulen = udat_formatForFields(udfmt, date2015Feb25, ubuf, kUBufFieldsLen, fpositer, &status);
1880 if ( U_FAILURE(status) ) {
1881 log_err("udat_formatForFields with no-field pattern fails, status %s\n", u_errorName(status));
1882 } else {
1883 field = ufieldpositer_next(fpositer, &beginPos, &endPos);
1884 if (field >= 0) {
1885 log_err("udat_formatForFields with no-field pattern as \"%s\"; expect field < 0, get field %d range %d-%d\n",
1886 aescstrdup(ubuf, ulen), field, beginPos, endPos);
1887 }
1888 }
1889
1890 ucal_close(ucal);
1891 udat_close(udfmt);
1892 }
1893 ufieldpositer_close(fpositer);
1894 }
1895 }
1896
TestForceGannenNumbering(void)1897 static void TestForceGannenNumbering(void) {
1898 UErrorCode status;
1899 const char* locID = "ja_JP@calendar=japanese";
1900 UDate refDate = 600336000000.0; // 1989 Jan 9 Monday = Heisei 1
1901 const UChar* testSkeleton = u"yMMMd";
1902
1903 // Test Gannen year forcing
1904 status = U_ZERO_ERROR;
1905 UDateTimePatternGenerator* dtpgen = udatpg_open(locID, &status);
1906 if (U_FAILURE(status)) {
1907 log_data_err("Fail in udatpg_open locale %s: %s", locID, u_errorName(status));
1908 } else {
1909 UChar pattern[kUbufMax];
1910 int32_t patlen = udatpg_getBestPattern(dtpgen, testSkeleton, -1, pattern, kUbufMax, &status);
1911 if (U_FAILURE(status)) {
1912 log_data_err("Fail in udatpg_getBestPattern locale %s: %s", locID, u_errorName(status));
1913 } else {
1914 UDateFormat *testFmt = udat_open(UDAT_PATTERN, UDAT_PATTERN, locID, NULL, 0, pattern, patlen, &status);
1915 if (U_FAILURE(status)) {
1916 log_data_err("Fail in udat_open locale %s: %s", locID, u_errorName(status));
1917 } else {
1918 UChar testString[kUbufMax];
1919 int32_t testStrLen = udat_format(testFmt, refDate, testString, kUbufMax, NULL, &status);
1920 if (U_FAILURE(status)) {
1921 log_err("Fail in udat_format locale %s: %s", locID, u_errorName(status));
1922 } else if (testStrLen < 3 || testString[2] != 0x5143) {
1923 char bbuf[kBbufMax];
1924 u_austrncpy(bbuf, testString, testStrLen);
1925 log_err("Formatting year 1 as Gannen, got%s but expected 3rd char to be 0x5143", bbuf);
1926 }
1927 udat_close(testFmt);
1928 }
1929 }
1930 udatpg_close(dtpgen);
1931 }
1932 }
1933
1934 typedef struct {
1935 UChar patternChar; // for future use
1936 UDateFormatField dateField;
1937 UCalendarDateFields calField;
1938 } PatternCharToFieldsItem;
1939
1940 static const PatternCharToFieldsItem patCharToFieldsItems[] = {
1941 { u'G', UDAT_ERA_FIELD, UCAL_ERA },
1942 { u'y', UDAT_YEAR_FIELD, UCAL_YEAR },
1943 { u'Y', UDAT_YEAR_WOY_FIELD, UCAL_YEAR_WOY },
1944 { u'Q', UDAT_QUARTER_FIELD, UCAL_MONTH },
1945 { u'H', UDAT_HOUR_OF_DAY0_FIELD, UCAL_HOUR_OF_DAY },
1946 { u'r', UDAT_RELATED_YEAR_FIELD, UCAL_EXTENDED_YEAR },
1947 { u'B', UDAT_FLEXIBLE_DAY_PERIOD_FIELD, UCAL_FIELD_COUNT },
1948 { u'$', UDAT_FIELD_COUNT, UCAL_FIELD_COUNT },
1949 { 0xFFFF, (UDateFormatField)-1, UCAL_FIELD_COUNT }, // patternChar ignored here
1950 { (UChar)0, (UDateFormatField)0, (UCalendarDateFields)0 } // terminator
1951 };
1952
TestMapDateToCalFields(void)1953 static void TestMapDateToCalFields(void){
1954 const PatternCharToFieldsItem* itemPtr;
1955 for ( itemPtr=patCharToFieldsItems; itemPtr->patternChar!=(UChar)0; itemPtr++) {
1956 UCalendarDateFields calField = udat_toCalendarDateField(itemPtr->dateField);
1957 if (calField != itemPtr->calField) {
1958 log_err("for pattern char 0x%04X, dateField %d, expect calField %d and got %d\n",
1959 itemPtr->patternChar, itemPtr->dateField, itemPtr->calField, calField);
1960 }
1961 }
1962 }
1963
TestNarrowQuarters(void)1964 static void TestNarrowQuarters(void) {
1965 // Test for rdar://79238094
1966 const UChar* testCases[] = {
1967 u"en_US", u"QQQQ y", u"1st quarter 1970",
1968 u"en_US", u"QQQ y", u"Q1 1970",
1969 u"en_US", u"QQQQQ y", u"1 1970",
1970 u"es_MX", u"QQQQ y", u"1.er trimestre 1970",
1971 u"es_MX", u"QQQ y", u"T1 1970",
1972 u"es_MX", u"QQQQQ y", u"1 1970",
1973 u"en_US", u"qqqq", u"1st quarter",
1974 u"en_US", u"qqq", u"Q1",
1975 u"en_US", u"qqqqq", u"1",
1976 u"es_MX", u"qqqq", u"1.er trimestre",
1977 u"es_MX", u"qqq", u"T1",
1978 u"es_MX", u"qqqqq", u"1T",
1979 };
1980
1981 UErrorCode err = U_ZERO_ERROR;
1982 UChar result[100];
1983 UDate parsedDate = 0;
1984 UDate expectedFormatParsedDate = 0;
1985 UDate expectedStandaloneParsedDate = 0;
1986
1987 for (int32_t i = 0; i < UPRV_LENGTHOF(testCases); i += 3) {
1988 const UChar* localeID = testCases[i];
1989 const UChar* pattern = testCases[i + 1];
1990 const UChar* expectedResult = testCases[i + 2];
1991
1992 err = U_ZERO_ERROR;
1993
1994 UDateFormat* df = udat_open(UDAT_PATTERN, UDAT_PATTERN, austrdup(localeID), u"UTC", 0, pattern, -1, &err);
1995
1996 udat_format(df, 0, result, 100, NULL, &err);
1997
1998 if (assertSuccess("Formatting date failed", &err)) {
1999 assertUEquals("Wrong formatting result", expectedResult, result);
2000 }
2001
2002 bool patternIsStandaloneQuarter = u_strchr(pattern, u'q') != NULL;
2003
2004 parsedDate = udat_parse(df, expectedResult, -1, NULL, &err);
2005 if (!patternIsStandaloneQuarter && expectedFormatParsedDate == 0) {
2006 expectedFormatParsedDate = parsedDate;
2007 } else if (patternIsStandaloneQuarter && expectedStandaloneParsedDate == 0) {
2008 expectedStandaloneParsedDate = parsedDate;
2009 }
2010
2011 if (assertSuccess("Parsing date failed", &err)) {
2012 if (patternIsStandaloneQuarter) {
2013 assertDoubleEquals("Wrong parsing result", expectedStandaloneParsedDate, parsedDate);
2014 } else {
2015 assertDoubleEquals("Wrong parsing result", expectedFormatParsedDate, parsedDate);
2016 }
2017 }
2018
2019 udat_close(df);
2020 }
2021 }
2022
TestExtraneousCharacters(void)2023 static void TestExtraneousCharacters(void) {
2024 // regression test for ICU-21802
2025 UErrorCode err = U_ZERO_ERROR;
2026 UCalendar* cal = ucal_open(u"UTC", -1, "en_US", UCAL_GREGORIAN, &err);
2027 UDateFormat* df = udat_open(UDAT_PATTERN, UDAT_PATTERN, "en_US", u"UTC", -1, u"yyyyMMdd", -1, &err);
2028
2029 if (assertSuccess("Failed to create date formatter and calendar", &err)) {
2030 udat_setLenient(df, false);
2031
2032 udat_parseCalendar(df, cal, u"2021", -1, NULL, &err);
2033 assertTrue("Success parsing '2021'", err == U_PARSE_ERROR);
2034
2035 err = U_ZERO_ERROR;
2036 udat_parseCalendar(df, cal, u"2021-", -1, NULL, &err);
2037 assertTrue("Success parsing '2021-'", err == U_PARSE_ERROR);
2038 }
2039 udat_close(df);
2040 ucal_close(cal);
2041 }
2042
2043 #endif /* #if !UCONFIG_NO_FORMATTING */
2044