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