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