1// © 2016 and later: Unicode, Inc. and others. 2// License & terms of use: http://www.unicode.org/copyright.html#License 3/* 4 ******************************************************************************* 5 * Copyright (C) 2006-2016, Google, International Business Machines Corporation 6 * and others. All Rights Reserved. 7 ******************************************************************************* 8 */ 9 10package com.ibm.icu.dev.test.format; 11 12import java.text.ParsePosition; 13import java.util.Collection; 14import java.util.Date; 15import java.util.HashSet; 16import java.util.Iterator; 17import java.util.LinkedHashMap; 18import java.util.LinkedHashSet; 19import java.util.List; 20import java.util.Locale; 21import java.util.Map; 22import java.util.Random; 23import java.util.Set; 24 25import org.junit.Test; 26 27import com.ibm.icu.dev.test.TestFmwk; 28import com.ibm.icu.impl.PatternTokenizer; 29import com.ibm.icu.impl.Utility; 30import com.ibm.icu.text.DateFormat; 31import com.ibm.icu.text.DateTimePatternGenerator; 32import com.ibm.icu.text.DateTimePatternGenerator.FormatParser; 33import com.ibm.icu.text.DateTimePatternGenerator.VariableField; 34import com.ibm.icu.text.SimpleDateFormat; 35import com.ibm.icu.text.UTF16; 36import com.ibm.icu.text.UnicodeSet; 37import com.ibm.icu.util.Calendar; 38import com.ibm.icu.util.GregorianCalendar; 39import com.ibm.icu.util.SimpleTimeZone; 40import com.ibm.icu.util.TimeZone; 41import com.ibm.icu.util.ULocale; 42 43public class DateTimeGeneratorTest extends TestFmwk { 44 public static boolean GENERATE_TEST_DATA; 45 static { 46 try { 47 GENERATE_TEST_DATA = System.getProperty("GENERATE_TEST_DATA") != null; 48 } catch (SecurityException e) { 49 GENERATE_TEST_DATA = false; 50 } 51 }; 52 public static int RANDOM_COUNT = 1000; 53 public static boolean DEBUG = false; 54 55 @Test 56 public void TestC() { 57 String[][] tests = { 58 {"zh", "Cm", "Bh:mm"}, 59 {"de", "Cm", "HH:mm"}, 60 {"en", "Cm", "h:mm a"}, 61 {"en-BN", "Cm", "h:mm b"}, 62 {"gu-IN", "Cm", "h:mm B"}, 63 {"und-IN", "Cm", "h:mm a"}, 64 }; 65 for (String[] test : tests) { 66 DateTimePatternGenerator gen = DateTimePatternGenerator.getInstance(ULocale.forLanguageTag(test[0])); 67 String skeleton = test[1]; 68 String pattern = gen.getBestPattern(skeleton); 69 assertEquals(test[0] + "/" + skeleton, test[2], pattern); 70 } 71 } 72 73 @Test 74 public void TestSimple() { 75 // some simple use cases 76 ULocale locale = ULocale.GERMANY; 77 TimeZone zone = TimeZone.getTimeZone("Europe/Paris"); 78 79 // make from locale 80 DateTimePatternGenerator gen = DateTimePatternGenerator.getInstance(locale); 81 SimpleDateFormat format = new SimpleDateFormat(gen.getBestPattern("MMMddHmm"), locale); 82 format.setTimeZone(zone); 83 assertEquals("simple format: MMMddHmm", "14. Okt., 08:58", format.format(sampleDate)); 84 // (a generator can be built from scratch, but that is not a typical use case) 85 86 // modify the generator by adding patterns 87 DateTimePatternGenerator.PatternInfo returnInfo = new DateTimePatternGenerator.PatternInfo(); 88 gen.addPattern("d'. von' MMMM", true, returnInfo); 89 // the returnInfo is mostly useful for debugging problem cases 90 format.applyPattern(gen.getBestPattern("MMMMdHmm")); 91 assertEquals("modified format: MMMdHmm", "14. von Oktober, 08:58", format.format(sampleDate)); 92 93 // get a pattern and modify it 94 format = (SimpleDateFormat)DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, locale); 95 format.setTimeZone(zone); 96 String pattern = format.toPattern(); 97 assertEquals("full-date", "Donnerstag, 14. Oktober 1999 um 08:58:59 Mitteleurop\u00E4ische Sommerzeit", format.format(sampleDate)); 98 99 // modify it to change the zone. 100 String newPattern = gen.replaceFieldTypes(pattern, "vvvv"); 101 format.applyPattern(newPattern); 102 assertEquals("full-date: modified zone", "Donnerstag, 14. Oktober 1999 um 08:58:59 Mitteleurop\u00E4ische Zeit", format.format(sampleDate)); 103 104 // add test of basic cases 105 106 //lang YYYYMMM MMMd MMMdhmm hmm hhmm Full Date-Time 107 // en Mar 2007 Mar 4 6:05 PM Mar 4 6:05 PM 06:05 PM Sunday, March 4, 2007 6:05:05 PM PT 108 DateTimePatternGenerator enGen = DateTimePatternGenerator.getInstance(ULocale.ENGLISH); 109 TimeZone enZone = TimeZone.getTimeZone("Etc/GMT"); 110 SimpleDateFormat enFormat = (SimpleDateFormat)DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.FULL, ULocale.ENGLISH); 111 enFormat.setTimeZone(enZone); 112 String[][] tests = { 113 {"yyyyMMMdd", "Oct 14, 1999"}, 114 {"yyyyqqqq", "4th quarter 1999"}, 115 {"yMMMdd", "Oct 14, 1999"}, 116 {"EyyyyMMMdd", "Thu, Oct 14, 1999"}, 117 {"yyyyMMdd", "10/14/1999"}, 118 {"yyyyMMM", "Oct 1999"}, 119 {"yyyyMM", "10/1999"}, 120 {"yyMM", "10/99"}, 121 {"yMMMMMd", "O 14, 1999"}, // narrow format 122 {"EEEEEMMMMMd", "T, O 14"}, // narrow format 123 {"MMMd", "Oct 14"}, 124 {"MMMdhmm", "Oct 14, 6:58 AM"}, 125 {"EMMMdhmms", "Thu, Oct 14, 6:58:59 AM"}, 126 {"MMdhmm", "10/14, 6:58 AM"}, 127 {"EEEEMMMdhmms", "Thursday, Oct 14, 6:58:59 AM"}, 128 {"yyyyMMMddhhmmss", "Oct 14, 1999, 6:58:59 AM"}, // (fixed expected result per ticket 6872<-7180) 129 {"EyyyyMMMddhhmmss", "Thu, Oct 14, 1999, 6:58:59 AM"}, // (fixed expected result per ticket 6872<-7180) 130 {"hmm", "6:58 AM"}, 131 {"hhmm", "6:58 AM"}, // (fixed expected result per ticket 6872<-7180) 132 {"hhmmVVVV", "6:58 AM GMT"}, // (fixed expected result per ticket 6872<-7180) 133 }; 134 for (int i = 0; i < tests.length; ++i) { 135 final String testSkeleton = tests[i][0]; 136 String pat = enGen.getBestPattern(testSkeleton); 137 enFormat.applyPattern(pat); 138 String formattedDate = enFormat.format(sampleDate); 139 assertEquals("Testing skeleton '" + testSkeleton + "' with " + sampleDate, tests[i][1], formattedDate); 140 } 141 } 142 143 @Test 144 public void TestRoot() { 145 DateTimePatternGenerator rootGen = DateTimePatternGenerator.getInstance(ULocale.ROOT); 146 SimpleDateFormat rootFormat = new SimpleDateFormat(rootGen.getBestPattern("yMdHms"), ULocale.ROOT); 147 rootFormat.setTimeZone(gmt); 148 // *** expected result should be "1999-10-14 6:58:59" with current data, changed test temporarily to match current result, needs investigation 149 assertEquals("root format: yMdHms", "1999-10-14 06:58:59", rootFormat.format(sampleDate)); 150 } 151 152 @Test 153 public void TestEmpty() { 154 // now nothing 155 DateTimePatternGenerator nullGen = DateTimePatternGenerator.getEmptyInstance(); 156 SimpleDateFormat format = new SimpleDateFormat(nullGen.getBestPattern("yMdHms"), ULocale.ROOT); 157 TimeZone rootZone = TimeZone.getTimeZone("Etc/GMT"); 158 format.setTimeZone(rootZone); 159 } 160 161 @Test 162 public void TestPatternParser() { 163 StringBuffer buffer = new StringBuffer(); 164 PatternTokenizer pp = new PatternTokenizer() 165 .setIgnorableCharacters(new UnicodeSet("[-]")) 166 .setSyntaxCharacters(new UnicodeSet("[a-zA-Z]")) 167 .setEscapeCharacters(new UnicodeSet("[b#]")) 168 .setUsingQuote(true); 169 logln("Using Quote"); 170 for (int i = 0; i < patternTestData.length; ++i) { 171 String patternTest = (String) patternTestData[i]; 172 CheckPattern(buffer, pp, patternTest); 173 } 174 String[] randomSet = {"abcdef", "$12!@#-", "'\\"}; 175 for (int i = 0; i < RANDOM_COUNT; ++i) { 176 String patternTest = getRandomString(randomSet, 0, 10); 177 CheckPattern(buffer, pp, patternTest); 178 } 179 logln("Using Backslash"); 180 pp.setUsingQuote(false).setUsingSlash(true); 181 for (int i = 0; i < patternTestData.length; ++i) { 182 String patternTest = (String) patternTestData[i]; 183 CheckPattern(buffer, pp, patternTest); 184 } 185 for (int i = 0; i < RANDOM_COUNT; ++i) { 186 String patternTest = getRandomString(randomSet, 0, 10); 187 CheckPattern(buffer, pp, patternTest); 188 } 189 } 190 191 Random random = new java.util.Random(-1); 192 193 private String getRandomString(String[] randomList, int minLen, int maxLen) { 194 StringBuffer result = new StringBuffer(); 195 int len = random.nextInt(maxLen + 1 - minLen) + minLen; 196 for (int i = minLen; i < len; ++ i) { 197 String source = randomList[random.nextInt(randomList.length)]; // don't bother with surrogates 198 char ch = source.charAt(random.nextInt(source.length())); 199 UTF16.append(result, ch); 200 } 201 return result.toString(); 202 } 203 204 private void CheckPattern(StringBuffer buffer, PatternTokenizer pp, String patternTest) { 205 pp.setPattern(patternTest); 206 if (DEBUG && isVerbose()) { 207 showItems(buffer, pp, patternTest); 208 } 209 String normalized = pp.setStart(0).normalize(); 210 logln("input:\t<" + patternTest + ">" + "\tnormalized:\t<" + normalized + ">"); 211 String doubleNormalized = pp.setPattern(normalized).normalize(); 212 if (!normalized.equals(doubleNormalized)) { 213 errln("Normalization not idempotent:\t" + patternTest + "\tnormalized: " + normalized + "\tnormalized2: " + doubleNormalized); 214 // allow for debugging at the point of failure 215 if (DEBUG) { 216 pp.setPattern(patternTest); 217 normalized = pp.setStart(0).normalize(); 218 pp.setPattern(normalized); 219 showItems(buffer, pp, normalized); 220 doubleNormalized = pp.normalize(); 221 } 222 } 223 } 224 225 private void showItems(StringBuffer buffer, PatternTokenizer pp, String patternTest) { 226 logln("input:\t<" + patternTest + ">"); 227 while (true) { 228 buffer.setLength(0); 229 int status = pp.next(buffer); 230 if (status == PatternTokenizer.DONE) break; 231 String lit = ""; 232 if (status != PatternTokenizer.SYNTAX ) { 233 lit = "\t<" + pp.quoteLiteral(buffer) + ">"; 234 } 235 logln("\t" + statusName[status] + "\t<" + buffer + ">" + lit); 236 } 237 } 238 239 static final String[] statusName = {"DONE", "SYNTAX", "LITERAL", "BROKEN_QUOTE", "BROKEN_ESCAPE", "UNKNOWN"}; 240 241 @Test 242 public void TestBasic() { 243 ULocale uLocale = null; 244 DateTimePatternGenerator dtfg = null; 245 Date date = null; 246 for (int i = 0; i < dateTestData.length; ++i) { 247 if (dateTestData[i] instanceof ULocale) { 248 uLocale = (ULocale) dateTestData[i]; 249 dtfg = DateTimePatternGenerator.getInstance(uLocale); 250 if (GENERATE_TEST_DATA) logln("new ULocale(\"" + uLocale.toString() + "\"),"); 251 } else if (dateTestData[i] instanceof Date) { 252 date = (Date) dateTestData[i]; 253 if (GENERATE_TEST_DATA) logln("new Date(" + date.getTime()+ "L),"); 254 } else if (dateTestData[i] instanceof String) { 255 String testSkeleton = (String) dateTestData[i]; 256 String pattern = dtfg.getBestPattern(testSkeleton); 257 SimpleDateFormat sdf = new SimpleDateFormat(pattern, uLocale); 258 String formatted = sdf.format(date); 259 if (GENERATE_TEST_DATA) logln("new String[] {\"" + testSkeleton + "\", \"" + Utility.escape(formatted) + "\"},"); 260 //logln(uLocale + "\t" + testSkeleton + "\t" + pattern + "\t" + sdf.format(date)); 261 } else { 262 String[] testPair = (String[]) dateTestData[i]; 263 String testSkeleton = testPair[0]; 264 String testFormatted = testPair[1]; 265 String pattern = dtfg.getBestPattern(testSkeleton); 266 SimpleDateFormat sdf = new SimpleDateFormat(pattern, uLocale); 267 String formatted = sdf.format(date); 268 if (GENERATE_TEST_DATA) { 269 logln("new String[] {\"" + testSkeleton + "\", \"" + Utility.escape(formatted) + "\"},"); 270 } else if (!formatted.equals(testFormatted)) { 271 errln(uLocale + "\tformatted string doesn't match test case: " + testSkeleton + "\t generated: " + pattern + "\t expected: " + testFormatted + "\t got: " + formatted); 272 if (true) { // debug 273 pattern = dtfg.getBestPattern(testSkeleton); 274 sdf = new SimpleDateFormat(pattern, uLocale); 275 formatted = sdf.format(date); 276 } 277 } 278 //logln(uLocale + "\t" + testSkeleton + "\t" + pattern + "\t" + sdf.format(date)); 279 } 280 } 281 } 282 283 static final Object[] patternTestData = { 284 "'$f''#c", 285 "'' 'a", 286 "'.''.'", 287 "\\u0061\\\\", 288 "mm.dd 'dd ' x", 289 "'' ''", 290 }; 291 292 // can be generated by using GENERATE_TEST_DATA. Must be reviewed before adding 293 static final Object[] dateTestData = { 294 new Date(916300739123L), // 1999-01-13T23:58:59.123,0-0800 295 296 new ULocale("en_US"), 297 new String[] {"yM", "1/1999"}, 298 new String[] {"yMMM", "Jan 1999"}, 299 new String[] {"yMd", "1/13/1999"}, 300 new String[] {"yMMMd", "Jan 13, 1999"}, 301 new String[] {"Md", "1/13"}, 302 new String[] {"MMMd", "Jan 13"}, 303 new String[] {"MMMMd", "January 13"}, 304 new String[] {"yQQQ", "Q1 1999"}, 305 new String[] {"hhmm", "11:58 PM"}, 306 new String[] {"HHmm", "23:58"}, 307 new String[] {"jjmm", "11:58 PM"}, 308 new String[] {"mmss", "58:59"}, 309 new String[] {"yyyyMMMM", "January 1999"}, // (new item for testing 6872<-5702) 310 new String[] {"MMMEd", "Wed, Jan 13"}, 311 new String[] {"Ed", "13 Wed"}, 312 new String[] {"jmmssSSS", "11:58:59.123 PM"}, 313 new String[] {"JJmm", "11:58"}, 314 315 new ULocale("en_US@calendar=japanese"), // (new locale for testing ticket 6872<-5702) 316 new String[] {"yM", "1/11 H"}, 317 new String[] {"yMMM", "Jan 11 Heisei"}, 318 new String[] {"yMd", "1/13/11 H"}, 319 new String[] {"yMMMd", "Jan 13, 11 Heisei"}, 320 new String[] {"Md", "1/13"}, 321 new String[] {"MMMd", "Jan 13"}, 322 new String[] {"MMMMd", "January 13"}, 323 new String[] {"yQQQ", "Q1 11 Heisei"}, 324 new String[] {"hhmm", "11:58 PM"}, 325 new String[] {"HHmm", "23:58"}, 326 new String[] {"jjmm", "11:58 PM"}, 327 new String[] {"mmss", "58:59"}, 328 new String[] {"yyyyMMMM", "January 11 Heisei"}, 329 new String[] {"MMMEd", "Wed, Jan 13"}, 330 new String[] {"Ed", "13 Wed"}, 331 new String[] {"jmmssSSS", "11:58:59.123 PM"}, 332 new String[] {"JJmm", "11:58"}, 333 334 new ULocale("de_DE"), 335 new String[] {"yM", "1.1999"}, 336 new String[] {"yMMM", "Jan. 1999"}, 337 new String[] {"yMd", "13.1.1999"}, 338 new String[] {"yMMMd", "13. Jan. 1999"}, 339 new String[] {"Md", "13.1."}, // 13.1 340 new String[] {"MMMd", "13. Jan."}, 341 new String[] {"MMMMd", "13. Januar"}, 342 new String[] {"yQQQ", "Q1 1999"}, 343 new String[] {"hhmm", "11:58 nachm."}, 344 new String[] {"HHmm", "23:58"}, 345 new String[] {"jjmm", "23:58"}, 346 new String[] {"mmss", "58:59"}, 347 new String[] {"yyyyMMMM", "Januar 1999"}, // (new item for testing 6872<-5702) 348 new String[] {"MMMEd", "Mi., 13. Jan."}, 349 new String[] {"Ed", "Mi., 13."}, 350 new String[] {"jmmssSSS", "23:58:59,123"}, 351 new String[] {"JJmm", "23:58"}, 352 353 new ULocale("fi"), 354 new String[] {"yM", "1.1999"}, // (fixed expected result per ticket 6872<-6626) 355 new String[] {"yMMM", "tammi 1999"}, // (fixed expected result per ticket 6872<-7007) 356 new String[] {"yMd", "13.1.1999"}, 357 new String[] {"yMMMd", "13. tammik. 1999"}, 358 new String[] {"Md", "13.1."}, 359 new String[] {"MMMd", "13. tammik."}, 360 new String[] {"MMMMd", "13. tammikuuta"}, 361 new String[] {"yQQQ", "1. nelj. 1999"}, 362 new String[] {"hhmm", "11.58 ip."}, 363 new String[] {"HHmm", "23.58"}, 364 new String[] {"jjmm", "23.58"}, 365 new String[] {"mmss", "58.59"}, 366 new String[] {"yyyyMMMM", "tammikuu 1999"}, // (new item for testing 6872<-5702,7007) 367 new String[] {"MMMEd", "ke 13. tammik."}, 368 new String[] {"Ed", "ke 13."}, 369 new String[] {"jmmssSSS", "23.58.59,123"}, 370 new String[] {"JJmm", "23.58"}, 371 372 new ULocale("es"), 373 new String[] {"yM", "1/1999"}, 374 new String[] {"yMMM", "ene. 1999"}, 375 new String[] {"yMd", "13/1/1999"}, 376 new String[] {"yMMMd", "13 ene. 1999"}, 377 new String[] {"Md", "13/1"}, 378 new String[] {"MMMd", "13 ene."}, 379 new String[] {"MMMMd", "13 de enero"}, 380 new String[] {"yQQQ", "T1 1999"}, 381 new String[] {"hhmm", "11:58 p. m."}, 382 new String[] {"HHmm", "23:58"}, 383 new String[] {"jjmm", "23:58"}, 384 new String[] {"mmss", "58:59"}, 385 new String[] {"yyyyMMMM", "enero de 1999"}, 386 new String[] {"MMMEd", "mi\u00E9., 13 ene."}, 387 new String[] {"Ed", "mi\u00E9. 13"}, 388 new String[] {"jmmssSSS", "23:58:59,123"}, 389 new String[] {"JJmm", "23:58"}, 390 391 new ULocale("ja"), // (new locale for testing ticket 6872<-6626) 392 new String[] {"yM", "1999/1"}, 393 new String[] {"yMMM", "1999\u5E741\u6708"}, 394 new String[] {"yMd", "1999/1/13"}, 395 new String[] {"yMMMd", "1999\u5E741\u670813\u65E5"}, 396 new String[] {"Md", "1/13"}, 397 new String[] {"MMMd", "1\u670813\u65E5"}, 398 new String[] {"MMMMd", "1\u670813\u65E5"}, 399 new String[] {"yQQQ", "1999/Q1"}, 400 new String[] {"hhmm", "\u5348\u5F8C11:58"}, 401 new String[] {"HHmm", "23:58"}, 402 new String[] {"jjmm", "23:58"}, 403 new String[] {"mmss", "58:59"}, 404 new String[] {"yyyyMMMM", "1999\u5E741\u6708"}, // (new item for testing 6872<-5702) 405 new String[] {"MMMEd", "1\u670813\u65E5(\u6C34)"}, 406 new String[] {"Ed", "13\u65E5(\u6C34)"}, 407 new String[] {"jmmssSSS", "23:58:59.123"}, 408 new String[] {"JJmm", "23:58"}, 409 410 new ULocale("ja@calendar=japanese"), // (new locale for testing ticket 6872<-5702) 411 new String[] {"yM", "\u5E73\u621011/1"}, 412 new String[] {"yMMM", "\u5E73\u621011\u5E741\u6708"}, 413 new String[] {"yMd", "\u5E73\u621011/1/13"}, 414 new String[] {"yMMMd", "\u5E73\u621011\u5E741\u670813\u65E5"}, 415 new String[] {"Md", "1/13"}, 416 new String[] {"MMMd", "1\u670813\u65E5"}, 417 new String[] {"MMMMd", "1\u670813\u65E5"}, 418 new String[] {"yQQQ", "\u5E73\u621011/Q1"}, 419 new String[] {"hhmm", "\u5348\u5F8C11:58"}, 420 new String[] {"HHmm", "23:58"}, 421 new String[] {"jjmm", "23:58"}, 422 new String[] {"mmss", "58:59"}, 423 new String[] {"yyyyMMMM", "\u5E73\u621011\u5E741\u6708"}, 424 new String[] {"MMMEd", "1\u670813\u65E5(\u6C34)"}, 425 new String[] {"Ed", "13\u65E5(\u6C34)"}, 426 new String[] {"jmmssSSS", "23:58:59.123"}, 427 new String[] {"JJmm", "23:58"}, 428 429 new ULocale("zh_Hans_CN"), 430 new String[] {"yM", "1999\u5E741\u6708"}, 431 new String[] {"yMMM", "1999\u5E741\u6708"}, // (fixed expected result per ticket 6872<-6626) 432 new String[] {"yMd", "1999/1/13"}, 433 new String[] {"yMMMd", "1999\u5E741\u670813\u65E5"}, // (fixed expected result per ticket 6872<-6626) 434 new String[] {"Md", "1/13"}, 435 new String[] {"MMMd", "1\u670813\u65E5"}, // (fixed expected result per ticket 6872<-6626) 436 new String[] {"MMMMd", "1\u670813\u65E5"}, 437 new String[] {"yQQQ", "1999\u5E74\u7B2C1\u5B63\u5EA6"}, 438 new String[] {"hhmm", "\u4E0B\u534811:58"}, 439 new String[] {"HHmm", "23:58"}, 440 new String[] {"jjmm", "\u4E0B\u534811:58"}, 441 new String[] {"mmss", "58:59"}, 442 new String[] {"yyyyMMMM", "1999\u5E741\u6708"}, // (new item for testing 6872<-5702) 443 new String[] {"MMMEd", "1\u670813\u65E5\u5468\u4E09"}, 444 new String[] {"Ed", "13\u65E5\u5468\u4E09"}, 445 new String[] {"jmmssSSS", "\u4E0B\u534811:58:59.123"}, 446 new String[] {"JJmm", "11:58"}, 447 448 new ULocale("zh_TW@calendar=roc"), // (new locale for testing ticket 6872<-5702) 449 new String[] {"yM", "\u6C11\u570B88/1"}, 450 new String[] {"yMMM", "\u6C11\u570B88\u5E741\u6708"}, 451 new String[] {"yMd", "\u6C11\u570B88/1/13"}, 452 new String[] {"yMMMd", "\u6C11\u570B88\u5E741\u670813\u65E5"}, 453 new String[] {"Md", "1/13"}, 454 new String[] {"MMMd", "1\u670813\u65E5"}, 455 new String[] {"MMMMd", "1\u670813\u65E5"}, 456 new String[] {"yQQQ", "\u6C11\u570B88\u5E741\u5B63"}, 457 new String[] {"hhmm", "\u4E0B\u534811:58"}, 458 new String[] {"HHmm", "23:58"}, 459 new String[] {"jjmm", "\u4E0B\u534811:58"}, 460 new String[] {"mmss", "58:59"}, 461 new String[] {"yyyyMMMM", "\u6C11\u570B88\u5E741\u6708"}, 462 new String[] {"MMMEd", "1\u670813\u65E5\u9031\u4E09"}, 463 new String[] {"Ed", "13 \u9031\u4E09"}, 464 new String[] {"jmmssSSS", "\u4E0B\u534811:58:59.123"}, 465 new String[] {"JJmm", "11:58"}, 466 467 new ULocale("ru"), 468 new String[] {"yM", "01.1999"}, 469 new String[] {"yMMM", "\u044F\u043D\u0432. 1999 \u0433."}, 470 new String[] {"yMd", "13.01.1999"}, 471 new String[] {"yMMMd", "13 \u044F\u043D\u0432. 1999 \u0433."}, 472 new String[] {"Md", "13.01"}, 473 new String[] {"MMMd", "13 \u044F\u043D\u0432."}, 474 new String[] {"MMMMd", "13 \u044F\u043D\u0432\u0430\u0440\u044F"}, 475 new String[] {"yQQQ", "1-\u0439 \u043A\u0432. 1999 \u0433."}, 476 new String[] {"hhmm", "11:58 \u041F\u041F"}, 477 new String[] {"HHmm", "23:58"}, 478 new String[] {"jjmm", "23:58"}, 479 new String[] {"mmss", "58:59"}, 480 new String[] {"yyyyMMMM", "\u044F\u043D\u0432\u0430\u0440\u044C 1999 \u0433."}, 481 new String[] {"MMMEd", "\u0441\u0440, 13 \u044F\u043D\u0432."}, 482 new String[] {"Ed", "\u0441\u0440, 13"}, 483 new String[] {"jmmssSSS", "23:58:59,123"}, 484 new String[] {"JJmm", "23:58"}, 485 486 new ULocale("zh@calendar=chinese"), 487 new String[] {"yM", "1998\u620A\u5BC5\u5E74\u5341\u4E00\u6708"}, 488 new String[] {"yMMM", "1998\u620A\u5BC5\u5E74\u5341\u4E00\u6708"}, 489 new String[] {"yMd", "1998\u5E74\u5341\u4E00\u670826"}, 490 new String[] {"yMMMd", "1998\u5E74\u5341\u4E00\u670826"}, 491 new String[] {"Md", "11-26"}, 492 new String[] {"MMMd", "\u5341\u4E00\u670826\u65E5"}, 493 new String[] {"MMMMd", "\u5341\u4E00\u670826\u65E5"}, 494 new String[] {"yQQQ", "1998\u620A\u5BC5\u5E74\u7B2C\u56DB\u5B63\u5EA6"}, 495 new String[] {"hhmm", "\u4E0B\u534811:58"}, 496 new String[] {"HHmm", "23:58"}, 497 new String[] {"jjmm", "\u4E0B\u534811:58"}, 498 new String[] {"mmss", "58:59"}, 499 new String[] {"yyyyMMMM", "1998\u620A\u5BC5\u5E74\u5341\u4E00\u6708"}, 500 new String[] {"MMMEd", "\u5341\u4E00\u670826\u65E5\u5468\u4E09"}, 501 new String[] {"Ed", "26\u65E5\u5468\u4E09"}, 502 new String[] {"jmmssSSS", "\u4E0B\u534811:58:59.123"}, 503 new String[] {"JJmm", "11:58"}, 504 }; 505 506 @Test 507 public void DayMonthTest() { 508 final ULocale locale = ULocale.FRANCE; 509 510 // set up the generator 511 DateTimePatternGenerator dtpgen 512 = DateTimePatternGenerator.getInstance(locale); 513 514 // get a pattern for an abbreviated month and day 515 final String pattern = dtpgen.getBestPattern("MMMd"); 516 SimpleDateFormat formatter = new SimpleDateFormat(pattern, locale); 517 518 // use it to format (or parse) 519 String formatted = formatter.format(new Date()); 520 logln("formatted=" + formatted); 521 // for French, the result is "13 sept." 522 } 523 524 @Test 525 public void TestOrdering() { 526 ULocale[] locales = ULocale.getAvailableLocales(); 527 for (int i = 0; i < locales.length; ++i) { 528 for (int style1 = DateFormat.FULL; style1 <= DateFormat.SHORT; ++style1) { 529 for (int style2 = DateFormat.FULL; style2 < style1; ++style2) { 530 checkCompatible(style1, style2, locales[i]); 531 } 532 } 533 } 534 } 535 536 @Test 537 public void TestReplacingZoneString() { 538 Date testDate = new Date(); 539 TimeZone testTimeZone = TimeZone.getTimeZone("America/New_York"); 540 TimeZone bogusTimeZone = new SimpleTimeZone(1234, "Etc/Unknown"); 541 Calendar calendar = Calendar.getInstance(); 542 ParsePosition parsePosition = new ParsePosition(0); 543 544 ULocale[] locales = ULocale.getAvailableLocales(); 545 int count = 0; 546 for (int i = 0; i < locales.length; ++i) { 547 // skip the country locales unless we are doing exhaustive tests 548 if (getExhaustiveness() < 6) { 549 if (locales[i].getCountry().length() > 0) { 550 continue; 551 } 552 } 553 count++; 554 // Skipping some test case in the non-exhaustive mode to reduce the test time 555 //ticket#6503 556 if(getExhaustiveness()<=5 && count%3!=0){ 557 continue; 558 } 559 logln(locales[i].toString()); 560 DateTimePatternGenerator dtpgen 561 = DateTimePatternGenerator.getInstance(locales[i]); 562 563 for (int style1 = DateFormat.FULL; style1 <= DateFormat.SHORT; ++style1) { 564 final SimpleDateFormat oldFormat = (SimpleDateFormat) DateFormat.getTimeInstance(style1, locales[i]); 565 String pattern = oldFormat.toPattern(); 566 String newPattern = dtpgen.replaceFieldTypes(pattern, "VVVV"); // replaceZoneString(pattern, "VVVV"); 567 if (newPattern.equals(pattern)) { 568 continue; 569 } 570 // verify that it roundtrips parsing 571 SimpleDateFormat newFormat = new SimpleDateFormat(newPattern, locales[i]); 572 newFormat.setTimeZone(testTimeZone); 573 String formatted = newFormat.format(testDate); 574 calendar.setTimeZone(bogusTimeZone); 575 parsePosition.setIndex(0); 576 newFormat.parse(formatted, calendar, parsePosition); 577 if (parsePosition.getErrorIndex() >= 0) { 578 errln("Failed parse with VVVV:\t" + locales[i] + ",\t\"" + pattern + "\",\t\"" + newPattern + "\",\t\"" + formatted.substring(0,parsePosition.getErrorIndex()) + "{}" + formatted.substring(parsePosition.getErrorIndex()) + "\""); 579 } else if (!calendar.getTimeZone().getID().equals(testTimeZone.getID())) { 580 errln("Failed timezone roundtrip with VVVV:\t" + locales[i] + ",\t\"" + pattern + "\",\t\"" + newPattern + "\",\t\"" + formatted + "\",\t" + calendar.getTimeZone().getID() + " != " + testTimeZone.getID()); 581 } else { 582 logln(locales[i] + ":\t\"" + pattern + "\" => \t\"" + newPattern + "\"\t" + formatted); 583 } 584 } 585 } 586 } 587 588 @Test 589 public void TestVariableCharacters() { 590 UnicodeSet valid = new UnicodeSet("[G y Y u U r Q q M L l w W d D F g E e c a h H K k m s S A z Z O v V X x]"); 591 for (char c = 0; c < 0xFF; ++c) { 592 boolean works = false; 593 try { 594 VariableField vf = new VariableField(String.valueOf(c), true); 595 logln("VariableField " + vf.toString()); 596 works = true; 597 } catch (Exception e) {} 598 if (works != valid.contains(c)) { 599 if (works) { 600 errln("VariableField can be created with illegal character: " + c); 601 } else { 602 errln("VariableField can't be created with legal character: " + c); 603 } 604 } 605 } 606 } 607 608 static String[] DATE_STYLE_NAMES = { 609 "FULL", "LONG", "MEDIUM", "SHORT" 610 }; 611 612 /** 613 * @param fullOrder 614 * @param longOrder 615 */ 616 private void checkCompatible(int style1, int style2, ULocale uLocale) { 617 DateOrder order1 = getOrdering(style1, uLocale); 618 DateOrder order2 = getOrdering(style2, uLocale); 619 if (!order1.hasSameOrderAs(order2)) { 620 // Note: This test case was updated by #6806 and no longer reports 621 // ordering difference as an error case. 622 logln(showOrderComparison(uLocale, style1, style2, order1, order2)); 623 } 624 } 625 626 private String showOrderComparison(ULocale uLocale, int style1, int style2, DateOrder order1, DateOrder order2) { 627 String pattern1 = ((SimpleDateFormat) DateFormat.getDateInstance(style1, uLocale)).toPattern(); 628 String pattern2 = ((SimpleDateFormat) DateFormat.getDateInstance(style2, uLocale)).toPattern(); 629 return "Mismatch in in ordering for " + uLocale + ": " + DATE_STYLE_NAMES[style1] + ": " + order1 + ", <" + pattern1 630 + ">; " 631 + DATE_STYLE_NAMES[style2] + ": " + order2 + ", <" + pattern2 + ">; " ; 632 } 633 634 /** 635 * Main date fields -- Poor-man's enum -- change to real enum when we get JDK 1.5 636 */ 637 public static class DateFieldType { 638 private String name; 639 private DateFieldType(String string) { 640 name = string; 641 } 642 643 public static DateFieldType 644 YEAR = new DateFieldType("YEAR"), 645 MONTH = new DateFieldType("MONTH"), 646 DAY = new DateFieldType("DAY"); 647 648 @Override 649 public String toString() { 650 return name; 651 } 652 } 653 654 /** 655 * Simple struct for output from getOrdering 656 */ 657 static class DateOrder { 658 int monthLength; 659 DateFieldType[] fields = new DateFieldType[3]; 660 661 public boolean isCompatible(DateOrder other) { 662 return monthLength == other.monthLength; 663 } 664 /** 665 * @param order2 666 * @return 667 */ 668 public boolean hasSameOrderAs(DateOrder other) { 669 // TODO Auto-generated method stub 670 return fields[0] == other.fields[0] && fields[1] == other.fields[1] && fields[2] == other.fields[2]; 671 } 672 @Override 673 public String toString() { 674 return "{" + monthLength + ", " + fields[0] + ", " + fields[1] + ", " + fields[2] + "}"; 675 } 676 @Override 677 public boolean equals(Object that) { 678 DateOrder other = (DateOrder) that; 679 return monthLength == other.monthLength && fields[0] == other.fields[0] && fields[1] == other.fields[1] && fields[2] == other.fields[2]; 680 } 681 } 682 683 DateTimePatternGenerator.FormatParser formatParser = new DateTimePatternGenerator.FormatParser (); 684 DateTimePatternGenerator generator = DateTimePatternGenerator.getEmptyInstance(); 685 686 private Calendar sampleCalendar; 687 { 688 sampleCalendar = new GregorianCalendar(TimeZone.getTimeZone("America/Los_Angeles")); 689 sampleCalendar.set(1999, Calendar.OCTOBER, 13, 23, 58, 59); 690 } 691 692 private Date sampleDate = sampleCalendar.getTime(); 693 private TimeZone gmt = TimeZone.getTimeZone("Etc/GMT"); 694 695 /** 696 * Replace the zone string with a different type, eg v's for z's, etc. <p>Called with a pattern, such as one gotten from 697 * <pre> 698 * String pattern = ((SimpleDateFormat) DateFormat.getTimeInstance(style, locale)).toPattern(); 699 * </pre> 700 * @param pattern original pattern to change, such as "HH:mm zzzz" 701 * @param newZone Must be: z, zzzz, Z, ZZZZ, v, vvvv, V, or VVVV 702 * @return 703 */ 704 public String replaceZoneString(String pattern, String newZone) { 705 final List itemList = formatParser.set(pattern).getItems(); 706 boolean changed = false; 707 for (int i = 0; i < itemList.size(); ++i) { 708 Object item = itemList.get(i); 709 if (item instanceof VariableField) { 710 VariableField variableField = (VariableField) item; 711 if (variableField.getType() == DateTimePatternGenerator.ZONE) { 712 if (!variableField.toString().equals(newZone)) { 713 changed = true; 714 itemList.set(i, new VariableField(newZone, true)); 715 } 716 } 717 } 718 } 719 return changed ? formatParser.toString() : pattern; 720 } 721 722 public boolean containsZone(String pattern) { 723 for (Iterator it = formatParser.set(pattern).getItems().iterator(); it.hasNext();) { 724 Object item = it.next(); 725 if (item instanceof VariableField) { 726 VariableField variableField = (VariableField) item; 727 if (variableField.getType() == DateTimePatternGenerator.ZONE) { 728 return true; 729 } 730 } 731 } 732 return false; 733 } 734 735 /** 736 * Get the ordering from a particular date format. Best is to use 737 * DateFormat.FULL to get the format with String form month (like "January") 738 * and DateFormat.SHORT for the numeric format order. They may be different. 739 * (Theoretically all 4 formats could be different but that never happens in 740 * practice.) 741 * 742 * @param style 743 * DateFormat.FULL..DateFormat.SHORT 744 * @param locale 745 * desired locale. 746 * @return 747 * @return list of ordered items DateFieldType (I 748 * didn't know what form you really wanted so this is just a 749 * stand-in.) 750 */ 751 private DateOrder getOrdering(int style, ULocale locale) { 752 // and the date pattern 753 String pattern = ((SimpleDateFormat) DateFormat.getDateInstance(style, locale)).toPattern(); 754 int count = 0; 755 DateOrder result = new DateOrder(); 756 757 for (Iterator it = formatParser.set(pattern).getItems().iterator(); it.hasNext();) { 758 Object item = it.next(); 759 if (!(item instanceof String)) { 760 // the first character of the variable field determines the type, 761 // according to CLDR. 762 String variableField = item.toString(); 763 switch (variableField.charAt(0)) { 764 case 'y': case 'Y': case 'u': 765 result.fields[count++] = DateFieldType.YEAR; 766 break; 767 case 'M': case 'L': 768 result.monthLength = variableField.length(); 769 if (result.monthLength < 2) { 770 result.monthLength = 2; 771 } 772 result.fields[count++] = DateFieldType.MONTH; 773 break; 774 case 'd': case 'D': case 'F': case 'g': 775 result.fields[count++] = DateFieldType.DAY; 776 break; 777 } 778 } 779 } 780 return result; 781 } 782 783 /* Tests the method 784 * public static DateTimePatternGenerator getInstance() 785 */ 786 @Test 787 public void TestGetInstance(){ 788 try{ 789 DateTimePatternGenerator.getInstance(); 790 } catch(Exception e){ 791 errln("DateTimePatternGenerator.getInstance() was not suppose to " + 792 "return an exception."); 793 } 794 } 795 796 /* Tests the method 797 * public String getSkeleton(String pattern) 798 */ 799 @Test 800 public void TestGetSkeleton(){ 801 DateTimePatternGenerator dtpg = DateTimePatternGenerator.getInstance(); 802 String[] cases = {"MMDD","MMMDD","MMM-DD","DD/MMM","ddM","MMMMd"}; 803 String[] results = {"MMDD","MMMDD","MMMDD","MMMDD","Mdd","MMMMd"}; 804 for(int i=0; i<cases.length; i++){ 805 if(!dtpg.getSkeleton(cases[i]).equals(results[i])){ 806 errln("DateTimePatternGenerator.getSkeleton(String) did " + 807 "return the expected result when passing " + cases[i] + 808 " and expected " + results[i] + " but got " + 809 dtpg.getSkeleton(cases[i])); 810 } 811 } 812 } 813 814 /* Tests the method 815 * public String getCanonicalSkeletonAllowingDuplicates(String pattern) 816 */ 817 public void TestGetCanonicalSkeletonAllowingDuplicates(){ 818 DateTimePatternGenerator dtpg = DateTimePatternGenerator.getInstance(); 819 String[] cases = {"GyQMwEdaHmsSv","LegH","Legh"}; 820 String[] results = {"GyQMwEdHmsSv","MEdH","MEdh"}; 821 for(int i=0; i<cases.length; i++){ 822 if(!dtpg.getCanonicalSkeletonAllowingDuplicates(cases[i]).equals(results[i])){ 823 errln("DateTimePatternGenerator.getCanonicalSkeletonAllowingDuplicates(String) did " + 824 "return the expected result when passing " + cases[i] + 825 " and expected " + results[i] + " but got " + 826 dtpg.getCanonicalSkeletonAllowingDuplicates(cases[i])); 827 } 828 } 829 } 830 831 /* Tests the method 832 * public String getBaseSkeleton(String pattern) 833 */ 834 @Test 835 public void TestGetBaseSkeleton(){ 836 DateTimePatternGenerator dtpg = DateTimePatternGenerator.getInstance(); 837 String[] cases = {"MMDD","MMMDD","MMM-DD","DD/MMM","ddM","MMMMd"}; 838 String[] results = {"MD","MMMD","MMMD","MMMD","Md","MMMMd"}; 839 for(int i=0; i<cases.length; i++){ 840 if(!dtpg.getBaseSkeleton(cases[i]).equals(results[i])){ 841 errln("DateTimePatternGenerator.getSkeleton(String) did " + 842 "return the expected result when passing " + cases[i] + 843 " and expected " + results[i] + " but got " + 844 dtpg.getBaseSkeleton(cases[i])); 845 } 846 } 847 } 848 849 /* Tests the method 850 * public Map<String, String> getSkeletons(Map<String, String> result) 851 */ 852 @Test 853 public void TestGetSkeletons(){ 854 DateTimePatternGenerator dtpg = DateTimePatternGenerator.getInstance(); 855 // Tests when "if (result == null)" is true 856 try{ 857 dtpg.getSkeletons(null); 858 } catch(Exception e){ 859 errln("DateTimePatternGenerator.getSkeletons(Map) was suppose to " + 860 "return a new LinkedHashMap for a null parameter."); 861 } 862 863 // Tests when "if (result == null)" is false 864 Map<String,String> mm = new LinkedHashMap<String, String>(); 865 try{ 866 dtpg.getSkeletons(mm); 867 } catch(Exception e){ 868 errln("DateTimePatternGenerator.getSkeletons(Map) was suppose to " + 869 "return a new LinkedHashMap for a LinkedHashMap parameter."); 870 } 871 } 872 873 /* Tests the method 874 * public Set<String> getBaseSkeletons(Set<String> result) 875 */ 876 @Test 877 public void TestGetBaseSkeletons(){ 878 DateTimePatternGenerator dtpg = DateTimePatternGenerator.getInstance(); 879 // Tests when "if (result == null)" is true 880 try{ 881 dtpg.getBaseSkeletons(null); 882 } catch(Exception e){ 883 errln("DateTimePatternGenerator.getBaseSkeletons(Map) was suppose to " + 884 "return a new LinkedHashMap for a null parameter."); 885 } 886 887 // Tests when "if (result == null)" is false 888 Set<String> mm = new HashSet<String>(); 889 try{ 890 dtpg.getBaseSkeletons(mm); 891 } catch(Exception e){ 892 errln("DateTimePatternGenerator.getBaseSkeletons(Map) was suppose to " + 893 "return a new LinkedHashMap for a HashSet parameter."); 894 } 895 } 896 897 /* Tests the method 898 * public String getDecimal() 899 */ 900 @Test 901 public void TestGetDecimal(){ 902 DateTimePatternGenerator dtpg = DateTimePatternGenerator.getInstance(); 903 if(!dtpg.getDecimal().equals(".")){ 904 errln("DateTimePatternGenerator.getDecimal() was to return '.' " + 905 "when the object gets a new instance."); 906 } 907 908 String[] cases = {",","-","","*","&","a","0"}; 909 for(int i=0; i<cases.length; i++){ 910 dtpg.setDecimal(cases[i]); 911 if(!dtpg.getDecimal().equals(cases[i])){ 912 errln("DateTimePatternGenerator.getDecimal() was to return " + cases[i] + 913 "when setting decimal with " + cases[i]); 914 } 915 } 916 } 917 918 /* Tests the method 919 * public Collection<String> getRedundants(Collection<String> output) 920 */ 921 @Test 922 public void TestGetRedundants(){ 923 DateTimePatternGenerator dtpg = DateTimePatternGenerator.getInstance(); 924 925 // Tests when "if (output == null)" is true 926 try{ 927 dtpg.getRedundants(null); 928 } catch(Exception e){ 929 errln("DateTimeGenerator.getRedundants was not supposed to return " + 930 "an exception when passing a null parameter: " + e); 931 } 932 933 // Tests when "if (output == null)" is false 934 try{ 935 Collection<String> out = new LinkedHashSet<String>(); 936 dtpg.getRedundants(out); 937 } catch(Exception e){ 938 errln("DateTimeGenerator.getRedundants was not supposed to return " + 939 "an exception when passing a new LinkedHashSet<String>() parameter: " + e); 940 } 941 } 942 943 /* Tests the method 944 * public String setAppendItemFormat(int field) 945 */ 946 @Test 947 public void TestSetAppendItemFormat(){ 948 DateTimePatternGenerator dtpg = DateTimePatternGenerator.getInstance(); 949 String[] cases = {"d","u","m","m","y"}; 950 for(int i=0; i<cases.length; i++){ 951 dtpg.setAppendItemFormat(i, cases[i]); 952 if(!dtpg.getAppendItemFormat(i).equals(cases[i])){ 953 errln("DateTimePatternGenerator.getAppendItemFormat(int field) " + 954 "did not return as expected. Value set at " + i + " was " + 955 cases[i] + " but got back " + dtpg.getAppendItemFormat(i)); 956 } 957 } 958 } 959 960 /* Tests the method 961 * public String getAppendItemFormat(int field) 962 */ 963 @Test 964 public void TestGetAppendItemFormat(){ 965 DateTimePatternGenerator dtpg = DateTimePatternGenerator.getInstance(ULocale.ENGLISH); 966 int[] fields = {DateTimePatternGenerator.ERA,DateTimePatternGenerator.DAY,DateTimePatternGenerator.SECOND}; 967 String[] results = {"{0} {1}","{0} ({2}: {1})","{0} ({2}: {1})"}; 968 for(int i=0; i<fields.length; i++){ 969 if(!dtpg.getAppendItemFormat(fields[i]).equals(results[i])){ 970 errln("DateTimePatternGenerator.getAppendItemFormat(int field) " + 971 "did not return as expected. For field " + fields[i] + ", was expecting " + 972 results[i] + " but got back " + dtpg.getAppendItemFormat(fields[i])); 973 } 974 } 975 } 976 977 /* Tests the method 978 * public String getAppendItemName(int field) 979 */ 980 private final class AppendItemName { 981 public int field; 982 public String name; 983 public AppendItemName(int f, String n) { 984 field = f; 985 name = n; 986 } 987 } 988 989 @Test 990 public void TestGetAppendItemName(){ 991 final AppendItemName[] appendItemNames = { 992 new AppendItemName( DateTimePatternGenerator.YEAR, "vuosi" ), 993 new AppendItemName( DateTimePatternGenerator.MONTH, "kuukausi" ), 994 new AppendItemName( DateTimePatternGenerator.WEEKDAY, "viikonp\u00E4iv\u00E4" ), 995 new AppendItemName( DateTimePatternGenerator.DAY, "p\u00E4iv\u00E4" ), 996 new AppendItemName( DateTimePatternGenerator.HOUR, "tunti" ), 997 }; 998 999 DateTimePatternGenerator dtpg = DateTimePatternGenerator.getInstance(); 1000 String[] cases = {"d","u","m","m","y"}; 1001 for(int i=0; i<cases.length; i++){ 1002 dtpg.setAppendItemName(i, cases[i]); 1003 if(!dtpg.getAppendItemName(i).equals(cases[i])){ 1004 errln("DateTimePatternGenerator.getAppendItemFormat(int field) " + 1005 "did not return as expected. Value set at " + i + " was " + 1006 cases[i] + " but got back " + dtpg.getAppendItemName(i)); 1007 } 1008 } 1009 1010 DateTimePatternGenerator dtpgfi = DateTimePatternGenerator.getInstance(ULocale.forLanguageTag("fi")); 1011 for (AppendItemName appendItemName: appendItemNames) { 1012 String name = dtpgfi.getAppendItemName(appendItemName.field); 1013 if (!name.equals(appendItemName.name)) { 1014 errln("DateTimePatternGenerator.getAppendItemName returns invalid name for field " + appendItemName.field 1015 + ": got " + name + " but expected " + appendItemName.name); 1016 } 1017 } 1018 } 1019 1020 /* Tests the method 1021 * public static boolean isSingleField(String skeleton) 1022 */ 1023 @SuppressWarnings("static-access") 1024 @Test 1025 public void TestIsSingleField(){ 1026 DateTimePatternGenerator dtpg = DateTimePatternGenerator.getInstance(); 1027 String[] cases = {" ", "m","mm","md","mmd","mmdd"}; 1028 boolean[] results = {true,true,true,false,false,false}; 1029 for(int i=0; i<cases.length; i++){ 1030 if(dtpg.isSingleField(cases[i]) != results[i]){ 1031 errln("DateTimePatternGenerator.isSingleField(String skeleton) " + 1032 "did not return as expected. Value passed was " + cases[i] + 1033 " but got back " + dtpg.isSingleField(cases[i])); 1034 } 1035 } 1036 } 1037 1038 /* Tests the method 1039 * public Object freeze() 1040 * public Object cloneAsThawed() 1041 */ 1042 @Test 1043 public void TestFreezeAndCloneAsThawed(){ 1044 DateTimePatternGenerator dtpg = DateTimePatternGenerator.getInstance(); 1045 1046 if(dtpg.isFrozen() != false){ 1047 errln("DateTimePatternGenerator.isFrozen() is suppose to return false " + 1048 "for a DateTimePatternGenerator object that was just " + 1049 "created."); 1050 } 1051 1052 dtpg.freeze(); 1053 if(dtpg.isFrozen() != true){ 1054 errln("DateTimePatternGenerator.isFrozen() is suppose to return true " + 1055 "for a DateTimePatternGenerator object that was just " + 1056 "created and freeze."); 1057 } 1058 1059 DateTimePatternGenerator dtpg2 = dtpg.cloneAsThawed(); 1060 if(dtpg.isFrozen() != false){ 1061 errln("DateTimePatternGenerator.isFrozen() is suppose to return false " + 1062 "for a DateTimePatternGenerator object that was just " + 1063 "clone as thawed."); 1064 } 1065 if(dtpg2.isFrozen() != false){ 1066 errln("DateTimePatternGenerator.isFrozen() is suppose to return false " + 1067 "for a second DateTimePatternGenerator object that was just " + 1068 "clone as thawed."); 1069 } 1070 } 1071 1072 /* Tests the method 1073 * public Object clone() 1074 */ 1075 @Test 1076 public void TestClone(){ 1077 DateTimePatternGenerator dtpg = DateTimePatternGenerator.getInstance(); 1078 DateTimePatternGenerator dtpg2 = (DateTimePatternGenerator) dtpg.clone(); 1079 dtpg = (DateTimePatternGenerator) dtpg2.clone(); 1080 } 1081 1082 /* Tests the constructor 1083 * public VariableField(String string) 1084 */ 1085 //TODO(junit) why is this "unused" 1086 @SuppressWarnings("unused") 1087 @Test 1088 public void TestVariableField_String(){ 1089 String[] cases = {"d","mm","aa"}; 1090 String[] invalid = {null,"","dummy"}; 1091 for(int i=0; i<cases.length; i++){ 1092 try{ 1093 VariableField vf = new VariableField(cases[i]); 1094 } catch(Exception e){ 1095 errln("VariableField constructor was not suppose to return " + 1096 "an exception when created when passing " + cases[i]); 1097 } 1098 } 1099 for(int i=0; i<invalid.length; i++){ 1100 try{ 1101 VariableField vf = new VariableField(invalid[i]); 1102 errln("VariableField constructor was suppose to return " + 1103 "an exception when created when passing " + invalid[i]); 1104 } catch(Exception e){} 1105 } 1106 } 1107 1108 /* Tests the method 1109 * public FormatParser set(String string, boolean strict) 1110 */ 1111 @Test 1112 public void TestSet(){ 1113 FormatParser fp = new FormatParser(); 1114 //Tests when "if (string.length() == 0)" is true 1115 try{ 1116 fp.set("",true); 1117 }catch(Exception e){ 1118 errln("FormatParser.set(String,boolean) was not suppose to " + 1119 "return an exception."); 1120 } 1121 } 1122 1123 /* Tests the method 1124 * public String toString() 1125 */ 1126 @Test 1127 public void TestToString(){ 1128 FormatParser fp = new FormatParser(); 1129 if(!fp.toString().equals("")){ 1130 errln("FormatParser.toString() was suppose to return an " + 1131 "empty string for a new FormatParser object."); 1132 } 1133 1134 String[] cases = {"m","d","y","mm","mmm","mm dd","mm':'dd","mm-dd-yyyy"}; 1135 String[] results = {"m","d","y","mm","mmm","mm dd","mm:dd","mm-dd-yyyy"}; 1136 for(int i=0; i<cases.length; i++){ 1137 fp.set(cases[i]); 1138 if(!fp.toString().equals(results[i])){ 1139 errln("FormatParser.toString() was suppose to return " + results[i] + 1140 " after setting the object. Got: " + fp.toString()); 1141 } 1142 } 1143 } 1144 1145 /* Tests the method 1146 * public boolean hasDateAndTimeFields() 1147 */ 1148 @Test 1149 public void TestHasDateAndTimeFields(){ 1150 FormatParser fp = new FormatParser(); 1151 if(fp.hasDateAndTimeFields() != false){ 1152 errln("FormatParser.hasDateAndTimeFields() was suppose to return " + 1153 "false when a new object is created."); 1154 } 1155 1156 String[] cases = {"MMDDYY", "HHMMSS", "", "MM/DD/YYYY HH:MM:SS", 1157 "MMDDYY HHMMSS", "HHMMSS MMDDYYYY", "HMS MDY"}; 1158 boolean[] results = {false,true,false,true,true,true,true}; 1159 for(int i=0; i<cases.length; i++){ 1160 fp.set(cases[i]); 1161 if(fp.hasDateAndTimeFields() != results[i]){ 1162 errln("FormatParser.hasDateAndTimeFields() was suppose to " + 1163 "return " + results[i] + " but returned " + 1164 fp.hasDateAndTimeFields() + " for parameter " + 1165 cases[i] + " that is set to FormatParser."); 1166 } 1167 } 1168 } 1169 1170 /* Tests the method 1171 * private void checkFrozen() 1172 * from public void setDateTimeFormat(String dateTimeFormat) 1173 */ 1174 @Test 1175 public void TestCheckFrozen(){ 1176 // Tests when "if (isFrozen())" is true 1177 DateTimePatternGenerator dt = DateTimePatternGenerator.getInstance(); 1178 try{ 1179 dt.freeze(); 1180 dt.setDateTimeFormat("MMDDYYYY"); 1181 errln("DateTimePatternGenerator.checkFrozen() was suppose to " + 1182 "return an exception when trying to setDateTimeFormat " + 1183 "for a frozen object."); 1184 } catch(Exception e){} 1185 dt = dt.cloneAsThawed(); 1186 } 1187 1188 /* Tests the method 1189 * public String getFields(String pattern) 1190 */ 1191 @Test 1192 public void TestGetFields(){ 1193 DateTimePatternGenerator dt = DateTimePatternGenerator.getInstance(); 1194 String[] cases = {"MMDDYY", "HHMMSS", "", "MM/DD/YYYY HH:MM:SS", 1195 "MMDDYY HHMMSS", "HHMMSS MMDDYYYY", "HMS MDY"}; 1196 String[] results = {"{Month:N}{Day_Of_Year:N}{Year:N}", 1197 "{Hour:N}{Month:N}{Fractional_Second:N}","", 1198 "{Month:N}/{Day_Of_Year:N}/{Year:N} {Hour:N}:{Month:N}:{Fractional_Second:N}", 1199 "{Month:N}{Day_Of_Year:N}{Year:N} {Hour:N}{Month:N}{Fractional_Second:N}", 1200 "{Hour:N}{Month:N}{Fractional_Second:N} {Month:N}{Day_Of_Year:N}{Year:N}", 1201 "{Hour:N}{Month:N}{Fractional_Second:N} {Month:N}{Day_Of_Year:N}{Year:N}"}; 1202 for(int i=0; i<cases.length; i++){ 1203 if(!dt.getFields(cases[i]).equals(results[i])) { 1204 errln("DateTimePatternGenerator.getFields(String) did not " + 1205 "not return an expected result when passing " + cases[i] + 1206 ". Got " + dt.getFields(cases[i]) + " but expected " + 1207 results[i]); 1208 } 1209 } 1210 } 1211 1212 /* 1213 * Test case for DateFormatPatternGenerator threading problem #7169 1214 */ 1215 @Test 1216 public void TestT7169() { 1217 Thread[] workers = new Thread[10]; 1218 for (int i = 0 ; i < workers.length; i++) { 1219 workers[i] = new Thread(new Runnable() { 1220 @Override 1221 public void run() { 1222 try { 1223 for (int i = 0; i < 50; i++) { 1224 DateTimePatternGenerator patternGenerator = 1225 DateTimePatternGenerator.getFrozenInstance(ULocale.US); 1226 patternGenerator.getBestPattern("MMMMd"); 1227 } 1228 } catch (Exception e) { 1229 errln("FAIL: Caught an exception (frozen)" + e); 1230 } 1231 try { 1232 for (int i = 0; i < 50; i++) { 1233 DateTimePatternGenerator patternGenerator = 1234 DateTimePatternGenerator.getInstance(ULocale.US); 1235 patternGenerator.getBestPattern("MMMMd"); 1236 } 1237 } catch (Exception e) { 1238 errln("FAIL: Caught an exception " + e); 1239 } 1240 } 1241 }); 1242 } 1243 for (Thread wk : workers) { 1244 wk.start(); 1245 } 1246 for (Thread wk : workers) { 1247 try { 1248 wk.join(); 1249 } catch (InterruptedException ie) { 1250 1251 } 1252 } 1253 } 1254 1255 /** 1256 * Test handling of options 1257 * 1258 * For reference, as of ICU 4.3.3, 1259 * root/gregorian has 1260 * Hm{"H:mm"} 1261 * Hms{"H:mm:ss"} 1262 * hm{"h:mm a"} 1263 * hms{"h:mm:ss a"} 1264 * en/gregorian has 1265 * Hm{"H:mm"} 1266 * Hms{"H:mm:ss"} 1267 * hm{"h:mm a"} 1268 * be/gregorian has 1269 * HHmmss{"HH.mm.ss"} 1270 * Hm{"HH.mm"} 1271 * hm{"h.mm a"} 1272 * hms{"h.mm.ss a"} 1273 */ 1274 private final class TestOptionsItem { 1275 public String locale; 1276 public String skeleton; 1277 public String expectedPattern; 1278 public int options; 1279 // Simple constructor 1280 public TestOptionsItem(String loc, String skel, String expectedPat, int opts) { 1281 locale = loc; 1282 skeleton = skel; 1283 expectedPattern = expectedPat; 1284 options = opts; 1285 } 1286 } 1287 @Test 1288 public void TestOptions() { 1289 final TestOptionsItem[] testOptionsData = { 1290 new TestOptionsItem( "en", "Hmm", "HH:mm", DateTimePatternGenerator.MATCH_NO_OPTIONS ), 1291 new TestOptionsItem( "en", "HHmm", "HH:mm", DateTimePatternGenerator.MATCH_NO_OPTIONS ), 1292 new TestOptionsItem( "en", "hhmm", "h:mm a", DateTimePatternGenerator.MATCH_NO_OPTIONS ), 1293 new TestOptionsItem( "en", "Hmm", "HH:mm", DateTimePatternGenerator.MATCH_HOUR_FIELD_LENGTH ), 1294 new TestOptionsItem( "en", "HHmm", "HH:mm", DateTimePatternGenerator.MATCH_HOUR_FIELD_LENGTH ), 1295 new TestOptionsItem( "en", "hhmm", "hh:mm a", DateTimePatternGenerator.MATCH_HOUR_FIELD_LENGTH ), 1296 new TestOptionsItem( "da", "Hmm", "HH.mm", DateTimePatternGenerator.MATCH_NO_OPTIONS ), 1297 new TestOptionsItem( "da", "HHmm", "HH.mm", DateTimePatternGenerator.MATCH_NO_OPTIONS ), 1298 new TestOptionsItem( "da", "hhmm", "h.mm a", DateTimePatternGenerator.MATCH_NO_OPTIONS ), 1299 new TestOptionsItem( "da", "Hmm", "H.mm", DateTimePatternGenerator.MATCH_HOUR_FIELD_LENGTH ), 1300 new TestOptionsItem( "da", "HHmm", "HH.mm", DateTimePatternGenerator.MATCH_HOUR_FIELD_LENGTH ), 1301 new TestOptionsItem( "da", "hhmm", "hh.mm a", DateTimePatternGenerator.MATCH_HOUR_FIELD_LENGTH ), 1302 // 1303 new TestOptionsItem( "en", "yyyy", "yyyy", DateTimePatternGenerator.MATCH_NO_OPTIONS ), 1304 new TestOptionsItem( "en", "YYYY", "YYYY", DateTimePatternGenerator.MATCH_NO_OPTIONS ), 1305 new TestOptionsItem( "en", "U", "y", DateTimePatternGenerator.MATCH_NO_OPTIONS ), 1306 new TestOptionsItem( "en@calendar=japanese", "yyyy", "y G", DateTimePatternGenerator.MATCH_NO_OPTIONS ), 1307 new TestOptionsItem( "en@calendar=japanese", "YYYY", "Y G", DateTimePatternGenerator.MATCH_NO_OPTIONS ), 1308 new TestOptionsItem( "en@calendar=japanese", "U", "y G", DateTimePatternGenerator.MATCH_NO_OPTIONS ), 1309 new TestOptionsItem( "en@calendar=chinese", "yyyy", "r(U)", DateTimePatternGenerator.MATCH_NO_OPTIONS ), 1310 new TestOptionsItem( "en@calendar=chinese", "YYYY", "Y(Y)", DateTimePatternGenerator.MATCH_NO_OPTIONS ), // not a good result, want r(Y) or r(U) 1311 new TestOptionsItem( "en@calendar=chinese", "U", "r(U)", DateTimePatternGenerator.MATCH_NO_OPTIONS ), 1312 new TestOptionsItem( "en@calendar=chinese", "Gy", "r(U)", DateTimePatternGenerator.MATCH_NO_OPTIONS ), 1313 new TestOptionsItem( "en@calendar=chinese", "GU", "r(U)", DateTimePatternGenerator.MATCH_NO_OPTIONS ), 1314 new TestOptionsItem( "en@calendar=chinese", "ULLL", "MMM U", DateTimePatternGenerator.MATCH_NO_OPTIONS ), 1315 new TestOptionsItem( "en@calendar=chinese", "yMMM", "MMM r(U)", DateTimePatternGenerator.MATCH_NO_OPTIONS ), 1316 new TestOptionsItem( "en@calendar=chinese", "GUMMM", "MMM r(U)", DateTimePatternGenerator.MATCH_NO_OPTIONS ), 1317 new TestOptionsItem( "zh@calendar=chinese", "yyyy", "rU\u5E74", DateTimePatternGenerator.MATCH_NO_OPTIONS ), 1318 new TestOptionsItem( "zh@calendar=chinese", "YYYY", "YY\u5E74", DateTimePatternGenerator.MATCH_NO_OPTIONS ), // not a good result, want r(Y) or r(U) 1319 new TestOptionsItem( "zh@calendar=chinese", "U", "rU\u5E74", DateTimePatternGenerator.MATCH_NO_OPTIONS ), 1320 new TestOptionsItem( "zh@calendar=chinese", "Gy", "rU\u5E74", DateTimePatternGenerator.MATCH_NO_OPTIONS ), 1321 new TestOptionsItem( "zh@calendar=chinese", "GU", "rU\u5E74", DateTimePatternGenerator.MATCH_NO_OPTIONS ), 1322 new TestOptionsItem( "zh@calendar=chinese", "ULLL", "U\u5E74MMM", DateTimePatternGenerator.MATCH_NO_OPTIONS ), 1323 new TestOptionsItem( "zh@calendar=chinese", "yMMM", "rU\u5E74MMM", DateTimePatternGenerator.MATCH_NO_OPTIONS ), 1324 new TestOptionsItem( "zh@calendar=chinese", "GUMMM", "rU\u5E74MMM", DateTimePatternGenerator.MATCH_NO_OPTIONS ), 1325 }; 1326 1327 for (int i = 0; i < testOptionsData.length; ++i) { 1328 ULocale uloc = new ULocale(testOptionsData[i].locale); 1329 DateTimePatternGenerator dtpgen = DateTimePatternGenerator.getInstance(uloc); 1330 String pattern = dtpgen.getBestPattern(testOptionsData[i].skeleton, testOptionsData[i].options); 1331 if (pattern.compareTo(testOptionsData[i].expectedPattern) != 0) { 1332 errln("Locale " + testOptionsData[i].locale + ", skeleton " + testOptionsData[i].skeleton + 1333 ", options " + ((testOptionsData[i].options != 0)? "!=0": "==0") + 1334 ", expected pattern " + testOptionsData[i].expectedPattern + ", got " + pattern); 1335 } 1336 } 1337 } 1338 1339 /** 1340 * Test that DTPG can handle all valid pattern character / length combinations 1341 */ 1342 private final class AllFieldsTestItem { 1343 public char patternChar; 1344 public int[] fieldLengths; 1345 public String mustIncludeOneOf; 1346 // Simple constructor 1347 public AllFieldsTestItem(char pC, int[] fL, String mI) { 1348 patternChar = pC; 1349 fieldLengths = fL; 1350 mustIncludeOneOf = mI; 1351 } 1352 } 1353 1354 @Test 1355 public void TestAllFieldPatterns() { 1356 String[] localeNames = { 1357 "root", 1358 "root@calendar=japanese", 1359 "root@calendar=chinese", 1360 "en", 1361 "en@calendar=japanese", 1362 "en@calendar=chinese", 1363 }; 1364 final AllFieldsTestItem[] testItems = { 1365 // pat fieldLengths generated pattern must 1366 // chr to test include one of these 1367 new AllFieldsTestItem( 'G', new int[]{1,2,3,4,5}, "G" ), // era 1368 // year 1369 new AllFieldsTestItem( 'y', new int[]{1,2,3,4}, "yU" ), // year 1370 new AllFieldsTestItem( 'Y', new int[]{1,2,3,4}, "Y" ), // year for week of year 1371 new AllFieldsTestItem( 'u', new int[]{1,2,3,4,5}, "yuU" ), // extended year 1372 new AllFieldsTestItem( 'U', new int[]{1,2,3,4,5}, "yU" ), // cyclic year name 1373 // quarter 1374 new AllFieldsTestItem( 'Q', new int[]{1,2,3,4}, "Qq" ), // x 1375 new AllFieldsTestItem( 'q', new int[]{1,2,3,4}, "Qq" ), // standalone 1376 // month 1377 new AllFieldsTestItem( 'M', new int[]{1,2,3,4,5}, "ML" ), // x 1378 new AllFieldsTestItem( 'L', new int[]{1,2,3,4,5}, "ML" ), // standalone 1379 // week 1380 new AllFieldsTestItem( 'w', new int[]{1,2}, "w" ), // week of year 1381 new AllFieldsTestItem( 'W', new int[]{1}, "W" ), // week of month 1382 // day 1383 new AllFieldsTestItem( 'd', new int[]{1,2}, "d" ), // day of month 1384 new AllFieldsTestItem( 'D', new int[]{1,2,3}, "D" ), // day of year 1385 new AllFieldsTestItem( 'F', new int[]{1}, "F" ), // day of week in month 1386 new AllFieldsTestItem( 'g', new int[]{7}, "g" ), // modified julian day 1387 // weekday 1388 new AllFieldsTestItem( 'E', new int[]{1,2,3,4,5,6}, "Eec" ), // day of week 1389 new AllFieldsTestItem( 'e', new int[]{1,2,3,4,5,6}, "Eec" ), // local day of week 1390 new AllFieldsTestItem( 'c', new int[]{1,2,3,4,5,6}, "Eec" ), // standalone local day of week 1391 // day period 1392 // new AllFieldsTestItem( 'a', new int[]{1}, "a" ), // am or pm // not clear this one is supposed to work (it doesn't) 1393 // hour 1394 new AllFieldsTestItem( 'h', new int[]{1,2}, "hK" ), // 12 (1-12) 1395 new AllFieldsTestItem( 'H', new int[]{1,2}, "Hk" ), // 24 (0-23) 1396 new AllFieldsTestItem( 'K', new int[]{1,2}, "hK" ), // 12 (0-11) 1397 new AllFieldsTestItem( 'k', new int[]{1,2}, "Hk" ), // 24 (1-24) 1398 new AllFieldsTestItem( 'j', new int[]{1,2}, "hHKk" ), // locale default 1399 // minute 1400 new AllFieldsTestItem( 'm', new int[]{1,2}, "m" ), // x 1401 // second & fractions 1402 new AllFieldsTestItem( 's', new int[]{1,2}, "s" ), // x 1403 new AllFieldsTestItem( 'S', new int[]{1,2,3,4}, "S" ), // fractional second 1404 new AllFieldsTestItem( 'A', new int[]{8}, "A" ), // milliseconds in day 1405 // zone 1406 new AllFieldsTestItem( 'z', new int[]{1,2,3,4}, "z" ), // x 1407 new AllFieldsTestItem( 'Z', new int[]{1,2,3,4,5}, "Z" ), // x 1408 new AllFieldsTestItem( 'O', new int[]{1,4}, "O" ), // x 1409 new AllFieldsTestItem( 'v', new int[]{1,4}, "v" ), // x 1410 new AllFieldsTestItem( 'V', new int[]{1,2,3,4}, "V" ), // x 1411 new AllFieldsTestItem( 'X', new int[]{1,2,3,4,5}, "X" ), // x 1412 new AllFieldsTestItem( 'x', new int[]{1,2,3,4,5}, "x" ), // x 1413 }; 1414 final int FIELD_LENGTH_MAX = 8; 1415 1416 for (String localeName: localeNames) { 1417 ULocale uloc = new ULocale(localeName); 1418 DateTimePatternGenerator dtpgen = DateTimePatternGenerator.getInstance(uloc); 1419 for (AllFieldsTestItem testItem: testItems) { 1420 char[] skelBuf = new char[FIELD_LENGTH_MAX]; 1421 for (int chrIndx = 0; chrIndx < FIELD_LENGTH_MAX; chrIndx++) { 1422 skelBuf[chrIndx] = testItem.patternChar; 1423 } 1424 for (int lenIndx = 0; lenIndx < testItem.fieldLengths.length; lenIndx++) { 1425 int skelLen = testItem.fieldLengths[lenIndx]; 1426 if (skelLen > FIELD_LENGTH_MAX) { 1427 continue; 1428 }; 1429 String skeleton = new String(skelBuf, 0, skelLen); 1430 String pattern = dtpgen.getBestPattern(skeleton); 1431 if (pattern.length() <= 0) { 1432 errln("DateTimePatternGenerator getBestPattern for locale " + localeName + 1433 ", skeleton " + skeleton + ", produces 0-length pattern"); 1434 } else { 1435 // test that resulting pattern has at least one char in mustIncludeOneOf 1436 boolean inQuoted = false; 1437 int patIndx, patLen = pattern.length(); 1438 for (patIndx = 0; patIndx < patLen; patIndx++) { 1439 char c = pattern.charAt(patIndx); 1440 if (c == '\'') { 1441 inQuoted = !inQuoted; 1442 } else if (!inQuoted && c <= 'z' && c >= 'A') { 1443 if (testItem.mustIncludeOneOf.indexOf(c) >= 0) { 1444 break; 1445 } 1446 } 1447 } 1448 if (patIndx >= patLen) { 1449 errln("DateTimePatternGenerator getBestPattern for locale " + localeName + 1450 ", skeleton " + skeleton + 1451 ", produces pattern without required chars: " + pattern); 1452 } 1453 } 1454 } 1455 } 1456 } 1457 } 1458 1459 @Test 1460 public void TestJavaLocale() { 1461 DateTimePatternGenerator genUloc = DateTimePatternGenerator.getInstance(ULocale.GERMANY); 1462 DateTimePatternGenerator genLoc = DateTimePatternGenerator.getInstance(Locale.GERMANY); 1463 1464 final String pat = "yMdHms"; 1465 String patUloc = genUloc.getBestPattern(pat); 1466 String patLoc = genLoc.getBestPattern(pat); 1467 1468 assertEquals("German pattern 'yMdHms' - getInstance with Java Locale", patUloc, patLoc); 1469 } 1470 1471 /* Tests the method 1472 * public static int getAppendFormatNumber(String string) 1473 */ 1474 @Test 1475 public void TestGetAppendFormatNumber(){ 1476 int fieldNum; 1477 fieldNum = DateTimePatternGenerator.getAppendFormatNumber("Era"); 1478 assertEquals("DateTimePatternGenerator.getAppendFormatNumber for Era", 0, fieldNum); 1479 fieldNum = DateTimePatternGenerator.getAppendFormatNumber("Timezone"); 1480 assertEquals("DateTimePatternGenerator.getAppendFormatNumber for Timezone", 15, fieldNum); 1481 } 1482 1483 /* 1484 * Coverage for methods otherwise not covered by other tests. 1485 */ 1486 @Test 1487 public void TestCoverage() { 1488 DateTimePatternGenerator dtpg; 1489 1490 // DateTimePatternGenerator#getDefaultHourFormatChar 1491 // DateTimePatternGenerator#setDefaultHourFormatChar 1492 { 1493 dtpg = DateTimePatternGenerator.getEmptyInstance(); 1494 assertEquals("Default hour char on empty instance", 'H', dtpg.getDefaultHourFormatChar()); 1495 dtpg.setDefaultHourFormatChar('e'); 1496 assertEquals("Default hour char after explicit set", 'e', dtpg.getDefaultHourFormatChar()); 1497 dtpg = DateTimePatternGenerator.getInstance(ULocale.ENGLISH); 1498 assertEquals("Default hour char on populated English instance", 'h', dtpg.getDefaultHourFormatChar()); 1499 } 1500 1501 // DateTimePatternGenerator#getSkeletonAllowingDuplicates 1502 // DateTimePatternGenerator#getCanonicalSkeletonAllowingDuplicates 1503 // DateTimePatternGenerator#getCanonicalChar 1504 { 1505 dtpg = DateTimePatternGenerator.getInstance(ULocale.ENGLISH); 1506 assertEquals("Example skeleton with no duplicate fields", "MMMdd", dtpg.getSkeleton("dd/MMM")); 1507 assertEquals("Should return same result as getSkeleton with no duplicate fields", 1508 dtpg.getSkeleton("dd/MMM"), dtpg.getSkeletonAllowingDuplicates("dd/MMM")); 1509 1510 try { 1511 dtpg.getSkeleton("dd/MMM Zz"); 1512 fail("getSkeleton should throw upon duplicate fields"); 1513 } catch(IllegalArgumentException e) { 1514 assertEquals("getSkeleton should throw upon duplicate fields", 1515 "Conflicting fields:\tZ, z\t in dd/MMM Zz", e.getMessage()); 1516 } 1517 1518 assertEquals("Should not throw upon duplicate fields", 1519 "MMMddZ", dtpg.getSkeletonAllowingDuplicates("dd/MMM Zz")); 1520 assertEquals("Should not throw upon duplicate fields and should return Canonical fields", 1521 "MMMddv", dtpg.getCanonicalSkeletonAllowingDuplicates("dd/MMM Zz")); 1522 } 1523 1524 // DistanceInfo#toString 1525 // DateTimePatternGenerator#showMask 1526 try { 1527 String actual = invokeToString("com.ibm.icu.text.DateTimePatternGenerator$DistanceInfo"); 1528 assertEquals("DistanceInfo toString", "missingFieldMask: , extraFieldMask: ", actual); 1529 } catch(Exception e) { 1530 errln("Couldn't call DistanceInfo.toString(): " + e.toString()); 1531 } 1532 1533 // DateTimePatternGenerator#skeletonsAreSimilar 1534 // DateTimePatternGenerator#getSet 1535 { 1536 dtpg = DateTimePatternGenerator.getInstance(ULocale.ENGLISH); 1537 assertTrue("Trivial skeletonsAreSimilar", dtpg.skeletonsAreSimilar("MMMdd", "MMMdd")); 1538 assertTrue("Different number of chars in skeletonsAreSimilar", dtpg.skeletonsAreSimilar("Mddd", "MMMdd")); 1539 assertFalse("Failure case for skeletonsAreSimilar", dtpg.skeletonsAreSimilar("mmDD", "MMMdd")); 1540 } 1541 } 1542 1543 @Test 1544 public void TestEmptyInstance() { 1545 DateTimePatternGenerator dtpg = DateTimePatternGenerator.getEmptyInstance(); 1546 String skeleton = "GrMMd"; 1547 String message = "DTPG getEmptyInstance should not throw exceptions on basic operations and should conform to " 1548 + "the example in setAppendItemFormat"; 1549 assertEquals(message, "G ├'F7': d┤ ├'F3': MM┤ ├'F1': y┤", dtpg.getBestPattern(skeleton)); 1550 dtpg.addPattern("d-MM-yyyy", false, new DateTimePatternGenerator.PatternInfo()); 1551 assertEquals(message, "d-MM-y ├'F0': G┤", dtpg.getBestPattern(skeleton)); 1552 dtpg.setAppendItemFormat(DateTimePatternGenerator.ERA, "{0}, {1}"); 1553 assertEquals(message, "d-MM-y, G", dtpg.getBestPattern(skeleton)); 1554 } 1555} 1556