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