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