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