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