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