1 /* 2 * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 import java.text.*; 25 import java.util.*; 26 import java.io.*; 27 28 /** 29 * @test 30 * @bug 4029195 4052408 4056591 4059917 4060212 4061287 4065240 4071441 4073003 31 * 4089106 4100302 4101483 4103340 4103341 4104136 4104522 4106807 4108407 32 * 4134203 4138203 4148168 4151631 4151706 4153860 4162071 4182066 4209272 4210209 33 * 4213086 4250359 4253490 4266432 4406615 4413980 8008577 34 * @library /java/text/testlib 35 * @run main/othervm -Djava.locale.providers=COMPAT,SPI DateFormatRegression 36 */ 37 public class DateFormatRegression extends IntlTest { 38 39 public static void main(String[] args) throws Exception { 40 new DateFormatRegression().run(args); 41 } 42 43 public void Test4029195() { 44 @SuppressWarnings("deprecation") 45 Date today = new Date(); 46 47 logln("today: " + today); 48 49 SimpleDateFormat sdf = (SimpleDateFormat)SimpleDateFormat.getDateInstance(); 50 logln("pattern: " + sdf.toPattern()); 51 logln("today: " + sdf.format(today)); 52 53 sdf.applyPattern("G yyyy DDD"); 54 String todayS = sdf.format(today); 55 logln("today: " + todayS); 56 try { 57 today = sdf.parse(todayS); 58 logln("today date: " + today); 59 } catch(Exception e) { 60 logln("Error reparsing date: " + e.getMessage()); 61 } 62 63 try { 64 String rt = sdf.format(sdf.parse(todayS)); 65 logln("round trip: " + rt); 66 if (!rt.equals(todayS)) errln("Fail: Want " + todayS + " Got " + rt); 67 } 68 catch (ParseException e) { 69 errln("Fail: " + e); 70 e.printStackTrace(); 71 } 72 } 73 74 public void Test4052408() { 75 DateFormat fmt = DateFormat.getDateTimeInstance(DateFormat.SHORT, 76 DateFormat.SHORT, Locale.US); 77 @SuppressWarnings("deprecation") 78 Date date = new Date(97, Calendar.MAY, 3, 8, 55); 79 String str; 80 logln(str = fmt.format(date)); 81 82 if (!str.equals("5/3/97 8:55 AM")) 83 errln("Fail: Test broken; Want 5/3/97 8:55 AM Got " + str); 84 Map<Integer,String> expected = new HashMap<>(); 85 expected.put(DateFormat.MONTH_FIELD, "5"); 86 expected.put(DateFormat.DATE_FIELD, "3"); 87 expected.put(DateFormat.YEAR_FIELD, "97"); 88 expected.put(DateFormat.HOUR1_FIELD, "8"); 89 expected.put(DateFormat.MINUTE_FIELD, "55"); 90 expected.put(DateFormat.AM_PM_FIELD, "AM"); 91 92 StringBuffer buf = new StringBuffer(); 93 String fieldNames[] = { 94 "ERA_FIELD", 95 "YEAR_FIELD", 96 "MONTH_FIELD", 97 "DATE_FIELD", 98 "HOUR_OF_DAY1_FIELD", 99 "HOUR_OF_DAY0_FIELD", 100 "MINUTE_FIELD", 101 "SECOND_FIELD", 102 "MILLISECOND_FIELD", 103 "DAY_OF_WEEK_FIELD", 104 "DAY_OF_YEAR_FIELD", 105 "DAY_OF_WEEK_IN_MONTH_FIELD", 106 "WEEK_OF_YEAR_FIELD", 107 "WEEK_OF_MONTH_FIELD", 108 "AM_PM_FIELD", 109 "HOUR1_FIELD", 110 "HOUR0_FIELD", 111 "TIMEZONE_FIELD", 112 }; 113 boolean pass = true; 114 for (int i=0; i<=17; ++i) { 115 FieldPosition pos = new FieldPosition(i); 116 fmt.format(date, buf, pos); 117 char[] dst = new char[pos.getEndIndex() - pos.getBeginIndex()]; 118 buf.getChars(pos.getBeginIndex(), pos.getEndIndex(), dst, 0); 119 str = new String(dst); 120 log(i + ": " + fieldNames[i] + 121 ", \"" + str + "\", " + 122 pos.getBeginIndex() + ", " + 123 pos.getEndIndex()); 124 String exp = expected.get(i); 125 if ((exp == null && str.length() == 0) || 126 str.equals(exp)) 127 logln(" ok"); 128 else { 129 logln(" expected " + exp); 130 pass = false; 131 } 132 } 133 if (!pass) errln("Fail: FieldPosition not set right by DateFormat"); 134 } 135 136 /** 137 * Verify the function of the [s|g]et2DigitYearStart() API. 138 */ 139 @SuppressWarnings("deprecation") 140 public void Test4056591() { 141 try { 142 SimpleDateFormat fmt = new SimpleDateFormat("yyMMdd", Locale.US); 143 Date start = new Date(1809-1900, Calendar.DECEMBER, 25); 144 fmt.set2DigitYearStart(start); 145 if (!fmt.get2DigitYearStart().equals(start)) 146 errln("get2DigitYearStart broken"); 147 Object[] DATA = { 148 "091225", new Date(1809-1900, Calendar.DECEMBER, 25), 149 "091224", new Date(1909-1900, Calendar.DECEMBER, 24), 150 "091226", new Date(1809-1900, Calendar.DECEMBER, 26), 151 "611225", new Date(1861-1900, Calendar.DECEMBER, 25), 152 }; 153 for (int i=0; i<DATA.length; i+=2) { 154 String s = (String) DATA[i]; 155 Date exp = (Date) DATA[i+1]; 156 Date got = fmt.parse(s); 157 logln(s + " -> " + got + "; exp " + exp); 158 if (!got.equals(exp)) errln("set2DigitYearStart broken"); 159 } 160 } 161 catch (ParseException e) { 162 errln("Fail: " + e); 163 e.printStackTrace(); 164 } 165 } 166 167 public void Test4059917() { 168 Locale locale = Locale.getDefault(); 169 if (!TestUtils.usesAsciiDigits(locale)) { 170 logln("Skipping this test because locale is " + locale); 171 return; 172 } 173 174 SimpleDateFormat fmt; 175 String myDate; 176 177 fmt = new SimpleDateFormat( "yyyy/MM/dd" ); 178 myDate = "1997/01/01"; 179 aux917( fmt, myDate ); 180 181 fmt = new SimpleDateFormat( "yyyyMMdd" ); 182 myDate = "19970101"; 183 aux917( fmt, myDate ); 184 } 185 186 void aux917( SimpleDateFormat fmt, String str ) { 187 try { 188 logln( "==================" ); 189 logln( "testIt: pattern=" + fmt.toPattern() + 190 " string=" + str ); 191 192 Object o; 193 o = fmt.parseObject( str ); 194 logln( "Parsed object: " + o ); 195 196 String formatted = fmt.format( o ); 197 logln( "Formatted string: " + formatted ); 198 if (!formatted.equals(str)) errln("Fail: Want " + str + " Got " + formatted); 199 } 200 catch (ParseException e) { 201 errln("Fail: " + e); 202 e.printStackTrace(); 203 } 204 } 205 206 public void Test4060212() { 207 Locale savedLocale = Locale.getDefault(); 208 Locale.setDefault(Locale.US); 209 try { 210 String dateString = "1995-040.05:01:29"; 211 212 logln( "dateString= " + dateString ); 213 logln("Using yyyy-DDD.hh:mm:ss"); 214 SimpleDateFormat formatter = new SimpleDateFormat("yyyy-DDD.hh:mm:ss"); 215 ParsePosition pos = new ParsePosition(0); 216 Date myDate = formatter.parse( dateString, pos ); 217 String myString = DateFormat.getDateTimeInstance( DateFormat.FULL, 218 DateFormat.LONG).format( myDate ); 219 logln( myString ); 220 Calendar cal = new GregorianCalendar(); 221 cal.setTime(myDate); 222 if (cal.get(Calendar.DAY_OF_YEAR) != 40) 223 errln("Fail: Got " + cal.get(Calendar.DAY_OF_YEAR) + 224 " Want 40"); 225 226 logln("Using yyyy-ddd.hh:mm:ss"); 227 formatter = new SimpleDateFormat("yyyy-ddd.hh:mm:ss"); 228 pos = new ParsePosition(0); 229 myDate = formatter.parse( dateString, pos ); 230 myString = DateFormat.getDateTimeInstance( DateFormat.FULL, 231 DateFormat.LONG).format( myDate ); 232 logln( myString ); 233 cal.setTime(myDate); 234 if (cal.get(Calendar.DAY_OF_YEAR) != 40) 235 errln("Fail: Got " + cal.get(Calendar.DAY_OF_YEAR) + 236 " Want 40"); 237 } 238 finally { 239 Locale.setDefault(savedLocale); 240 } 241 } 242 243 public void Test4061287() { 244 SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy"); 245 try { 246 logln(df.parse("35/01/1971").toString()); 247 } 248 catch (ParseException e) { 249 errln("Fail: " + e); 250 e.printStackTrace(); 251 } 252 df.setLenient(false); 253 boolean ok = false; 254 try { 255 logln(df.parse("35/01/1971").toString()); 256 } catch (ParseException e) {ok=true;} 257 if (!ok) errln("Fail: Lenient not working"); 258 } 259 260 @SuppressWarnings("deprecation") 261 public void Test4065240() { 262 Date curDate; 263 DateFormat shortdate, fulldate; 264 String strShortDate, strFullDate; 265 Locale saveLocale = Locale.getDefault(); 266 TimeZone saveZone = TimeZone.getDefault(); 267 try { 268 Locale curLocale = new Locale("de","DE"); 269 Locale.setDefault(curLocale); 270 TimeZone.setDefault(TimeZone.getTimeZone("EST")); 271 curDate = new Date(98, 0, 1); 272 shortdate = DateFormat.getDateInstance(DateFormat.SHORT); 273 fulldate = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG 274 ); 275 strShortDate = new String("The current date (short form) is " + shortdate. 276 format(curDate)); 277 strFullDate = new String("The current date (long form) is " + fulldate.format(curDate)); 278 279 logln(strShortDate); 280 logln(strFullDate); 281 282 // UPDATE THIS AS ZONE NAME RESOURCE FOR <EST> in de_DE is updated 283 if (!strFullDate.endsWith("EST") 284 && !strFullDate.endsWith("GMT-05:00")) { 285 errln("Fail: Want GMT-05:00"); 286 } 287 } 288 finally { 289 Locale.setDefault(saveLocale); 290 TimeZone.setDefault(saveZone); 291 } 292 } 293 294 /* 295 DateFormat.equals is too narrowly defined. As a result, MessageFormat 296 does not work correctly. DateFormat.equals needs to be written so 297 that the Calendar sub-object is not compared using Calendar.equals, 298 but rather compared for equivalency. This may necessitate adding a 299 (package private) method to Calendar to test for equivalency. 300 301 Currently this bug breaks MessageFormat.toPattern 302 */ 303 @SuppressWarnings("deprecation") 304 public void Test4071441() { 305 DateFormat fmtA = DateFormat.getInstance(); 306 DateFormat fmtB = DateFormat.getInstance(); 307 Calendar calA = fmtA.getCalendar(); 308 Calendar calB = fmtB.getCalendar(); 309 Date epoch = new Date(0); 310 Date xmas = new Date(61, Calendar.DECEMBER, 25); 311 calA.setTime(epoch); 312 calB.setTime(epoch); 313 if (!calA.equals(calB)) 314 errln("Fail: Can't complete test; Calendar instances unequal"); 315 if (!fmtA.equals(fmtB)) 316 errln("Fail: DateFormat unequal when Calendars equal"); 317 calB.setTime(xmas); 318 if (calA.equals(calB)) 319 errln("Fail: Can't complete test; Calendar instances equal"); 320 if (!fmtA.equals(fmtB)) 321 errln("Fail: DateFormat unequal when Calendars equivalent"); 322 logln("DateFormat.equals ok"); 323 } 324 325 /* The java.text.DateFormat.parse(String) method expects for the 326 US locale a string formatted according to mm/dd/yy and parses it 327 correctly. 328 329 When given a string mm/dd/yyyy it only parses up to the first 330 two y's, typically resulting in a date in the year 1919. 331 332 Please extend the parsing method(s) to handle strings with 333 four-digit year values (probably also applicable to various 334 other locales. */ 335 public void Test4073003() { 336 try { 337 DateFormat fmt = DateFormat.getDateInstance(DateFormat.SHORT, Locale.US); 338 String[] tests = { "12/25/61", "12/25/1961", "4/3/2010", "4/3/10" }; 339 for (int i=0; i<tests.length; i+=2) { 340 Date d = fmt.parse(tests[i]); 341 Date dd = fmt.parse(tests[i+1]); 342 String s = fmt.format(d); 343 String ss = fmt.format(dd); 344 if (!d.equals(dd)) 345 errln("Fail: " + d + " != " + dd); 346 if (!s.equals(ss)) 347 errln("Fail: " + s + " != " + ss); 348 logln("Ok: " + s + " " + d); 349 } 350 } 351 catch (ParseException e) { 352 errln("Fail: " + e); 353 e.printStackTrace(); 354 } 355 } 356 357 public void Test4089106() { 358 TimeZone def = TimeZone.getDefault(); 359 try { 360 TimeZone z = new SimpleTimeZone((int)(1.25 * 3600000), "FAKEZONE"); 361 TimeZone.setDefault(z); 362 SimpleDateFormat f = new SimpleDateFormat(); 363 if (!f.getTimeZone().equals(z)) 364 errln("Fail: SimpleTimeZone should use TimeZone.getDefault()"); 365 } 366 finally { 367 TimeZone.setDefault(def); 368 } 369 } 370 371 public void Test4100302() { 372 Locale[] locales = new Locale[] { 373 Locale.CANADA, 374 Locale.CANADA_FRENCH, 375 Locale.CHINA, 376 Locale.CHINESE, 377 Locale.ENGLISH, 378 Locale.FRANCE, 379 Locale.FRENCH, 380 Locale.GERMAN, 381 Locale.GERMANY, 382 Locale.ITALIAN, 383 Locale.ITALY, 384 Locale.JAPAN, 385 Locale.JAPANESE, 386 Locale.KOREA, 387 Locale.KOREAN, 388 Locale.PRC, 389 Locale.SIMPLIFIED_CHINESE, 390 Locale.TAIWAN, 391 Locale.TRADITIONAL_CHINESE, 392 Locale.UK, 393 Locale.US 394 }; 395 try { 396 boolean pass = true; 397 for(int i = 0; i < locales.length; i++) { 398 399 Format format = DateFormat.getDateTimeInstance(DateFormat.FULL, 400 DateFormat.FULL, locales[i]); 401 byte[] bytes; 402 403 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 404 ObjectOutputStream oos = new ObjectOutputStream(baos); 405 406 oos.writeObject(format); 407 oos.flush(); 408 409 baos.close(); 410 bytes = baos.toByteArray(); 411 412 ObjectInputStream ois = 413 new ObjectInputStream(new ByteArrayInputStream(bytes)); 414 415 if (!format.equals(ois.readObject())) { 416 pass = false; 417 logln("DateFormat instance for locale " + 418 locales[i] + " is incorrectly serialized/deserialized."); 419 } else { 420 logln("DateFormat instance for locale " + 421 locales[i] + " is OKAY."); 422 } 423 } 424 if (!pass) errln("Fail: DateFormat serialization/equality bug"); 425 } 426 catch (IOException e) { 427 errln("Fail: " + e); 428 e.printStackTrace(); 429 } 430 catch (ClassNotFoundException e) { 431 errln("Fail: " + e); 432 e.printStackTrace(); 433 } 434 } 435 436 /** 437 * Test whether DataFormat can be serialized/deserialized correctly 438 * even if invalid/customized TimeZone is used. 439 */ 440 public void Test4413980() { 441 TimeZone savedTimeZone = TimeZone.getDefault(); 442 try { 443 boolean pass = true; 444 String[] IDs = new String[] {"Undefined", "PST", "US/Pacific", 445 "GMT+3:00", "GMT-01:30"}; 446 for (int i = 0; i < IDs.length; i++) { 447 TimeZone tz = TimeZone.getTimeZone(IDs[i]); 448 TimeZone.setDefault(tz); 449 450 Format format = DateFormat.getDateTimeInstance(DateFormat.FULL, 451 DateFormat.FULL); 452 byte[] bytes; 453 454 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 455 ObjectOutputStream oos = new ObjectOutputStream(baos); 456 457 oos.writeObject(format); 458 oos.flush(); 459 460 baos.close(); 461 bytes = baos.toByteArray(); 462 463 ObjectInputStream ois = 464 new ObjectInputStream(new ByteArrayInputStream(bytes)); 465 466 if (!format.equals(ois.readObject())) { 467 pass = false; 468 logln("DateFormat instance which uses TimeZone <" + 469 IDs[i] + "> is incorrectly serialized/deserialized."); 470 } else { 471 logln("DateFormat instance which uses TimeZone <" + 472 IDs[i] + "> is correctly serialized/deserialized."); 473 } 474 } 475 if (!pass) { 476 errln("Fail: DateFormat serialization/equality bug"); 477 } 478 } 479 catch (IOException e) { 480 errln("Fail: " + e); 481 e.printStackTrace(); 482 } 483 catch (ClassNotFoundException e) { 484 errln("Fail: " + e); 485 e.printStackTrace(); 486 } 487 finally { 488 TimeZone.setDefault(savedTimeZone); 489 } 490 } 491 492 public void Test4101483() { 493 SimpleDateFormat sdf = new SimpleDateFormat("z", Locale.US); 494 FieldPosition fp = new FieldPosition(DateFormat.TIMEZONE_FIELD); 495 @SuppressWarnings("deprecation") 496 Date d= new Date(9234567890L); 497 StringBuffer buf = new StringBuffer(""); 498 logln(sdf.format(d, buf, fp).toString()); 499 logln(d + " => " + buf); 500 logln("beginIndex = " + fp.getBeginIndex()); 501 logln("endIndex = " + fp.getEndIndex()); 502 if (fp.getBeginIndex() == fp.getEndIndex()) errln("Fail: Empty field"); 503 } 504 505 /** 506 * Bug 4103340 507 * Bug 4138203 508 * This bug really only works in Locale.US, since that's what the locale 509 * used for Date.toString() is. Bug 4138203 reports that it fails on Korean 510 * NT; it would actually have failed on any non-US locale. Now it should 511 * work on all locales. 512 */ 513 public void Test4103340() { 514 // choose a date that is the FIRST of some month 515 // and some arbitrary time 516 @SuppressWarnings("deprecation") 517 Date d=new Date(97, 3, 1, 1, 1, 1); 518 SimpleDateFormat df=new SimpleDateFormat("MMMM", Locale.US); 519 520 String s = d.toString(); 521 String s2 = df.format(d); 522 logln("Date="+s); 523 logln("DF="+s2); 524 if (s.indexOf(s2.substring(0,2)) == -1) 525 errln("Months should match"); 526 } 527 528 public void Test4103341() { 529 TimeZone saveZone =TimeZone.getDefault(); 530 try { 531 TimeZone.setDefault(TimeZone.getTimeZone("CST")); 532 SimpleDateFormat simple = new SimpleDateFormat("MM/dd/yyyy HH:mm"); 533 if (!simple.getTimeZone().equals(TimeZone.getDefault())) 534 errln("Fail: SimpleDateFormat not using default zone"); 535 } 536 finally { 537 TimeZone.setDefault(saveZone); 538 } 539 } 540 541 public void Test4104136() { 542 SimpleDateFormat sdf = new SimpleDateFormat(); 543 String pattern = "'time' hh:mm"; 544 sdf.applyPattern(pattern); 545 logln("pattern: \"" + pattern + "\""); 546 547 @SuppressWarnings("deprecation") 548 Object[] DATA = { 549 "time 10:30", new ParsePosition(10), new Date(70, Calendar.JANUARY, 1, 10, 30), 550 "time 10:x", new ParsePosition(0), null, 551 "time 10x", new ParsePosition(0), null, 552 }; 553 for (int i=0; i<DATA.length; i+=3) { 554 String text = (String) DATA[i]; 555 ParsePosition finish = (ParsePosition) DATA[i+1]; 556 Date exp = (Date) DATA[i+2]; 557 558 ParsePosition pos = new ParsePosition(0); 559 Date d = sdf.parse(text, pos); 560 logln(" text: \"" + text + "\""); 561 logln(" index: " + pos.getIndex()); 562 logln(" result: " + d); 563 if (pos.getIndex() != finish.getIndex()) 564 errln("Fail: Expected pos " + finish.getIndex()); 565 if (!((d == null && exp == null) || 566 d.equals(exp))) 567 errln("Fail: Expected result " + exp); 568 } 569 } 570 571 /** 572 * CANNOT REPRODUCE 573 * According to the bug report, this test should throw a 574 * StringIndexOutOfBoundsException during the second parse. However, 575 * this is not seen. 576 */ 577 public void Test4104522() { 578 SimpleDateFormat sdf = new SimpleDateFormat(); 579 String pattern = "'time' hh:mm"; 580 sdf.applyPattern(pattern); 581 logln("pattern: \"" + pattern + "\""); 582 583 // works correctly 584 ParsePosition pp = new ParsePosition(0); 585 String text = "time "; 586 Date date = sdf.parse(text, pp); 587 logln(" text: \"" + text + "\"" + 588 " date: " + date); 589 590 // works wrong 591 pp = new ParsePosition(0); 592 text = "time"; 593 date = sdf.parse(text, pp); 594 logln(" text: \"" + text + "\"" + 595 " date: " + date); 596 } 597 598 public void Test4106807() { 599 Date date; 600 DateFormat df = DateFormat.getDateTimeInstance(); 601 Object[] data = { 602 new SimpleDateFormat("yyyyMMddHHmmss"), "19980211140000", 603 new SimpleDateFormat("yyyyMMddHHmmss'Z'"), "19980211140000", 604 new SimpleDateFormat("yyyyMMddHHmmss''"), "19980211140000", 605 new SimpleDateFormat("yyyyMMddHHmmss'a''a'"), "19980211140000a", 606 new SimpleDateFormat("yyyyMMddHHmmss %"), "19980211140000 ", 607 }; 608 GregorianCalendar gc = new GregorianCalendar(); 609 TimeZone timeZone = TimeZone.getDefault(); 610 611 TimeZone gmt = (TimeZone)timeZone.clone(); 612 613 gmt.setRawOffset(0); 614 615 for (int i=0; i<data.length; i+=2) { 616 SimpleDateFormat format = (SimpleDateFormat) data[i]; 617 String dateString = (String) data[i+1]; 618 try { 619 format.setTimeZone(gmt); 620 date = format.parse(dateString); 621 logln(df.format(date)); 622 gc.setTime(date); 623 logln("" + gc.get(Calendar.ZONE_OFFSET)); 624 logln(format.format(date)); 625 } 626 catch (ParseException e) { 627 logln("No way Jose"); 628 } 629 } 630 } 631 632 /** 633 * SimpleDateFormat won't parse "GMT" 634 */ 635 public void Test4134203() { 636 String dateFormat = "MM/dd/yy HH:mm:ss zzz"; 637 SimpleDateFormat fmt = new SimpleDateFormat(dateFormat); 638 ParsePosition p0 = new ParsePosition(0); 639 Date d = fmt.parse("01/22/92 04:52:00 GMT", p0); 640 logln(d.toString()); 641 // In the failure case an exception is thrown by parse(); 642 // if no exception is thrown, the test passes. 643 } 644 645 /** 646 * Another format for GMT string parse 647 */ 648 public void Test4266432() { 649 String dateFormat = "MM/dd HH:mm:ss zzz yyyy"; 650 SimpleDateFormat fmt = new SimpleDateFormat(dateFormat); 651 ParsePosition p0 = new ParsePosition(0); 652 Date d = fmt.parse("01/22 04:52:00 GMT 1992", p0); 653 logln(d.toString()); 654 // In the failure case an exception is thrown by parse(); 655 // if no exception is thrown, the test passes. 656 } 657 658 /** 659 * Millisecond field is limited to 3 digits; also test general millisecond 660 * handling. 661 * 662 * NOTE: Updated for fixed semantics as of Kestrel. See 663 * 4253490 664 */ 665 public void Test4148168() throws ParseException { 666 SimpleDateFormat fmt = new SimpleDateFormat("", Locale.US); 667 int ms = 456; 668 String[] PAT = { "S", "SS", "SSS", "SSSS", "SSSSS", 669 "SSSSSSSSSSSSSSSSSSSS" }; 670 String[] OUT = { "456", "456", "456", "0456", "00456", 671 "00000000000000000456" }; 672 Calendar cal = Calendar.getInstance(); 673 cal.clear(); 674 cal.set(Calendar.MILLISECOND, ms); 675 Date d = cal.getTime(); 676 for (int i=0; i<OUT.length; ++i) { 677 fmt.applyPattern(PAT[i]); 678 String str = fmt.format(d); 679 if (!str.equals(OUT[i])) { 680 errln("FAIL: " + ms + " ms x \"" + PAT[i] + "\" -> \"" + 681 str + "\", exp \"" + OUT[i] + '"'); 682 } 683 } 684 685 // Test parsing 686 fmt.applyPattern("s.S"); 687 String[] IN = { "1.4", "1.04", "1.004", "1.45", "1.456", 688 "1.4567", "1.45678" }; 689 int[] MS = { 4, 4, 4, 45, 456, 567, 678 }; 690 for (int i=0; i<IN.length; ++i) { 691 d = fmt.parse(IN[i]); 692 cal.setTime(d); 693 ms = cal.get(Calendar.MILLISECOND); 694 if (ms != MS[i]) { 695 errln("FAIL: parse(\"" + IN[i] + "\" x \"s.S\") -> " + 696 ms + " ms, exp " + MS[i] + " ms"); 697 } 698 } 699 } 700 701 /** 702 * SimpleDateFormat incorrect handling of 2 single quotes in format() 703 */ 704 public void Test4151631() { 705 String pattern = "'TO_DATE('''dd'-'MM'-'yyyy HH:mm:ss''' , ''DD-MM-YYYY HH:MI:SS'')'"; 706 logln("pattern=" + pattern); 707 SimpleDateFormat format = new SimpleDateFormat(pattern, Locale.US); 708 @SuppressWarnings("deprecation") 709 String result = format.format(new Date(1998-1900, Calendar.JUNE, 30, 13, 30, 0)); 710 if (!result.equals("TO_DATE('30-06-1998 13:30:00' , 'DD-MM-YYYY HH:MI:SS')")) { 711 errln("Fail: result=" + result); 712 } 713 else { 714 logln("Pass: result=" + result); 715 } 716 } 717 718 /** 719 * 'z' at end of date format throws index exception in SimpleDateFormat 720 * CANNOT REPRODUCE THIS BUG ON 1.2FCS 721 */ 722 @SuppressWarnings("deprecation") 723 public void Test4151706() { 724 SimpleDateFormat fmt = 725 new SimpleDateFormat("EEEE, dd-MMM-yy HH:mm:ss z", Locale.US); 726 try { 727 Date d = fmt.parse("Thursday, 31-Dec-98 23:00:00 GMT"); 728 if (d.getTime() != Date.UTC(1998-1900, Calendar.DECEMBER, 31, 23, 0, 0)) 729 errln("Incorrect value: " + d); 730 } catch (Exception e) { 731 errln("Fail: " + e); 732 } 733 } 734 735 /** 736 * SimpleDateFormat fails to parse redundant data. 737 * This is actually a bug down in GregorianCalendar, but it was reported 738 * as follows... 739 */ 740 public void Test4153860() throws ParseException { 741 Locale savedLocale = Locale.getDefault(); 742 Locale.setDefault(Locale.US); 743 try { 744 SimpleDateFormat sf = (SimpleDateFormat)DateFormat.getDateTimeInstance(); 745 // Set the pattern 746 sf.applyPattern("yyyy.MM-dd"); 747 // Try to create a Date for February 4th 748 Date d1 = sf.parse("1998.02-04"); 749 // Set the pattern, this time to use the W value 750 sf.applyPattern("yyyy.MM-dd W"); 751 // Try to create a Date for February 4th 752 Date d2 = sf.parse("1998.02-04 1"); 753 if (!d1.equals(d2)) { 754 errln("Parse failed, got " + d2 + 755 ", expected " + d1); 756 } 757 } 758 finally { 759 Locale.setDefault(savedLocale); 760 } 761 } 762 763 /** 764 * Confirm that "EST"(GMT-5:00) and "CST"(GMT-6:00) are used in US 765 * as "EST" or "CST", not Australian "EST" and "CST". 766 */ 767 @SuppressWarnings("deprecation") 768 public void Test4406615() { 769 Locale savedLocale = Locale.getDefault(); 770 TimeZone savedTimeZone = TimeZone.getDefault(); 771 Locale.setDefault(Locale.US); 772 TimeZone.setDefault(TimeZone.getTimeZone("PST")); 773 774 Date d1, d2; 775 String dt = "Mon, 1 Jan 2001 00:00:00"; 776 SimpleDateFormat sdf = 777 new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z"); 778 779 try { 780 d1 = sdf.parse(dt+" EST"); 781 d2 = sdf.parse(dt+" CST"); 782 783 if (d1.getYear() != (2000-1900) || d1.getMonth() != 11 || 784 d1.getDate() != 31 || d1.getHours() != 21 || d1.getMinutes() != 0 || 785 d2.getYear() != (2000-1900) || d2.getMonth() != 11 || 786 d2.getDate() != 31 || d2.getHours() != 22 || d2.getMinutes() != 0) { 787 errln("Parse failed, d1 = " + d1 + ", d2 = " + d2); 788 } else { 789 logln("Parse passed"); 790 } 791 } 792 catch (Exception e) { 793 errln("Parse failed, got Exception " + e); 794 } 795 finally { 796 Locale.setDefault(savedLocale); 797 TimeZone.setDefault(savedTimeZone); 798 } 799 } 800 801 /** 802 * Cannot reproduce this bug under 1.2 FCS -- it may be a convoluted duplicate 803 * of some other bug that has been fixed. 804 */ 805 public void Test4162071() { 806 String dateString = "Thu, 30-Jul-1999 11:51:14 GMT"; 807 String format = "EEE', 'dd-MMM-yyyy HH:mm:ss z"; // RFC 822/1123 808 SimpleDateFormat df = new 809 SimpleDateFormat(format, Locale.US); 810 811 try { 812 Date x = df.parse(dateString); 813 logln("Parse format \"" + format + "\" ok"); 814 logln(dateString + " -> " + df.format(x)); 815 } catch (Exception e) { 816 errln("Parse format \"" + format + "\" failed."); 817 } 818 } 819 820 /** 821 * DateFormat shouldn't parse year "-1" as a two-digit year (e.g., "-1" -> 1999). 822 */ 823 public void Test4182066() { 824 Locale savedLocale = Locale.getDefault(); 825 Locale.setDefault(Locale.US); 826 try { 827 SimpleDateFormat fmt = new SimpleDateFormat("MM/dd/yy", 828 DateFormatSymbols.getInstance(Locale.US)); 829 SimpleDateFormat dispFmt = new SimpleDateFormat("MMM dd yyyy GG", 830 DateFormatSymbols.getInstance(Locale.US)); 831 /* We expect 2-digit year formats to put 2-digit years in the right 832 * window. Out of range years, that is, anything less than "00" or 833 * greater than "99", are treated as literal years. So "1/2/3456" 834 * becomes 3456 AD. Likewise, "1/2/-3" becomes -3 AD == 2 BC. 835 */ 836 @SuppressWarnings("deprecation") 837 Object[] DATA = { 838 "02/29/00", new Date(2000-1900, Calendar.FEBRUARY, 29), 839 "01/23/01", new Date(2001-1900, Calendar.JANUARY, 23), 840 "04/05/-1", new Date( -1-1900, Calendar.APRIL, 5), 841 "01/23/-9", new Date( -9-1900, Calendar.JANUARY, 23), 842 "11/12/1314", new Date(1314-1900, Calendar.NOVEMBER, 12), 843 "10/31/1", new Date( 1-1900, Calendar.OCTOBER, 31), 844 "09/12/+1", null, // "+1" isn't recognized by US NumberFormat 845 "09/12/001", new Date( 1-1900, Calendar.SEPTEMBER,12), 846 }; 847 StringBuffer out = new StringBuffer(); 848 boolean pass = true; 849 for (int i=0; i<DATA.length; i+=2) { 850 String str = (String) DATA[i]; 851 Date expected = (Date) DATA[i+1]; 852 Date actual; 853 try { 854 actual = fmt.parse(str); 855 } catch (ParseException e) { 856 actual = null; 857 } 858 String actStr = actual != null 859 ? dispFmt.format(actual) : String.valueOf(actual); 860 if (expected == actual 861 || (expected != null && expected.equals(actual))) { 862 out.append(str + " => " + actStr + "\n"); 863 } else { 864 String expStr = expected != null 865 ? dispFmt.format(expected) : String.valueOf(expected); 866 out.append("FAIL: " + str + " => " + actStr 867 + ", expected " + expStr + "\n"); 868 pass = false; 869 } 870 } 871 if (pass) { 872 log(out.toString()); 873 } else { 874 err(out.toString()); 875 } 876 } 877 finally { 878 Locale.setDefault(savedLocale); 879 } 880 } 881 882 /** 883 * Bug 4210209 884 * Bug 4209272 885 * DateFormat cannot parse Feb 29 2000 when setLenient(false) 886 */ 887 public void Test4210209() { 888 String pattern = "MMM d, yyyy"; 889 DateFormat fmt = new SimpleDateFormat(pattern, 890 DateFormatSymbols.getInstance(Locale.US)); 891 fmt.getCalendar().setLenient(false); 892 @SuppressWarnings("deprecation") 893 Date d = new Date(2000-1900, Calendar.FEBRUARY, 29); 894 String s = fmt.format(d); 895 logln(d + " x " + pattern + " => " + s); 896 ParsePosition pos = new ParsePosition(0); 897 d = fmt.parse(s, pos); 898 logln(d + " <= " + pattern + " x " + s); 899 logln("Parse pos = " + pos); 900 if (pos.getErrorIndex() != -1) { 901 errln("FAIL"); 902 } 903 904 // The underlying bug is in GregorianCalendar. If the following lines 905 // succeed, the bug is fixed. If the bug isn't fixed, they will throw 906 // an exception. 907 GregorianCalendar cal = new GregorianCalendar(); 908 cal.clear(); 909 cal.setLenient(false); 910 cal.set(2000, Calendar.FEBRUARY, 29); // This should work! 911 logln(cal.getTime().toString()); 912 } 913 914 /** 915 * DateFormat.getDateTimeInstance() allows illegal parameters. 916 */ 917 public void Test4213086() { 918 int[] DATA = { 919 // Style value, 0/1 for illegal/legal 920 -99, 0, 921 -1, 0, 922 0, 1, 923 1, 1, 924 2, 1, 925 3, 1, 926 4, 0, 927 99, 0, 928 }; 929 String[] DESC = { 930 "getDateTimeInstance(date)", 931 "getDateTimeInstance(time)", 932 "getDateInstance", 933 "getTimeInstance", 934 }; 935 String[] GOT = { 936 "disallowed", "allowed", "<invalid>" 937 }; 938 for (int i=0; i<DATA.length; i+=2) { 939 int got = 2; 940 for (int j=0; j<4; ++j) { 941 Exception e = null; 942 try { 943 DateFormat df; 944 switch (j) { 945 case 0: 946 df = DateFormat.getDateTimeInstance(DATA[i], 0); 947 break; 948 case 1: 949 df = DateFormat.getDateTimeInstance(0, DATA[i]); 950 break; 951 case 2: 952 df = DateFormat.getDateInstance(DATA[i]); 953 break; 954 case 3: 955 df = DateFormat.getTimeInstance(DATA[i]); 956 break; 957 } 958 got = 1; 959 } catch (IllegalArgumentException iae) { 960 got = 0; 961 } catch (Exception ex) { 962 e = ex; 963 } 964 if (got != DATA[i+1] || e != null) { 965 errln("FAIL: DateFormat." + DESC[j] + " style " + DATA[i] + " " + 966 (e != null ? e.toString() : GOT[got])); 967 } 968 } 969 } 970 } 971 972 @SuppressWarnings("deprecation") 973 public void Test4253490() throws ParseException { 974 SimpleDateFormat fmt = new SimpleDateFormat("S", Locale.US); 975 976 GregorianCalendar cal = new GregorianCalendar(); 977 978 int FORMAT_MS = 12; 979 String[] FORMAT_PAT = { "S", "SS", "SSS", "SSSS" }; 980 String[] FORMAT_TO = { "12", "12", "012", "0012" }; 981 982 String PARSE_PAT = "S"; 983 String[] PARSE_STR = { "1", "12", "125", "1250" }; 984 int[] PARSE_TO = { 1, 12, 125, 250 }; 985 String PARSE_LPAT = "SSSSS"; 986 987 // Test formatting. We want to make sure all digits are output 988 // and that they are zero-padded on the left if necessary. 989 cal.setTime(new Date(0L)); 990 cal.set(Calendar.MILLISECOND, FORMAT_MS); 991 Date d = cal.getTime(); 992 for (int i=0; i<FORMAT_PAT.length; ++i) { 993 fmt.applyPattern(FORMAT_PAT[i]); 994 String s = fmt.format(d); 995 if (s.equals(FORMAT_TO[i])) { 996 logln(String.valueOf(FORMAT_MS) + " ms f* \"" + 997 FORMAT_PAT[i] + "\" -> \"" + s + '"'); 998 } else { 999 errln("FAIL: " + FORMAT_MS + " ms f* \"" + 1000 FORMAT_PAT[i] + "\" -> \"" + s + "\", expect \"" + 1001 FORMAT_TO[i] + '"'); 1002 } 1003 } 1004 1005 // Test parsing. We want to make sure all digits are read. 1006 fmt.applyPattern(PARSE_PAT); 1007 for (int i=0; i<PARSE_STR.length; ++i) { 1008 cal.setTime(fmt.parse(PARSE_STR[i])); 1009 int ms = cal.get(Calendar.MILLISECOND); 1010 if (ms == PARSE_TO[i]) { 1011 logln("\"" + PARSE_STR[i] + "\" p* \"" + 1012 PARSE_PAT + "\" -> " + ms + " ms"); 1013 } else { 1014 errln("FAIL: \"" + PARSE_STR[i] + "\" p* \"" + 1015 PARSE_PAT + "\" -> " + ms + " ms, expect " + 1016 PARSE_TO[i] + " ms"); 1017 } 1018 } 1019 1020 // Test LONG parsing. We want to make sure all digits are read. 1021 fmt.applyPattern(PARSE_LPAT); 1022 for (int i=0; i<PARSE_STR.length; ++i) { 1023 cal.setTime(fmt.parse(PARSE_STR[i])); 1024 int ms = cal.get(Calendar.MILLISECOND); 1025 if (ms == PARSE_TO[i]) { 1026 logln("\"" + PARSE_STR[i] + "\" p* \"" + 1027 PARSE_LPAT + "\" -> " + ms + " ms"); 1028 } else { 1029 errln("FAIL: \"" + PARSE_STR[i] + "\" p* \"" + 1030 PARSE_LPAT + "\" -> " + ms + " ms, expect " + 1031 PARSE_TO[i] + " ms"); 1032 } 1033 } 1034 } 1035 1036 /** 1037 * Bug in handling of time instance; introduces in fix for 4213086. 1038 */ 1039 public void Test4250359() { 1040 DateFormat df = DateFormat.getTimeInstance(DateFormat.SHORT, 1041 Locale.US); 1042 @SuppressWarnings("deprecation") 1043 Date d = new Date(1999-1900, Calendar.DECEMBER, 25, 1044 1, 2, 3); 1045 String s = df.format(d); 1046 // If the bug is present, we see "1:02 AM 1:02 AM". 1047 // Look for more than one instance of "AM". 1048 int i = s.indexOf("AM"); 1049 int j = s.indexOf("AM", i+1); 1050 if (i < 0 || j >= 0) { 1051 errln("FAIL: getTimeInstance().format(d) => \"" + 1052 s + "\""); 1053 } 1054 } 1055 1056 /** 1057 * Test whether SimpleDataFormat (DateFormatSymbols) can format/parse 1058 * non-localized time zones. 1059 */ 1060 public void Test4261506() { 1061 Locale savedLocale = Locale.getDefault(); 1062 TimeZone savedTimeZone = TimeZone.getDefault(); 1063 Locale.setDefault(Locale.JAPAN); 1064 1065 // XXX: Test assumes "PST" is not TimeZoneNames_ja. Need to 1066 // pick up another time zone when L10N is done to that file. 1067 TimeZone.setDefault(TimeZone.getTimeZone("PST")); 1068 SimpleDateFormat fmt = new SimpleDateFormat("yy/MM/dd hh:ss zzz", Locale.JAPAN); 1069 @SuppressWarnings("deprecation") 1070 String result = fmt.format(new Date(1999, 0, 1)); 1071 logln("format()=>" + result); 1072 if (!result.endsWith("PST")) { 1073 errln("FAIL: SimpleDataFormat.format() did not retrun PST"); 1074 } 1075 1076 Date d = null; 1077 try { 1078 d = fmt.parse("99/1/1 10:10 PST"); 1079 } catch (ParseException e) { 1080 errln("FAIL: SimpleDataFormat.parse() could not parse PST"); 1081 } 1082 1083 result = fmt.format(d); 1084 logln("roundtrip:" + result); 1085 if (!result.equals("99/01/01 10:10 PST")) { 1086 errln("FAIL: SimpleDataFomat timezone roundtrip failed"); 1087 } 1088 1089 Locale.setDefault(savedLocale); 1090 TimeZone.setDefault(savedTimeZone); 1091 } 1092 1093 } 1094 1095 //eof