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