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