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