1 /******************************************************************** 2 * COPYRIGHT: 3 * Copyright (c) 2008-2013, International Business Machines Corporation and 4 * others. All Rights Reserved. 5 ********************************************************************/ 6 7 #include "unicode/utypes.h" 8 9 #if !UCONFIG_NO_FORMATTING 10 11 #include <stdio.h> 12 #include <stdlib.h> 13 #include "dtptngts.h" 14 15 #include "unicode/calendar.h" 16 #include "unicode/smpdtfmt.h" 17 #include "unicode/dtfmtsym.h" 18 #include "unicode/dtptngen.h" 19 #include "loctest.h" 20 21 22 // This is an API test, not a unit test. It doesn't test very many cases, and doesn't 23 // try to test the full functionality. It just calls each function in the class and 24 // verifies that it works on a basic level. 25 26 void IntlTestDateTimePatternGeneratorAPI::runIndexedTest( int32_t index, UBool exec, const char* &name, char* /*par*/ ) 27 { 28 if (exec) logln("TestSuite DateTimePatternGeneratorAPI"); 29 switch (index) { 30 TESTCASE(0, testAPI); 31 TESTCASE(1, testOptions); 32 default: name = ""; break; 33 } 34 } 35 36 #define MAX_LOCALE 11 37 38 /** 39 * Test various generic API methods of DateTimePatternGenerator for API coverage. 40 */ 41 void IntlTestDateTimePatternGeneratorAPI::testAPI(/*char *par*/) 42 { 43 UnicodeString patternData[] = { 44 UnicodeString("yM"), // 00 45 UnicodeString("yMMM"), // 01 46 UnicodeString("yMd"), // 02 47 UnicodeString("yMMMd"), // 03 48 UnicodeString("Md"), // 04 49 UnicodeString("MMMd"), // 05 50 UnicodeString("MMMMd"), // 06 51 UnicodeString("yQQQ"), // 07 52 UnicodeString("hhmm"), // 08 53 UnicodeString("HHmm"), // 09 54 UnicodeString("jjmm"), // 10 55 UnicodeString("mmss"), // 11 56 UnicodeString("yyyyMMMM"), // 12 57 UnicodeString("MMMEd"), // 13 58 UnicodeString("Ed"), // 14 59 UnicodeString("jmmssSSS"), // 15 60 UnicodeString(), 61 }; 62 63 const char* testLocale[MAX_LOCALE][4] = { 64 {"en", "US", "", ""}, // 0 65 {"en", "US", "", "calendar=japanese"}, // 1 66 {"de", "DE", "", ""}, // 2 67 {"fi", "", "", ""}, // 3 68 {"es", "", "", ""}, // 4 69 {"ja", "", "", ""}, // 5 70 {"ja", "", "", "calendar=japanese"}, // 6 71 {"zh", "Hans", "CN", ""}, // 7 72 {"zh", "TW", "", "calendar=roc"}, // 8 73 {"ru", "", "", ""}, // 9 74 {"zh", "", "", "calendar=chinese"}, // 10 75 }; 76 77 // For Weds, Jan 13, 1999, 23:58:59 78 UnicodeString patternResults[] = { 79 // en_US // 0 en_US 80 UnicodeString("1/1999"), // 00: yM 81 UnicodeString("Jan 1999"), // 01: yMMM 82 UnicodeString("1/13/1999"), // 02: yMd 83 UnicodeString("Jan 13, 1999"), // 03: yMMMd 84 UnicodeString("1/13"), // 04: Md 85 UnicodeString("Jan 13"), // 05: MMMd 86 UnicodeString("January 13"), // 06: MMMMd 87 UnicodeString("Q1 1999"), // 07: yQQQ 88 UnicodeString("11:58 PM"), // 08: hhmm 89 UnicodeString("23:58"), // 09: HHmm 90 UnicodeString("11:58 PM"), // 10: jjmm 91 UnicodeString("58:59"), // 11: mmss 92 UnicodeString("January 1999"), // 12: yyyyMMMM 93 UnicodeString("Wed, Jan 13"), // 13: MMMEd -> EEE, MMM d 94 UnicodeString("13 Wed"), // 14: Ed -> d EEE 95 UnicodeString("11:58:59.123 PM"), // 15: jmmssSSS -> "h:mm:ss.SSS a" 96 97 // en_US@calendar=japanese // 1 en_US@calendar=japanese 98 UnicodeString("1/11 H"), // 0: yM 99 UnicodeString("Jan 11 Heisei"), // 1: yMMM 100 UnicodeString("1/13/11 H"), // 2: yMd 101 UnicodeString("Jan 13, 11 Heisei"), // 3: yMMMd 102 UnicodeString("1/13"), // 4: Md 103 UnicodeString("Jan 13"), // 5: MMMd 104 UnicodeString("January 13"), // 6: MMMMd 105 UnicodeString("Q1 11 Heisei"), // 7: yQQQ 106 UnicodeString("11:58 PM"), // 8: hhmm 107 UnicodeString("23:58"), // 9: HHmm 108 UnicodeString("11:58 PM"), // 10: jjmm 109 UnicodeString("58:59"), // 11: mmss 110 UnicodeString("January 11 Heisei"), // 12: yyyyMMMM 111 UnicodeString("Wed, Jan 13"), // 13: MMMEd -> EEE, MMM d" 112 UnicodeString("13 Wed"), // 14: Ed -> d EEE 113 UnicodeString("11:58:59.123 PM"), // 15: jmmssSSS -> "h:mm:ss.SSS a" 114 115 // de_DE // 2 de_DE 116 UnicodeString("1.1999"), // 00: yM 117 UnicodeString("Jan. 1999"), // 01: yMMM 118 UnicodeString("13.1.1999"), // 02: yMd 119 UnicodeString("13. Jan. 1999"), // 03: yMMMd 120 UnicodeString("13.1."), // 04: Md 121 UnicodeString("13. Jan."), // 05: MMMd 122 UnicodeString("13. Januar"), // 06: MMMMd 123 UnicodeString("Q1 1999"), // 07: yQQQ 124 UnicodeString("11:58 nachm."), // 08: hhmm 125 UnicodeString("23:58"), // 09: HHmm 126 UnicodeString("23:58"), // 10: jjmm 127 UnicodeString("58:59"), // 11: mmss 128 UnicodeString("Januar 1999"), // 12: yyyyMMMM 129 UnicodeString("Mi., 13. Jan."), // 13: MMMEd -> EEE, d. MMM 130 UnicodeString("Mi., 13."), // 14: Ed -> EEE d. 131 UnicodeString("23:58:59,123"), // 15: jmmssSSS -> "HH:mm:ss,SSS" 132 133 // fi // 3 fi 134 UnicodeString("1.1999"), // 00: yM (fixed expected result per ticket:6626:) 135 UnicodeString("tammi 1999"), // 01: yMMM 136 UnicodeString("13.1.1999"), // 02: yMd 137 UnicodeString("13. tammikuuta 1999"), // 03: yMMMd 138 UnicodeString("13.1."), // 04: Md 139 UnicodeString("13. tammikuuta"), // 05: MMMd 140 UnicodeString("13. tammikuuta"), // 06: MMMMd 141 UnicodeString("1. nelj. 1999"), // 07: yQQQ 142 UnicodeString("11.58 ip."), // 08: hhmm 143 UnicodeString("23.58"), // 09: HHmm 144 UnicodeString("23.58"), // 10: jjmm 145 UnicodeString("58.59"), // 11: mmss 146 UnicodeString("tammikuu 1999"), // 12: yyyyMMMM 147 UnicodeString("ke 13. tammikuuta"), // 13: MMMEd -> EEE d. MMM 148 UnicodeString("ke 13."), // 14: Ed -> ccc d. 149 UnicodeString("23.58.59,123"), // 15: jmmssSSS -> "H.mm.ss,SSS" 150 151 // es // 4 es 152 UnicodeString("1/1999"), // 00: yM -> "M/y" 153 UnicodeString("ene 1999"), // 01: yMMM -> "MMM y" 154 UnicodeString("13/1/1999"), // 02: yMd -> "d/M/y" 155 UnicodeString("13 ene 1999"), // 03: yMMMd -> "d MMM y" 156 UnicodeString("13/1"), // 04: Md -> "d/M" 157 UnicodeString("13 ene"), // 05: MMMd -> "d MMM" 158 UnicodeString("13 de enero"), // 06: MMMMd -> "d 'de' MMMM" 159 UnicodeString("T1 1999"), // 07: yQQQ -> "QQQ y" 160 UnicodeString("11:58 p.m."), // 08: hhmm -> "hh:mm a" 161 UnicodeString("23:58"), // 09: HHmm -> "HH:mm" 162 UnicodeString("23:58"), // 10: jjmm -> "HH:mm" 163 UnicodeString("58:59"), // 11: mmss -> "mm:ss" 164 UnicodeString("enero de 1999"), // 12: yyyyMMMM -> "MMMM 'de' yyyy" 165 CharsToUnicodeString("mi\\u00E9 13 ene"), // 13: MMMEd -> "E d MMM" 166 CharsToUnicodeString("mi\\u00E9 13"), // 14: Ed -> "EEE d" 167 UnicodeString("23:58:59,123"), // 15: jmmssSSS -> "H:mm:ss,SSS" 168 169 // ja // 5 ja 170 UnicodeString("1999/1"), // 00: yM -> y/M 171 CharsToUnicodeString("1999\\u5E741\\u6708"), // 01: yMMM -> y\u5E74M\u6708 172 UnicodeString("1999/1/13"), // 02: yMd -> y/M/d 173 CharsToUnicodeString("1999\\u5E741\\u670813\\u65E5"), // 03: yMMMd -> y\u5E74M\u6708d\u65E5 174 UnicodeString("1/13"), // 04: Md -> M/d 175 CharsToUnicodeString("1\\u670813\\u65E5"), // 05: MMMd -> M\u6708d\u65E5 176 CharsToUnicodeString("1\\u670813\\u65E5"), // 06: MMMMd -> M\u6708d\u65E5 177 UnicodeString("1999/1Q"), // 07: yQQQ -> yQQQ 178 CharsToUnicodeString("\\u5348\\u5F8C11:58"), // 08: hhmm 179 UnicodeString("23:58"), // 09: HHmm -> HH:mm 180 UnicodeString("23:58"), // 10: jjmm 181 UnicodeString("58:59"), // 11: mmss -> mm:ss 182 CharsToUnicodeString("1999\\u5E741\\u6708"), // 12: yyyyMMMM -> y\u5E74M\u6708 183 CharsToUnicodeString("1\\u670813\\u65E5(\\u6C34)"), // 13: MMMEd -> M\u6708d\u65E5(EEE) 184 CharsToUnicodeString("13\\u65E5(\\u6C34)"), // 14: Ed -> d\u65E5(EEE) 185 UnicodeString("23:58:59.123"), // 15: jmmssSSS -> "H:mm:ss.SSS" 186 187 // ja@calendar=japanese // 6 ja@calendar=japanese 188 CharsToUnicodeString("\\u5E73\\u621011/1"), // 00: yM -> Gy/m 189 CharsToUnicodeString("\\u5E73\\u621011\\u5E741\\u6708"), // 01: yMMM -> Gy\u5E74M\u6708 190 CharsToUnicodeString("\\u5E73\\u621011/1/13"), // 02: yMd -> Gy/m/d 191 CharsToUnicodeString("\\u5E73\\u621011\\u5E741\\u670813\\u65E5"), // 03: yMMMd -> Gy\u5E74M\u6708d\u65E5 192 UnicodeString("1/13"), // 04: Md -> M/d 193 CharsToUnicodeString("1\\u670813\\u65E5"), // 05: MMMd -> M\u6708d\u65E5 194 CharsToUnicodeString("1\\u670813\\u65E5"), // 06: MMMMd -> M\u6708d\u65E5 195 CharsToUnicodeString("\\u5E73\\u621011/1Q"), // 07: yQQQ -> Gy/QQQ 196 CharsToUnicodeString("\\u5348\\u5F8C11:58"), // 08: hhmm -> 197 UnicodeString("23:58"), // 09: HHmm -> HH:mm (as for ja) 198 UnicodeString("23:58"), // 10: jjmm 199 UnicodeString("58:59"), // 11: mmss -> mm:ss (as for ja) 200 CharsToUnicodeString("\\u5E73\\u621011\\u5E741\\u6708"), // 12: yyyyMMMM -> Gyyyy\u5E74M\u6708 201 CharsToUnicodeString("1\\u670813\\u65E5(\\u6C34)"), // 13: MMMEd -> M\u6708d\u65E5(EEE) 202 CharsToUnicodeString("13\\u65E5(\\u6C34)"), // 14: Ed -> d\u65E5(EEE) 203 UnicodeString("23:58:59.123"), // 15: jmmssSSS -> "H:mm:ss.SSS" 204 205 // zh_Hans_CN // 7 zh_Hans_CN 206 UnicodeString("1999/1", -1, US_INV), // 00: yM 207 CharsToUnicodeString("1999\\u5E741\\u6708"), // 01: yMMM -> yyyy\u5E74MMM (fixed expected result per ticket:6626:) 208 CharsToUnicodeString("1999/1/13"), // 02: yMd 209 CharsToUnicodeString("1999\\u5E741\\u670813\\u65E5"), // 03: yMMMd -> yyyy\u5E74MMMd\u65E5 (fixed expected result per ticket:6626:) 210 UnicodeString("1/13"), // 04: Md 211 CharsToUnicodeString("1\\u670813\\u65E5"), // 05: MMMd -> M\u6708d\u65E5 (fixed expected result per ticket:6626:) 212 CharsToUnicodeString("1\\u670813\\u65E5"), // 06: MMMMd -> M\u6708d\u65E5 213 CharsToUnicodeString("1999\\u5E74\\u7B2C1\\u5B63\\u5EA6"), // 07: yQQQ 214 CharsToUnicodeString("\\u4E0B\\u534811:58"), // 08: hhmm 215 UnicodeString("23:58"), // 09: HHmm 216 CharsToUnicodeString("\\u4E0B\\u534811:58"), // 10: jjmm 217 UnicodeString("58:59"), // 11: mmss 218 CharsToUnicodeString("1999\\u5E741\\u6708"), // 12: yyyyMMMM -> yyyy\u5E74MMM 219 CharsToUnicodeString("1\\u670813\\u65E5\\u5468\\u4E09"), // 13: MMMEd -> MMMd\u65E5EEE 220 CharsToUnicodeString("13\\u65E5\\u5468\\u4E09"), // 14: Ed -> d\u65E5EEE 221 CharsToUnicodeString("\\u4E0B\\u534811:58:59.123"), // 15: jmmssSSS -> "ah:mm:ss.SSS" 222 223 // zh_TW@calendar=roc // 8 zh_TW@calendar=roc 224 CharsToUnicodeString("\\u6C11\\u570B88/1"), // 00: yM -> Gy/M 225 CharsToUnicodeString("\\u6C11\\u570B88\\u5E741\\u6708"), // 01: yMMM -> Gy\u5E74M\u6708 226 CharsToUnicodeString("\\u6C11\\u570B88/1/13"), // 02: yMd -> Gy/M/d 227 CharsToUnicodeString("\\u6C11\\u570B88\\u5E741\\u670813\\u65E5"), // 03: yMMMd -> Gy\u5E74M\u6708d\u65E5 228 UnicodeString("1/13"), // 04: Md -> M/d 229 CharsToUnicodeString("1\\u670813\\u65E5"), // 05: MMMd ->M\u6708d\u65E5 230 CharsToUnicodeString("1\\u670813\\u65E5"), // 06: MMMMd ->M\u6708d\u65E5 231 CharsToUnicodeString("\\u6C11\\u570B88\\u5E741\\u5B63"), // 07: yQQQ -> Gy QQQ 232 CharsToUnicodeString("\\u4E0B\\u534811:58"), // 08: hhmm -> 233 UnicodeString("23:58"), // 09: HHmm -> 234 CharsToUnicodeString("\\u4E0B\\u534811:58"), // 10: jjmm 235 UnicodeString("58:59"), // 11: mmss -> 236 CharsToUnicodeString("\\u6C11\\u570B88\\u5E741\\u6708"), // 12: yyyyMMMM -> Gy\u5E74M\u670 237 CharsToUnicodeString("1\\u670813\\u65E5\\u9031\\u4E09"), // 13: MMMEd -> M\u6708d\u65E5EEE 238 CharsToUnicodeString("13\\u65E5\\uff08\\u9031\\u4E09\\uff09"), // 14: Ed -> d\u65E5\\uff08EEEi\\uff09 239 CharsToUnicodeString("\\u4E0B\\u534811:58:59.123"), // 15: jmmssSSS -> "ah:mm:ss.SSS" 240 241 // ru // 9 ru 242 UnicodeString("01.1999"), // 00: yM -> MM.y 243 CharsToUnicodeString("\\u042F\\u043D\\u0432. 1999"), // 01: yMMM -> LLL y 244 UnicodeString("13.01.1999"), // 02: yMd -> dd.MM.y 245 CharsToUnicodeString("13 \\u044F\\u043D\\u0432. 1999 \\u0433."), // 03: yMMMd -> d MMM y 246 UnicodeString("13.01"), // 04: Md -> dd.MM 247 CharsToUnicodeString("13 \\u044F\\u043D\\u0432."), // 05: MMMd -> d MMM 248 CharsToUnicodeString("13 \\u044F\\u043D\\u0432\\u0430\\u0440\\u044F"), // 06: MMMMd -> d MMMM 249 CharsToUnicodeString("1-\\u0439 \\u043A\\u0432. 1999 \\u0433."), // 07: yQQQ -> y QQQ 250 CharsToUnicodeString("11:58 \\u043F\\u043E\\u0441\\u043B\\u0435 \\u043F\\u043E\\u043B\\u0443\\u0434\\u043D\\u044F"), // 07: hhmm -> hh:mm a 251 UnicodeString("23:58"), // 09: HHmm -> HH:mm 252 UnicodeString("23:58"), // 10: jjmm -> HH:mm 253 UnicodeString("58:59"), // 11: mmss -> mm:ss 254 CharsToUnicodeString("\\u042F\\u043D\\u0432\\u0430\\u0440\\u044C 1999"), // 12: yyyyMMMM -> LLLL y 255 CharsToUnicodeString("\\u0421\\u0440, 13 \\u044F\\u043D\\u0432."), // 13: MMMEd -> ccc, d MMM 256 CharsToUnicodeString("\\u0421\\u0440, 13"), // 14: Ed -> EEE, d 257 UnicodeString("23:58:59,123"), // 15: jmmssSSS -> "H:mm:ss,SSS" 258 259 // zh@calendar=chinese // 10 zh@calendar=chinese 260 CharsToUnicodeString("\\u620A\\u5BC5\\u5E7411\\u6708"), // 00: yM 261 CharsToUnicodeString("\\u620A\\u5BC5\\u5E74\\u5341\\u4E00\\u6708"), // 01: yMMM 262 CharsToUnicodeString("\\u620A\\u5BC5\\u5E7411\\u670826\\u65E5"), // 02: yMd 263 CharsToUnicodeString("\\u620A\\u5BC5\\u5E74\\u5341\\u4E00\\u670826\\u65E5"), // 03: yMMMd 264 UnicodeString("11-26"), // 04: Md 265 CharsToUnicodeString("\\u5341\\u4E00\\u670826\\u65E5"), // 05: MMMd 266 CharsToUnicodeString("\\u5341\\u4E00\\u670826\\u65E5"), // 06: MMMMd 267 CharsToUnicodeString("\\u620A\\u5BC5\\u5E74\\u7b2c\\u56db\\u5B63\\u5EA6"), // 07: yQQQ 268 CharsToUnicodeString("\\u4E0B\\u534811:58"), // 08: hhmm 269 UnicodeString("23:58"), // 09: HHmm 270 CharsToUnicodeString("\\u4E0B\\u534811:58"), // 10: jjmm 271 UnicodeString("58:59"), // 11: mmss 272 CharsToUnicodeString("\\u620A\\u5BC5\\u5E74\\u5341\\u4E00\\u6708"), // 12: yyyyMMMM 273 CharsToUnicodeString("\\u5341\\u4E00\\u670826\\u65E5\\u5468\\u4E09"), // 13: MMMEd 274 CharsToUnicodeString("26\\u65E5\\u5468\\u4E09"), // 14: Ed -> d\u65E5EEE 275 CharsToUnicodeString("\\u4E0B\\u534811:58:59.123"), // 15: jmmssSS 276 277 UnicodeString(), 278 }; 279 280 UnicodeString patternTests2[] = { 281 UnicodeString("yyyyMMMdd"), 282 UnicodeString("yyyyqqqq"), 283 UnicodeString("yMMMdd"), 284 UnicodeString("EyyyyMMMdd"), 285 UnicodeString("yyyyMMdd"), 286 UnicodeString("yyyyMMM"), 287 UnicodeString("yyyyMM"), 288 UnicodeString("yyMM"), 289 UnicodeString("yMMMMMd"), 290 UnicodeString("EEEEEMMMMMd"), 291 UnicodeString("MMMd"), 292 UnicodeString("MMMdhmm"), 293 UnicodeString("EMMMdhmms"), 294 UnicodeString("MMdhmm"), 295 UnicodeString("EEEEMMMdhmms"), 296 UnicodeString("yyyyMMMddhhmmss"), 297 UnicodeString("EyyyyMMMddhhmmss"), 298 UnicodeString("hmm"), 299 UnicodeString("hhmm"), 300 UnicodeString("hhmmVVVV"), 301 UnicodeString(""), 302 }; 303 UnicodeString patternResults2[] = { 304 UnicodeString("Oct 14, 1999"), 305 UnicodeString("4th quarter 1999"), 306 UnicodeString("Oct 14, 1999"), 307 UnicodeString("Thu, Oct 14, 1999"), 308 UnicodeString("10/14/1999"), 309 UnicodeString("Oct 1999"), 310 UnicodeString("10/1999"), 311 UnicodeString("10/99"), 312 UnicodeString("O 14, 1999"), 313 UnicodeString("T, O 14"), 314 UnicodeString("Oct 14"), 315 UnicodeString("Oct 14, 6:58 AM"), 316 UnicodeString("Thu, Oct 14, 6:58:59 AM"), 317 UnicodeString("10/14, 6:58 AM"), 318 UnicodeString("Thursday, Oct 14, 6:58:59 AM"), 319 UnicodeString("Oct 14, 1999, 6:58:59 AM"), 320 UnicodeString("Thu, Oct 14, 1999, 6:58:59 AM"), 321 UnicodeString("6:58 AM"), 322 UnicodeString("6:58 AM"), 323 UnicodeString("6:58 AM GMT"), 324 UnicodeString(""), 325 }; 326 327 // results for getSkeletons() and getPatternForSkeleton() 328 const UnicodeString testSkeletonsResults[] = { 329 UnicodeString("HH:mm"), 330 UnicodeString("MMMMd"), 331 UnicodeString("MMMMMdd"), 332 }; 333 334 const UnicodeString testBaseSkeletonsResults[] = { 335 UnicodeString("Hm"), 336 UnicodeString("MMMMd"), 337 UnicodeString("MMMMMd"), 338 }; 339 340 UnicodeString newDecimal(" "); // space 341 UnicodeString newAppendItemName("hrs."); 342 UnicodeString newAppendItemFormat("{1} {0}"); 343 UnicodeString newDateTimeFormat("{1} {0}"); 344 UErrorCode status = U_ZERO_ERROR; 345 UnicodeString conflictingPattern; 346 UDateTimePatternConflict conflictingStatus; 347 348 // ======= Test CreateInstance with default locale 349 logln("Testing DateTimePatternGenerator createInstance from default locale"); 350 351 DateTimePatternGenerator *instFromDefaultLocale=DateTimePatternGenerator::createInstance(status); 352 if (U_FAILURE(status)) { 353 dataerrln("ERROR: Could not create DateTimePatternGenerator (default) - exitting"); 354 return; 355 } 356 else { 357 delete instFromDefaultLocale; 358 } 359 360 // ======= Test CreateInstance with given locale 361 logln("Testing DateTimePatternGenerator createInstance from French locale"); 362 status = U_ZERO_ERROR; 363 DateTimePatternGenerator *instFromLocale=DateTimePatternGenerator::createInstance(Locale::getFrench(), status); 364 if (U_FAILURE(status)) { 365 dataerrln("ERROR: Could not create DateTimePatternGenerator (Locale::getFrench()) - exitting"); 366 return; 367 } 368 369 // ======= Test clone DateTimePatternGenerator 370 logln("Testing DateTimePatternGenerator::clone()"); 371 status = U_ZERO_ERROR; 372 373 374 UnicodeString decimalSymbol = instFromLocale->getDecimal(); 375 UnicodeString newDecimalSymbol = UnicodeString("*"); 376 decimalSymbol = instFromLocale->getDecimal(); 377 instFromLocale->setDecimal(newDecimalSymbol); 378 DateTimePatternGenerator *cloneDTPatternGen=instFromLocale->clone(); 379 decimalSymbol = cloneDTPatternGen->getDecimal(); 380 if (decimalSymbol != newDecimalSymbol) { 381 errln("ERROR: inconsistency is found in cloned object."); 382 } 383 if ( !(*cloneDTPatternGen == *instFromLocale) ) { 384 errln("ERROR: inconsistency is found in cloned object."); 385 } 386 387 if ( *cloneDTPatternGen != *instFromLocale ) { 388 errln("ERROR: inconsistency is found in cloned object."); 389 } 390 391 delete instFromLocale; 392 delete cloneDTPatternGen; 393 394 // ======= Test simple use cases 395 logln("Testing simple use cases"); 396 status = U_ZERO_ERROR; 397 Locale deLocale=Locale::getGermany(); 398 UDate sampleDate=LocaleTest::date(99, 9, 13, 23, 58, 59); 399 DateTimePatternGenerator *gen = DateTimePatternGenerator::createInstance(deLocale, status); 400 if (U_FAILURE(status)) { 401 dataerrln("ERROR: Could not create DateTimePatternGenerator (Locale::getGermany()) - exitting"); 402 return; 403 } 404 UnicodeString findPattern = gen->getBestPattern(UnicodeString("MMMddHmm"), status); 405 SimpleDateFormat *format = new SimpleDateFormat(findPattern, deLocale, status); 406 if (U_FAILURE(status)) { 407 dataerrln("ERROR: Could not create SimpleDateFormat (Locale::getGermany())"); 408 delete gen; 409 return; 410 } 411 TimeZone *zone = TimeZone::createTimeZone(UnicodeString("ECT")); 412 if (zone==NULL) { 413 dataerrln("ERROR: Could not create TimeZone ECT"); 414 delete gen; 415 delete format; 416 return; 417 } 418 format->setTimeZone(*zone); 419 UnicodeString dateReturned, expectedResult; 420 dateReturned.remove(); 421 dateReturned = format->format(sampleDate, dateReturned, status); 422 expectedResult=UnicodeString("14. Okt. 08:58", -1, US_INV); 423 if ( dateReturned != expectedResult ) { 424 errln("ERROR: Simple test in getBestPattern with Locale::getGermany())."); 425 } 426 // add new pattern 427 status = U_ZERO_ERROR; 428 conflictingStatus = gen->addPattern(UnicodeString("d'. von' MMMM", -1, US_INV), true, conflictingPattern, status); 429 if (U_FAILURE(status)) { 430 errln("ERROR: Could not addPattern - d\'. von\' MMMM"); 431 } 432 status = U_ZERO_ERROR; 433 UnicodeString testPattern=gen->getBestPattern(UnicodeString("MMMMdd"), status); 434 testPattern=gen->getBestPattern(UnicodeString("MMMddHmm"), status); 435 format->applyPattern(gen->getBestPattern(UnicodeString("MMMMdHmm"), status)); 436 dateReturned.remove(); 437 dateReturned = format->format(sampleDate, dateReturned, status); 438 expectedResult=UnicodeString("14. von Oktober 08:58", -1, US_INV); 439 if ( dateReturned != expectedResult ) { 440 errln(UnicodeString("ERROR: Simple test addPattern failed!: d\'. von\' MMMM Got: ") + dateReturned + UnicodeString(" Expected: ") + expectedResult); 441 } 442 delete format; 443 444 // get a pattern and modify it 445 format = (SimpleDateFormat *)DateFormat::createDateTimeInstance(DateFormat::kFull, DateFormat::kFull, 446 deLocale); 447 format->setTimeZone(*zone); 448 UnicodeString pattern; 449 pattern = format->toPattern(pattern); 450 dateReturned.remove(); 451 dateReturned = format->format(sampleDate, dateReturned, status); 452 expectedResult=CharsToUnicodeString("Donnerstag, 14. Oktober 1999 08:58:59 Mitteleurop\\u00E4ische Sommerzeit"); 453 if ( dateReturned != expectedResult ) { 454 errln("ERROR: Simple test uses full date format."); 455 errln(UnicodeString(" Got: ") + dateReturned + UnicodeString(" Expected: ") + expectedResult); 456 } 457 458 // modify it to change the zone. 459 UnicodeString newPattern = gen->replaceFieldTypes(pattern, UnicodeString("vvvv"), status); 460 format->applyPattern(newPattern); 461 dateReturned.remove(); 462 dateReturned = format->format(sampleDate, dateReturned, status); 463 expectedResult=CharsToUnicodeString("Donnerstag, 14. Oktober 1999 08:58:59 Mitteleurop\\u00E4ische Zeit"); 464 if ( dateReturned != expectedResult ) { 465 errln("ERROR: Simple test modify the timezone!"); 466 errln(UnicodeString(" Got: ")+ dateReturned + UnicodeString(" Expected: ") + expectedResult); 467 } 468 469 // setDeciaml(), getDeciaml() 470 gen->setDecimal(newDecimal); 471 if (newDecimal != gen->getDecimal()) { 472 errln("ERROR: unexpected result from setDecimal() and getDecimal()!.\n"); 473 } 474 475 // setAppenItemName() , getAppendItemName() 476 gen->setAppendItemName(UDATPG_HOUR_FIELD, newAppendItemName); 477 if (newAppendItemName != gen->getAppendItemName(UDATPG_HOUR_FIELD)) { 478 errln("ERROR: unexpected result from setAppendItemName() and getAppendItemName()!.\n"); 479 } 480 481 // setAppenItemFormat() , getAppendItemFormat() 482 gen->setAppendItemFormat(UDATPG_HOUR_FIELD, newAppendItemFormat); 483 if (newAppendItemFormat != gen->getAppendItemFormat(UDATPG_HOUR_FIELD)) { 484 errln("ERROR: unexpected result from setAppendItemFormat() and getAppendItemFormat()!.\n"); 485 } 486 487 // setDateTimeFormat() , getDateTimeFormat() 488 gen->setDateTimeFormat(newDateTimeFormat); 489 if (newDateTimeFormat != gen->getDateTimeFormat()) { 490 errln("ERROR: unexpected result from setDateTimeFormat() and getDateTimeFormat()!.\n"); 491 } 492 493 // ======== Test getSkeleton and getBaseSkeleton 494 status = U_ZERO_ERROR; 495 pattern = UnicodeString("dd-MMM"); 496 UnicodeString expectedSkeleton = UnicodeString("MMMdd"); 497 UnicodeString expectedBaseSkeleton = UnicodeString("MMMd"); 498 UnicodeString retSkeleton = gen->getSkeleton(pattern, status); 499 if(U_FAILURE(status) || retSkeleton != expectedSkeleton ) { 500 errln("ERROR: Unexpected result from getSkeleton().\n"); 501 errln(UnicodeString(" Got: ") + retSkeleton + UnicodeString(" Expected: ") + expectedSkeleton ); 502 } 503 retSkeleton = gen->getBaseSkeleton(pattern, status); 504 if(U_FAILURE(status) || retSkeleton != expectedBaseSkeleton) { 505 errln("ERROR: Unexpected result from getBaseSkeleton().\n"); 506 errln(UnicodeString(" Got: ") + retSkeleton + UnicodeString(" Expected:")+ expectedBaseSkeleton); 507 } 508 509 pattern = UnicodeString("dd/MMMM/yy"); 510 expectedSkeleton = UnicodeString("yyMMMMdd"); 511 expectedBaseSkeleton = UnicodeString("yMMMMd"); 512 retSkeleton = gen->getSkeleton(pattern, status); 513 if(U_FAILURE(status) || retSkeleton != expectedSkeleton ) { 514 errln("ERROR: Unexpected result from getSkeleton().\n"); 515 errln(UnicodeString(" Got: ") + retSkeleton + UnicodeString(" Expected: ") + expectedSkeleton ); 516 } 517 retSkeleton = gen->getBaseSkeleton(pattern, status); 518 if(U_FAILURE(status) || retSkeleton != expectedBaseSkeleton) { 519 errln("ERROR: Unexpected result from getBaseSkeleton().\n"); 520 errln(UnicodeString(" Got: ") + retSkeleton + UnicodeString(" Expected:")+ expectedBaseSkeleton); 521 } 522 delete format; 523 delete zone; 524 delete gen; 525 526 { 527 // Trac# 6104 528 status = U_ZERO_ERROR; 529 pattern = UnicodeString("YYYYMMM"); 530 UnicodeString expR = CharsToUnicodeString("1999\\u5E741\\u6708"); // fixed expected result per ticket:6626: 531 Locale loc("ja"); 532 UDate testDate1= LocaleTest::date(99, 0, 13, 23, 58, 59); 533 DateTimePatternGenerator *patGen=DateTimePatternGenerator::createInstance(loc, status); 534 if(U_FAILURE(status)) { 535 dataerrln("ERROR: Could not create DateTimePatternGenerator"); 536 return; 537 } 538 UnicodeString bPattern = patGen->getBestPattern(pattern, status); 539 UnicodeString rDate; 540 SimpleDateFormat sdf(bPattern, loc, status); 541 rDate.remove(); 542 rDate = sdf.format(testDate1, rDate); 543 544 logln(UnicodeString(" ja locale with skeleton: YYYYMMM Best Pattern:") + bPattern); 545 logln(UnicodeString(" Formatted date:") + rDate); 546 547 if ( expR!= rDate ) { 548 errln(UnicodeString("\nERROR: Test Japanese month hack Got: ") + rDate + 549 UnicodeString(" Expected: ") + expR ); 550 } 551 552 delete patGen; 553 } 554 { // Trac# 6104 555 Locale loc("zh"); 556 UnicodeString expR = CharsToUnicodeString("1999\\u5E741\\u6708"); // fixed expected result per ticket:6626: 557 UDate testDate1= LocaleTest::date(99, 0, 13, 23, 58, 59); 558 DateTimePatternGenerator *patGen=DateTimePatternGenerator::createInstance(loc, status); 559 if(U_FAILURE(status)) { 560 dataerrln("ERROR: Could not create DateTimePatternGenerator"); 561 return; 562 } 563 UnicodeString bPattern = patGen->getBestPattern(pattern, status); 564 UnicodeString rDate; 565 SimpleDateFormat sdf(bPattern, loc, status); 566 rDate.remove(); 567 rDate = sdf.format(testDate1, rDate); 568 569 logln(UnicodeString(" zh locale with skeleton: YYYYMMM Best Pattern:") + bPattern); 570 logln(UnicodeString(" Formatted date:") + rDate); 571 if ( expR!= rDate ) { 572 errln(UnicodeString("\nERROR: Test Chinese month hack Got: ") + rDate + 573 UnicodeString(" Expected: ") + expR ); 574 } 575 delete patGen; 576 } 577 578 { 579 // Trac# 6172 duplicate time pattern 580 status = U_ZERO_ERROR; 581 pattern = UnicodeString("hmv"); 582 UnicodeString expR = UnicodeString("h:mm a v"); // avail formats has hm -> "h:mm a" (fixed expected result per ticket:6626:) 583 Locale loc("en"); 584 DateTimePatternGenerator *patGen=DateTimePatternGenerator::createInstance(loc, status); 585 if(U_FAILURE(status)) { 586 dataerrln("ERROR: Could not create DateTimePatternGenerator"); 587 return; 588 } 589 UnicodeString bPattern = patGen->getBestPattern(pattern, status); 590 logln(UnicodeString(" en locale with skeleton: hmv Best Pattern:") + bPattern); 591 592 if ( expR!= bPattern ) { 593 errln(UnicodeString("\nERROR: Test EN time format Got: ") + bPattern + 594 UnicodeString(" Expected: ") + expR ); 595 } 596 597 delete patGen; 598 } 599 600 601 // ======= Test various skeletons. 602 logln("Testing DateTimePatternGenerator with various skeleton"); 603 604 status = U_ZERO_ERROR; 605 int32_t localeIndex=0; 606 int32_t resultIndex=0; 607 UnicodeString resultDate; 608 UDate testDate= LocaleTest::date(99, 0, 13, 23, 58, 59) + 123.0; 609 while (localeIndex < MAX_LOCALE ) 610 { 611 int32_t dataIndex=0; 612 UnicodeString bestPattern; 613 614 Locale loc(testLocale[localeIndex][0], testLocale[localeIndex][1], testLocale[localeIndex][2], testLocale[localeIndex][3]); 615 logln("\n\n Locale: %s_%s_%s@%s", testLocale[localeIndex][0], testLocale[localeIndex][1], testLocale[localeIndex][2], testLocale[localeIndex][3]); 616 DateTimePatternGenerator *patGen=DateTimePatternGenerator::createInstance(loc, status); 617 if(U_FAILURE(status)) { 618 dataerrln("ERROR: Could not create DateTimePatternGenerator with locale index:%d . - exitting\n", localeIndex); 619 return; 620 } 621 while (patternData[dataIndex].length() > 0) { 622 log(patternData[dataIndex]); 623 bestPattern = patGen->getBestPattern(patternData[dataIndex++], status); 624 logln(UnicodeString(" -> ") + bestPattern); 625 626 SimpleDateFormat sdf(bestPattern, loc, status); 627 resultDate.remove(); 628 resultDate = sdf.format(testDate, resultDate); 629 if ( resultDate != patternResults[resultIndex] ) { 630 errln(UnicodeString("\nERROR: Test various skeletons[") + (dataIndex-1) + UnicodeString("], localeIndex ") + localeIndex + 631 UnicodeString(". Got: \"") + resultDate + UnicodeString("\" Expected: \"") + patternResults[resultIndex] + "\"" ); 632 } 633 634 resultIndex++; 635 } 636 delete patGen; 637 localeIndex++; 638 } 639 640 // ======= More tests ticket#6110 641 logln("Testing DateTimePatternGenerator with various skeleton"); 642 643 status = U_ZERO_ERROR; 644 localeIndex=0; 645 resultIndex=0; 646 testDate= LocaleTest::date(99, 9, 13, 23, 58, 59); 647 { 648 int32_t dataIndex=0; 649 UnicodeString bestPattern; 650 logln("\n\n Test various skeletons for English locale..."); 651 DateTimePatternGenerator *patGen=DateTimePatternGenerator::createInstance(Locale::getEnglish(), status); 652 if(U_FAILURE(status)) { 653 dataerrln("ERROR: Could not create DateTimePatternGenerator with locale English . - exitting\n"); 654 return; 655 } 656 TimeZone *enZone = TimeZone::createTimeZone(UnicodeString("ECT/GMT")); 657 if (enZone==NULL) { 658 dataerrln("ERROR: Could not create TimeZone ECT"); 659 delete patGen; 660 return; 661 } 662 SimpleDateFormat *enFormat = (SimpleDateFormat *)DateFormat::createDateTimeInstance(DateFormat::kFull, 663 DateFormat::kFull, Locale::getEnglish()); 664 enFormat->setTimeZone(*enZone); 665 while (patternTests2[dataIndex].length() > 0) { 666 logln(patternTests2[dataIndex]); 667 bestPattern = patGen->getBestPattern(patternTests2[dataIndex], status); 668 logln(UnicodeString(" -> ") + bestPattern); 669 enFormat->applyPattern(bestPattern); 670 resultDate.remove(); 671 resultDate = enFormat->format(testDate, resultDate); 672 if ( resultDate != patternResults2[resultIndex] ) { 673 errln(UnicodeString("\nERROR: Test various skeletons[") + dataIndex 674 + UnicodeString("]. Got: ") + resultDate + UnicodeString(" Expected: ") + 675 patternResults2[resultIndex] ); 676 } 677 dataIndex++; 678 resultIndex++; 679 } 680 delete patGen; 681 delete enZone; 682 delete enFormat; 683 } 684 685 686 687 // ======= Test random skeleton 688 DateTimePatternGenerator *randDTGen= DateTimePatternGenerator::createInstance(status); 689 if (U_FAILURE(status)) { 690 dataerrln("ERROR: Could not create DateTimePatternGenerator (Locale::getFrench()) - exitting"); 691 return; 692 } 693 UChar newChar; 694 int32_t i; 695 for (i=0; i<10; ++i) { 696 UnicodeString randomSkeleton; 697 int32_t len = rand() % 20; 698 for (int32_t j=0; j<len; ++j ) { 699 while ((newChar = (UChar)(rand()%0x7f))>=(UChar)0x20) { 700 randomSkeleton += newChar; 701 } 702 } 703 UnicodeString bestPattern = randDTGen->getBestPattern(randomSkeleton, status); 704 } 705 delete randDTGen; 706 707 // UnicodeString randomString=Unicode 708 // ======= Test getStaticClassID() 709 710 logln("Testing getStaticClassID()"); 711 status = U_ZERO_ERROR; 712 DateTimePatternGenerator *test= DateTimePatternGenerator::createInstance(status); 713 714 if(test->getDynamicClassID() != DateTimePatternGenerator::getStaticClassID()) { 715 errln("ERROR: getDynamicClassID() didn't return the expected value"); 716 } 717 delete test; 718 719 // ====== Test createEmptyInstance() 720 721 logln("Testing createEmptyInstance()"); 722 status = U_ZERO_ERROR; 723 724 test = DateTimePatternGenerator::createEmptyInstance(status); 725 if(U_FAILURE(status)) { 726 errln("ERROR: Fail to create an empty instance ! - exitting.\n"); 727 delete test; 728 return; 729 } 730 731 conflictingStatus = test->addPattern(UnicodeString("MMMMd"), true, conflictingPattern, status); 732 status = U_ZERO_ERROR; 733 testPattern=test->getBestPattern(UnicodeString("MMMMdd"), status); 734 conflictingStatus = test->addPattern(UnicodeString("HH:mm"), true, conflictingPattern, status); 735 conflictingStatus = test->addPattern(UnicodeString("MMMMMdd"), true, conflictingPattern, status); //duplicate pattern 736 StringEnumeration *output=NULL; 737 output = test->getRedundants(status); 738 expectedResult=UnicodeString("MMMMd"); 739 if (output != NULL) { 740 output->reset(status); 741 const UnicodeString *dupPattern=output->snext(status); 742 if ( (dupPattern==NULL) || (*dupPattern != expectedResult) ) { 743 errln("ERROR: Fail in getRedundants !\n"); 744 } 745 } 746 747 // ======== Test getSkeletons and getBaseSkeletons 748 StringEnumeration* ptrSkeletonEnum = test->getSkeletons(status); 749 if(U_FAILURE(status)) { 750 errln("ERROR: Fail to get skeletons !\n"); 751 } 752 UnicodeString returnPattern, *ptrSkeleton; 753 ptrSkeletonEnum->reset(status); 754 int32_t count=ptrSkeletonEnum->count(status); 755 for (i=0; i<count; ++i) { 756 ptrSkeleton = (UnicodeString *)ptrSkeletonEnum->snext(status); 757 returnPattern = test->getPatternForSkeleton(*ptrSkeleton); 758 if ( returnPattern != testSkeletonsResults[i] ) { 759 errln(UnicodeString("ERROR: Unexpected result from getSkeletons and getPatternForSkeleton\nGot: ") + returnPattern 760 + UnicodeString("\nExpected: ") + testSkeletonsResults[i] 761 + UnicodeString("\n")); 762 } 763 } 764 StringEnumeration* ptrBaseSkeletonEnum = test->getBaseSkeletons(status); 765 if(U_FAILURE(status)) { 766 errln("ERROR: Fail to get base skeletons !\n"); 767 } 768 count=ptrBaseSkeletonEnum->count(status); 769 for (i=0; i<count; ++i) { 770 ptrSkeleton = (UnicodeString *)ptrBaseSkeletonEnum->snext(status); 771 if ( *ptrSkeleton != testBaseSkeletonsResults[i] ) { 772 errln("ERROR: Unexpected result from getBaseSkeletons() !\n"); 773 } 774 } 775 776 // ========= DateTimePatternGenerator sample code in Userguide 777 // set up the generator 778 Locale locale = Locale::getFrench(); 779 status = U_ZERO_ERROR; 780 DateTimePatternGenerator *generator = DateTimePatternGenerator::createInstance( locale, status); 781 782 // get a pattern for an abbreviated month and day 783 pattern = generator->getBestPattern(UnicodeString("MMMd"), status); 784 SimpleDateFormat formatter(pattern, locale, status); 785 786 zone = TimeZone::createTimeZone(UnicodeString("GMT")); 787 formatter.setTimeZone(*zone); 788 // use it to format (or parse) 789 UnicodeString formatted; 790 formatted = formatter.format(Calendar::getNow(), formatted, status); 791 // for French, the result is "13 sept." 792 formatted.remove(); 793 // cannot use the result from getNow() because the value change evreyday. 794 testDate= LocaleTest::date(99, 0, 13, 23, 58, 59); 795 formatted = formatter.format(testDate, formatted, status); 796 expectedResult=UnicodeString("14 janv."); 797 if ( formatted != expectedResult ) { 798 errln("ERROR: Userguide sample code result!"); 799 errln(UnicodeString(" Got: ")+ formatted + UnicodeString(" Expected: ") + expectedResult); 800 } 801 802 delete zone; 803 delete output; 804 delete ptrSkeletonEnum; 805 delete ptrBaseSkeletonEnum; 806 delete test; 807 delete generator; 808 } 809 810 /** 811 * Test handling of options 812 * 813 * For reference, as of ICU 4.3.3, 814 * root/gregorian has 815 * Hm{"H:mm"} 816 * Hms{"H:mm:ss"} 817 * hm{"h:mm a"} 818 * hms{"h:mm:ss a"} 819 * en/gregorian has 820 * Hm{"H:mm"} 821 * Hms{"H:mm:ss"} 822 * hm{"h:mm a"} 823 * be/gregorian has 824 * HHmmss{"HH.mm.ss"} 825 * Hm{"HH.mm"} 826 * hm{"h.mm a"} 827 * hms{"h.mm.ss a"} 828 */ 829 typedef struct DTPtnGenOptionsData { 830 const char *locale; 831 const char *skel; 832 const char *expectedPattern; 833 UDateTimePatternMatchOptions options; 834 } DTPtnGenOptionsData; 835 void IntlTestDateTimePatternGeneratorAPI::testOptions(/*char *par*/) 836 { 837 DTPtnGenOptionsData testData[] = { 838 // locale skel expectedPattern options 839 { "en", "Hmm", "HH:mm", UDATPG_MATCH_NO_OPTIONS }, 840 { "en", "HHmm", "HH:mm", UDATPG_MATCH_NO_OPTIONS }, 841 { "en", "hhmm", "h:mm a", UDATPG_MATCH_NO_OPTIONS }, 842 { "en", "Hmm", "HH:mm", UDATPG_MATCH_HOUR_FIELD_LENGTH }, 843 { "en", "HHmm", "HH:mm", UDATPG_MATCH_HOUR_FIELD_LENGTH }, 844 { "en", "hhmm", "hh:mm a", UDATPG_MATCH_HOUR_FIELD_LENGTH }, 845 { "be", "Hmm", "HH.mm", UDATPG_MATCH_NO_OPTIONS }, 846 { "be", "HHmm", "HH.mm", UDATPG_MATCH_NO_OPTIONS }, 847 { "be", "hhmm", "h.mm a", UDATPG_MATCH_NO_OPTIONS }, 848 { "be", "Hmm", "H.mm", UDATPG_MATCH_HOUR_FIELD_LENGTH }, 849 { "be", "HHmm", "HH.mm", UDATPG_MATCH_HOUR_FIELD_LENGTH }, 850 { "be", "hhmm", "hh.mm a", UDATPG_MATCH_HOUR_FIELD_LENGTH }, 851 }; 852 853 int count = sizeof(testData) / sizeof(testData[0]); 854 const DTPtnGenOptionsData * testDataPtr = testData; 855 856 for (; count-- > 0; ++testDataPtr) { 857 UErrorCode status = U_ZERO_ERROR; 858 859 Locale locale(testDataPtr->locale); 860 UnicodeString skel(testDataPtr->skel); 861 UnicodeString expectedPattern(testDataPtr->expectedPattern); 862 UDateTimePatternMatchOptions options = testDataPtr->options; 863 864 DateTimePatternGenerator * dtpgen = DateTimePatternGenerator::createInstance(locale, status); 865 if (U_FAILURE(status)) { 866 dataerrln("Unable to create DateTimePatternGenerator instance for locale(%s): %s", locale.getName(), u_errorName(status)); 867 delete dtpgen; 868 continue; 869 } 870 UnicodeString pattern = dtpgen->getBestPattern(skel, options, status); 871 if (pattern.compare(expectedPattern) != 0) { 872 errln( UnicodeString("ERROR in getBestPattern, locale ") + UnicodeString(testDataPtr->locale) + 873 UnicodeString(", skeleton ") + skel + 874 ((options)?UnicodeString(", options!=0"):UnicodeString(", options==0")) + 875 UnicodeString(", expected pattern ") + expectedPattern + 876 UnicodeString(", got ") + pattern ); 877 } 878 delete dtpgen; 879 } 880 } 881 882 #endif /* #if !UCONFIG_NO_FORMATTING */ 883