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