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