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