1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
3 /********************************************************************
4 * COPYRIGHT:
5 * Copyright (c) 1997-2016, International Business Machines Corporation and
6 * others. All Rights Reserved.
7 ********************************************************************/
8 /********************************************************************************
9 *
10 * File CDATTST.C
11 *
12 * Modification History:
13 * Name Description
14 * Madhu Katragadda Creation
15 *********************************************************************************
16 */
17
18 /* C API TEST FOR DATE FORMAT */
19
20 #include "unicode/utypes.h"
21
22 #if !UCONFIG_NO_FORMATTING
23
24 #include "unicode/uloc.h"
25 #include "unicode/udat.h"
26 #include "unicode/udatpg.h"
27 #include "unicode/ucal.h"
28 #include "unicode/unum.h"
29 #include "unicode/ustring.h"
30 #include "unicode/ufieldpositer.h"
31 #include "cintltst.h"
32 #include "cdattst.h"
33 #include "cformtst.h"
34 #include "cmemory.h"
35
36 #include <math.h>
37
38 static void TestExtremeDates(void);
39 static void TestAllLocales(void);
40 static void TestRelativeCrash(void);
41 static void TestContext(void);
42 static void TestCalendarDateParse(void);
43 static void TestParseErrorReturnValue(void);
44 static void TestFormatForFields(void);
45
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 \\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 /*
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 #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 }
692 free(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
735 free(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 */
TestDateFormatCalendar()832 static 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 */
TestCalendarDateParse()959 static 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*/
getCurrentYear()1039 static 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. */
VerifygetSymbols(UDateFormat * datfor,UDateFormatSymbolType type,int32_t idx,const char * expected)1055 static 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
VerifysetSymbols(UDateFormat * datfor,UDateFormatSymbolType type,int32_t idx,const char * expected)1090 static 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
VerifygetsetSymbols(UDateFormat * from,UDateFormat * to,UDateFormatSymbolType type,int32_t idx)1133 static 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
myNumformat(const UNumberFormat * numfor,double d)1187 static 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 */
_aux1ExtremeDates(UDateFormat * fmt,UDate date,UChar * buf,int32_t buflen,char * cbuf,UErrorCode * ec)1223 static 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 */
_aux2ExtremeDates(UDateFormat * fmt,UDate small,UDate large,UChar * buf,int32_t buflen,char * cbuf,int32_t count,UErrorCode * ec)1243 static 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 */
TestExtremeDates()1272 static 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
TestAllLocales(void)1296 static 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
TestRelativeCrash(void)1317 static 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
1431 static const UChar skeleton_yMMMM[] = { 0x79,0x4D,0x4D,0x4D,0x4D,0 }; /* "yMMMM"; fr maps to "MMMM y", cs maps to "LLLL y" */
1432 static const UChar july2008_frDefault[] = { 0x6A,0x75,0x69,0x6C,0x6C,0x65,0x74,0x20,0x32,0x30,0x30,0x38,0 }; /* "juillet 2008" */
1433 static const UChar july2008_frTitle[] = { 0x4A,0x75,0x69,0x6C,0x6C,0x65,0x74,0x20,0x32,0x30,0x30,0x38,0 }; /* "Juillet 2008" sentence-begin, standalone */
1434 static const UChar july2008_csDefault[] = { 0x10D,0x65,0x72,0x76,0x65,0x6E,0x65,0x63,0x20,0x32,0x30,0x30,0x38,0 }; /* "c(hacek)ervenec 2008" */
1435 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 */
1436
1437 typedef struct {
1438 const char * locale;
1439 const UChar * skeleton;
1440 UDisplayContext capitalizationContext;
1441 const UChar * expectedFormat;
1442 } TestContextItem;
1443
1444 static 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
1462 static const UChar today_enDefault[] = { 0x74,0x6F,0x64,0x61,0x79,0 }; /* "today" */
1463 static const UChar today_enTitle[] = { 0x54,0x6F,0x64,0x61,0x79,0 }; /* "Today" sentence-begin, uiListOrMenu, standalone */
1464 static const UChar yesterday_enDefault[] = { 0x79,0x65,0x73,0x74,0x65,0x72,0x64,0x61,0x79,0 }; /* "yesterday" */
1465 static const UChar yesterday_enTitle[] = { 0x59,0x65,0x73,0x74,0x65,0x72,0x64,0x61,0x79,0 }; /* "Yesterday" sentence-begin, uiListOrMenu, standalone */
1466 static const UChar today_nbDefault[] = { 0x69,0x20,0x64,0x61,0x67,0 }; /* "i dag" */
1467 static const UChar today_nbTitle[] = { 0x49,0x20,0x64,0x61,0x67,0 }; /* "I dag" sentence-begin, standalone */
1468 static const UChar yesterday_nbDefault[] = { 0x69,0x20,0x67,0xE5,0x72,0 };
1469 static const UChar yesterday_nbTitle[] = { 0x49,0x20,0x67,0xE5,0x72,0 };
1470
1471 typedef struct {
1472 const char * locale;
1473 UDisplayContext capitalizationContext;
1474 const UChar * expectedFormatToday;
1475 const UChar * expectedFormatYesterday;
1476 } TestRelativeContextItem;
1477
1478 static 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
1496 static const UChar zoneGMT[] = { 0x47,0x4D,0x54,0 }; /* "GMT" */
1497 static const UDate july022008 = 1215000000000.0;
1498 enum { kUbufMax = 64, kBbufMax = 3*kUbufMax };
1499
TestContext(void)1500 static 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
1606 static 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
TestOverrideNumberFormat(void)1615 static 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 */
TestParseErrorReturnValue(void)1713 static 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 */
1748 static const char localeForFields[] = "en_US";
1749 /* zoneGMT[]defined above */
1750 static const UDate date2015Feb25 = 1424841000000.0; /* Wednesday, February 25, 2015 at 5:10:00 AM GMT */
1751 static const UChar patNoFields[] = { 0x0027, 0x0078, 0x0078, 0x0078, 0x0027, 0 }; /* "'xxx'" */
1752
1753 typedef struct {
1754 int32_t field;
1755 int32_t beginPos;
1756 int32_t endPos;
1757 } FieldsData;
1758 static 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
1777 enum {kUBufFieldsLen = 128, kBBufFieldsLen = 256 };
1778
TestFormatForFields(void)1779 static 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