1 // Copyright (C) 2016 and later: Unicode, Inc. and others. 2 // License & terms of use: http://www.unicode.org/copyright.html 3 /******************************************************************** 4 * COPYRIGHT: 5 * Copyright (c) 1997-2014, International Business Machines Corporation and 6 * others. All Rights Reserved. 7 ********************************************************************/ 8 /******************************************************************************** 9 * 10 * File CDTDPTST.C 11 * 12 * Modification History: 13 * Name Description 14 * Madhu Katragadda Creation 15 ********************************************************************************* 16 */ 17 /* INDEPTH TEST FOR DATE FORMAT */ 18 19 #include "unicode/utypes.h" 20 21 #if !UCONFIG_NO_FORMATTING 22 23 #include "unicode/uloc.h" 24 #include "unicode/udat.h" 25 #include "unicode/ucal.h" 26 #include "unicode/unum.h" 27 #include "unicode/ustring.h" 28 #include "cintltst.h" 29 #include "cdtdptst.h" 30 #include "cformtst.h" 31 32 #include "cmemory.h" 33 34 void addDtFrDepTest(TestNode** root); 35 36 void addDtFrDepTest(TestNode** root) 37 { 38 addTest(root, &TestTwoDigitYearDSTParse, "tsformat/cdtdptst/TestTwoDigitYearDSTParse"); 39 addTest(root, &TestPartialParse994, "tsformat/cdtdptst/TestPartialParse994"); 40 addTest(root, &TestRunTogetherPattern985, "tsformat/cdtdptst/TestRunTogetherPattern985"); 41 addTest(root, &TestCzechMonths459, "tsformat/cdtdptst/TestCzechMonths459"); 42 addTest(root, &TestQuotePattern161, "tsformat/cdtdptst/TestQuotePattern161"); 43 addTest(root, &TestBooleanAttributes, "tsformat/cdtdptst/TestBooleanAttributes"); 44 45 46 } 47 48 /** 49 * Test the parsing of 2-digit years. 50 */ 51 void TestTwoDigitYearDSTParse() 52 { 53 UDateFormat *fullFmt, *fmt; 54 UErrorCode status = U_ZERO_ERROR; 55 UChar *pattern; 56 UDate d; 57 UChar *s; 58 int32_t pos; 59 60 ctest_setTimeZone(NULL, &status); 61 62 pattern=(UChar*)malloc(sizeof(UChar) * (strlen("EEE MMM dd HH:mm:ss.SSS zzz yyyy G")+1 )); 63 u_uastrcpy(pattern, "EEE MMM dd HH:mm:ss.SSS zzz yyyy G"); 64 fullFmt= udat_open(UDAT_PATTERN, UDAT_PATTERN,"en_US",NULL,0,pattern, u_strlen(pattern),&status); 65 if(U_FAILURE(status)) { 66 log_data_err("FAIL: Error in creating a date format using udat_openPattern %s - (Are you missing data?)\n", 67 myErrorName(status) ); 68 } 69 else { 70 log_verbose("PASS: creating dateformat using udat_openPattern() succesful\n"); 71 72 u_uastrcpy(pattern, "dd-MMM-yy h:mm:ss 'o''clock' a z"); 73 fmt= udat_open(UDAT_PATTERN,UDAT_PATTERN,"en_US", NULL, 0,pattern, u_strlen(pattern), &status); 74 75 76 s=(UChar*)malloc(sizeof(UChar) * (strlen("03-Apr-04 2:20:47 o'clock AM PST")+1) ); 77 u_uastrcpy(s, "03-Apr-04 2:20:47 o'clock AM PST"); 78 pos=0; 79 d = udat_parse(fmt, s, u_strlen(s), &pos, &status); 80 if (U_FAILURE(status)) { 81 log_err("FAIL: Could not parse \"%s\"\n", austrdup(s)); 82 } else { 83 UCalendar *cal = ucal_open(NULL, 0, uloc_getDefault(), UCAL_TRADITIONAL, &status); 84 if (U_FAILURE(status)) { 85 log_err_status(status, "FAIL: Could not open calendar: %s\n", u_errorName(status)); 86 } else { 87 int32_t h; 88 ucal_setMillis(cal, d, &status); 89 h = ucal_get(cal, UCAL_HOUR_OF_DAY, &status); 90 if (U_FAILURE(status)) { 91 log_err("FAIL: Some calendar operations failed"); 92 } else if (h != 2) { 93 log_err("FAIL: Parse of \"%s\" returned HOUR_OF_DAY %d\n", 94 austrdup(s), h); 95 } 96 ucal_close(cal); 97 } 98 } 99 100 udat_close(fullFmt); 101 udat_close(fmt); 102 free(s); 103 } 104 free(pattern); 105 106 ctest_resetTimeZone(); 107 } 108 109 110 /** 111 * Verify that strings which contain incomplete specifications are parsed 112 * correctly. In some instances, this means not being parsed at all, and 113 * returning an appropriate error. 114 */ 115 void TestPartialParse994() 116 { 117 int32_t pos; 118 UDateFormat *f; 119 UErrorCode status = U_ZERO_ERROR; 120 UChar *s; 121 UChar *fmtChars; 122 UDate d, null; 123 null=0; 124 125 /* this is supposed to open default date format, but later on it treats it like it is "en_US" 126 - very bad if you try to run the tests on machine where default locale is NOT "en_US" */ 127 /* f = udat_open(UDAT_DEFAULT, UDAT_SHORT, NULL, NULL, 0, &status); */ 128 f = udat_open(UDAT_DEFAULT, UDAT_SHORT, "en_US", NULL, 0, NULL, 0,&status); 129 if(U_FAILURE(status)){ 130 log_data_err("FAIL: ErrorCode received during test: %s (Are you missing data?)\n", myErrorName(status)); 131 return; 132 } 133 s=(UChar*)malloc(sizeof(UChar) * (strlen("01/01/1997 10:11:42 AM")+1) ); 134 u_uastrcpy(s, "01/01/1997 10:11:42 AM"); 135 pos=0; 136 d = udat_parse(f, s, u_strlen(s), &pos, &status); 137 if(U_FAILURE(status)) { 138 log_data_err("FAIL: could not parse - exitting"); 139 return; 140 } 141 fmtChars = myDateFormat(f, d); 142 if(fmtChars) { 143 log_verbose("%s\n", fmtChars); 144 } else { 145 log_data_err("FAIL: could not format \n"); 146 return; 147 } 148 tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/01 10:11:42", d); 149 tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/01 10:", null); 150 tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/01 10", null); 151 tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/01 ", null); 152 tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/01", null); 153 udat_close(f); 154 free(s); 155 } 156 157 158 159 void tryPat994(UDateFormat* format, const char* pattern, const char* s, UDate expected) 160 { 161 UChar *f; 162 UChar *str, *pat; 163 UDate date; 164 UDate null=0; 165 int32_t pos; 166 UErrorCode status = U_ZERO_ERROR; 167 str=(UChar*)malloc(sizeof(UChar) * (strlen(s) + 1) ); 168 u_uastrcpy(str, s); 169 pat=(UChar*)malloc(sizeof(UChar) * (strlen(pattern) + 1) ); 170 u_uastrcpy(pat, pattern); 171 log_verbose("Pattern : %s ; String : %s\n", austrdup(pat), austrdup(str)); 172 udat_applyPattern(format, FALSE, pat, u_strlen(pat)); 173 pos=0; 174 date = udat_parse(format, str, u_strlen(str), &pos, &status); 175 if(U_FAILURE(status) || date == null) { 176 log_verbose("ParseException: : %s\n", myErrorName(status) ); 177 if (expected != null) 178 log_err("FAIL: Expected: %s\n", austrdup(myDateFormat(format, expected)) ); 179 } 180 else { 181 f=myDateFormat(format, date); 182 log_verbose(" parse( %s ) -> %s\n", austrdup(str), austrdup(f)); 183 if (expected == null || date != expected) 184 log_err("FAIL: Expected null for \"%s\"\n", s); 185 if (u_strcmp(f, str) !=0) 186 log_err("FAIL: Expected : %s\n", austrdup(str) ); 187 } 188 189 free(str); 190 free(pat); 191 } 192 193 194 /** 195 * Verify the behavior of patterns in which digits for different fields run together 196 * without intervening separators. 197 */ 198 void TestRunTogetherPattern985() 199 { 200 int32_t pos; 201 UChar *pattern=NULL, *now=NULL, *then=NULL; 202 UDateFormat *format; 203 UDate date1, date2; 204 UErrorCode status = U_ZERO_ERROR; 205 pattern=(UChar*)malloc(sizeof(UChar) * (strlen("yyyyMMddHHmmssSSS")+1) ); 206 u_uastrcpy(pattern, "yyyyMMddHHmmssSSS"); 207 format = udat_open(UDAT_PATTERN, UDAT_PATTERN, NULL, NULL, 0,pattern, u_strlen(pattern), &status); 208 if(U_FAILURE(status)){ 209 log_data_err("FAIL: Error in date format construction with pattern: %s - (Are you missing data?)\n", myErrorName(status)); 210 return; 211 } 212 date1 = ucal_getNow(); 213 now=myDateFormat(format, date1); 214 log_verbose("%s\n", austrdup(now) ); 215 pos = 0; 216 date2 = udat_parse(format, now, u_strlen(now), &pos, &status); 217 if (date2 == 0) log_verbose("Parse stopped at : %d\n", pos); 218 else then=myDateFormat(format, date2); 219 log_verbose("%s\n", austrdup(then) ); 220 if (!(date2 == date1)) log_err("FAIL\n"); 221 222 udat_close(format); 223 free(pattern); 224 225 } 226 227 /** 228 * Verify the handling of Czech June and July, which have the unique attribute that 229 * one is a proper prefix substring of the other. 230 */ 231 void TestCzechMonths459() 232 { 233 int32_t lneed, pos; 234 UChar *pattern=NULL, *tzID=NULL; 235 UChar *juneStr, *julyStr; 236 UDateFormat *fmt; 237 UCalendar *cal; 238 UDate june, july, d; 239 UErrorCode status = U_ZERO_ERROR; 240 UChar *date; 241 242 ctest_setTimeZone(NULL, &status); 243 fmt = udat_open(UDAT_FULL, UDAT_FULL, "cs", NULL, 0, NULL, 0, &status); 244 if(U_FAILURE(status)){ 245 log_data_err("Error in constructing the date format -> %s (Are you missing data?)\n", u_errorName(status)); 246 ctest_resetTimeZone(); 247 return; 248 } 249 lneed=0; 250 lneed=udat_toPattern(fmt, TRUE, NULL, lneed, &status); 251 if(status==U_BUFFER_OVERFLOW_ERROR){ 252 status=U_ZERO_ERROR; 253 pattern=(UChar*)malloc(sizeof(UChar) * (lneed+1) ); 254 udat_toPattern(fmt, TRUE, pattern, lneed+1, &status); 255 } 256 if(U_FAILURE(status)){ log_err("Error in extracting the pattern\n"); } 257 tzID=(UChar*)malloc(sizeof(UChar) * 4); 258 u_uastrcpy(tzID, "GMT"); 259 cal=ucal_open(tzID, u_strlen(tzID), "cs", UCAL_GREGORIAN, &status); 260 if(U_FAILURE(status)){ log_err("error in ucal_open caldef : %s\n", myErrorName(status)); } 261 262 ucal_setDate(cal, 1997, UCAL_JUNE, 15, &status); 263 june=ucal_getMillis(cal, &status); 264 ucal_setDate(cal, 1997, UCAL_JULY, 15, &status); 265 july=ucal_getMillis(cal, &status); 266 267 juneStr = myDateFormat(fmt, june); 268 julyStr = myDateFormat(fmt, july); 269 pos=0; 270 if(juneStr == NULL) { 271 log_data_err("Can't load juneStr. Quitting.\n"); 272 return; 273 } 274 d = udat_parse(fmt, juneStr, u_strlen(juneStr), &pos, &status); 275 date = myDateFormat(fmt, d); 276 277 if(U_SUCCESS(status)){ 278 UChar* out1 = myDateFormat(fmt, june); 279 UChar* out2 = myDateFormat(fmt, d); 280 if(u_strcmp(out1, out2) !=0) 281 log_err("Error in handling the czech month june\n"); 282 else 283 log_verbose("Pass: Date = %s (czech month June)\n", aescstrdup(date, -1)); 284 }else{ 285 log_err("udat_parse failed. Error. %s\n",u_errorName(status)); 286 } 287 pos=0; 288 d = udat_parse(fmt, julyStr, u_strlen(julyStr), &pos, &status); 289 date = myDateFormat(fmt, d); 290 if(u_strcmp(myDateFormat(fmt, july), myDateFormat(fmt, d) ) !=0) 291 log_err("Error in handling the czech month july\n"); 292 else 293 log_verbose("Pass: Date = %s (czech month July)\n", aescstrdup(date, -1)); 294 295 ctest_resetTimeZone(); 296 udat_close(fmt); 297 ucal_close(cal); 298 free(pattern); 299 free(tzID); 300 } 301 302 /** 303 * Test the handling of single quotes in patterns. 304 */ 305 void TestQuotePattern161() 306 { 307 UDateFormat *format; 308 UCalendar *cal; 309 UDate currentTime_1; 310 UChar *pattern, *tzID, *exp; 311 UChar *dateString; 312 UErrorCode status = U_ZERO_ERROR; 313 const char* expStr = "04/13/1999 at 10:42:28 AM "; 314 315 ctest_setTimeZone(NULL, &status); 316 317 pattern=(UChar*)malloc(sizeof(UChar) * (strlen("MM/dd/yyyy 'at' hh:mm:ss a zzz")+1) ); 318 u_uastrcpy(pattern, "MM/dd/yyyy 'at' hh:mm:ss a zzz"); 319 320 /* this is supposed to open default date format, but later on it treats it like it is "en_US" 321 - very bad if you try to run the tests on machine where default locale is NOT "en_US" */ 322 /* format= udat_openPattern(pattern, u_strlen(pattern), NULL, &status); */ 323 format= udat_open(UDAT_PATTERN, UDAT_PATTERN,"en_US", NULL, 0,pattern, u_strlen(pattern), &status); 324 if(U_FAILURE(status)){ 325 log_data_err("error in udat_open: %s - (Are you missing data?)\n", myErrorName(status)); 326 return; 327 } 328 tzID=(UChar*)malloc(sizeof(UChar) * 4); 329 u_uastrcpy(tzID, "PST"); 330 /* this is supposed to open default date format, but later on it treats it like it is "en_US" 331 - very bad if you try to run the tests on machine where default locale is NOT "en_US" */ 332 /* cal=ucal_open(tzID, u_strlen(tzID), NULL, UCAL_TRADITIONAL, &status); */ 333 cal=ucal_open(tzID, u_strlen(tzID), "en_US", UCAL_TRADITIONAL, &status); 334 if(U_FAILURE(status)){ log_err("error in ucal_open cal : %s\n", myErrorName(status)); } 335 336 ucal_setDateTime(cal, 1999, UCAL_APRIL, 13, 10, 42, 28, &status); 337 currentTime_1 = ucal_getMillis(cal, &status); 338 339 dateString = myDateFormat(format, currentTime_1); 340 exp=(UChar*)malloc(sizeof(UChar) * (strlen(expStr) + 1) ); 341 u_uastrcpy(exp, expStr); 342 343 log_verbose("%s\n", austrdup(dateString) ); 344 if(u_strncmp(dateString, exp, (int32_t)strlen(expStr)) !=0) 345 log_err("Error in formatting a pattern with single quotes\n"); 346 347 udat_close(format); 348 ucal_close(cal); 349 free(exp); 350 free(tzID); 351 free(pattern); 352 353 ctest_resetTimeZone(); 354 } 355 356 /* 357 * Testing udat_getBooleanAttribute and unum_setBooleanAttribute() to make sure basic C wrapper functionality is present 358 */ 359 void TestBooleanAttributes(void) 360 { 361 UDateFormat *en; 362 UErrorCode status=U_ZERO_ERROR; 363 UBool initialState = TRUE; 364 UBool switchedState = FALSE; 365 366 log_verbose("\ncreating a date format with english locale\n"); 367 en = udat_open(UDAT_FULL, UDAT_DEFAULT, "en_US", NULL, 0, NULL, 0, &status); 368 if(U_FAILURE(status)) { 369 log_data_err("error in creating the dateformat -> %s (Are you missing data?)\n", 370 myErrorName(status) ); 371 return; 372 } 373 374 375 initialState = udat_getBooleanAttribute(en, UDAT_PARSE_ALLOW_NUMERIC, &status); 376 if(initialState != TRUE) switchedState = TRUE; // if it wasn't the default of TRUE, then flip what we expect 377 378 udat_setBooleanAttribute(en, UDAT_PARSE_ALLOW_NUMERIC, switchedState, &status); 379 if(switchedState != udat_getBooleanAttribute(en, UDAT_PARSE_ALLOW_NUMERIC, &status)) { 380 log_err("unable to switch states!"); 381 return; 382 } 383 384 udat_close(en); 385 } 386 387 #endif /* #if !UCONFIG_NO_FORMATTING */ 388