< prev index next >

test/jdk/java/text/Format/DateFormat/DateFormatTest.java

Print this page

   1 /*
   2  * Copyright (c) 1997, 2022, 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 /**
  25  * @test
  26  * @bug 4052223 4089987 4469904 4326988 4486735 8008577 8045998 8140571
  27  *      8190748 8216969
  28  * @summary test DateFormat and SimpleDateFormat.
  29  * @library /java/text/testlib
  30  * @modules jdk.localedata
  31  * @run main/othervm -Djava.locale.providers=COMPAT,SPI DateFormatTest
  32  */
  33 
  34 import java.util.*;
  35 import java.text.*;
  36 import static java.util.GregorianCalendar.*;
  37 
  38 public class DateFormatTest extends IntlTest





  39 {
  40     public static void main(String[] args) throws Exception {
  41         Locale reservedLocale = Locale.getDefault();
  42         try {
  43             Locale.setDefault(Locale.US);
  44             new DateFormatTest().run(args);
  45         } finally {
  46             // restore the reserved locale
  47             Locale.setDefault(reservedLocale);
  48         }
  49     }
  50 
  51     // Test 4 digit year parsing with pattern "yy"
  52     @SuppressWarnings("deprecation")

  53     public void TestYearParsing()
  54     {
  55         String str = "7/Sep/2001";
  56         Date exp = new Date(2001-1900, SEPTEMBER, 7);
  57         String pat = "d/MMM/yy";
  58         SimpleDateFormat sdf = new SimpleDateFormat(pat, Locale.US);
  59         try {
  60             Date d = sdf.parse(str);
  61             logln(str + " parses with " + pat + " to " + d);
  62             if (d.getTime() != exp.getTime()) {
  63                 errln("FAIL: Expected " + exp);
  64             }
  65         }
  66         catch (ParseException e) {
  67             errln(str + " parse fails with " + pat);
  68         }
  69     }
  70 
  71     // Test written by Wally Wedel and emailed to me.

  72     public void TestWallyWedel()
  73     {
  74         /*
  75          * Instantiate a TimeZone so we can get the ids.
  76          */
  77         TimeZone tz = new SimpleTimeZone(7,"");
  78         /*
  79          * Computational variables.
  80          */
  81         int offset, hours, minutes;
  82         /*
  83          * Instantiate a SimpleDateFormat set up to produce a full time
  84          zone name.
  85          */
  86         SimpleDateFormat sdf = new SimpleDateFormat("zzzz");
  87         /*
  88          * A String array for the time zone ids.
  89          */
  90         String[] ids = TimeZone.getAvailableIDs();
  91         /*
  92          * How many ids do we have?
  93          */
  94         logln("Time Zone IDs size: " + ids.length);
  95         /*
  96          * Column headings (sort of)
  97          */
  98         logln("Ordinal ID offset(h:m) name");
  99         /*
 100          * Loop through the tzs.
 101          */
 102         Date today = new Date();
 103         Calendar cal = Calendar.getInstance();
 104         for (int i = 0; i < ids.length; i++) {
 105             // logln(i + " " + ids[i]);
 106             TimeZone ttz = TimeZone.getTimeZone(ids[i]);
 107             // offset = ttz.getRawOffset();
 108             cal.setTimeZone(ttz);
 109             cal.setTime(today);
 110             offset = cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET);
 111             // logln(i + " " + ids[i] + " offset " + offset);
 112             char sign = '+';
 113             if (offset < 0) { sign = '-'; offset = -offset; }
 114             hours = offset/3600000;
 115             minutes = (offset%3600000)/60000;
 116             String dstOffset = "" + sign + (hours < 10 ? "0" : "") +
 117                 hours + ':' + (minutes < 10 ? "0" : "") + minutes;
 118             /*
 119              * Instantiate a date so we can display the time zone name.
 120              */
 121             sdf.setTimeZone(ttz);
 122             /*
 123              * Format the output.
 124              */
 125             StringBuffer tzS = new StringBuffer();
 126             sdf.format(today,tzS, new FieldPosition(0));
 127             String fmtOffset = tzS.toString();
 128             String fmtDstOffset = null;
 129             if (fmtOffset.startsWith("GMT"))
 130             {
 131                 fmtDstOffset = fmtOffset.substring(3);
 132             }
 133             /*
 134              * Show our result.
 135              */
 136             boolean ok = fmtDstOffset == null || fmtDstOffset.equals(dstOffset);
 137             if (ok)
 138             {
 139                 logln(i + " " + ids[i] + " " + dstOffset +
 140                       " " + fmtOffset +
 141                       (fmtDstOffset != null ? " ok" : " ?"));
 142             }
 143             else
 144             {
 145                 errln(i + " " + ids[i] + " " + dstOffset +
 146                       " " + fmtOffset + " *** FAIL ***");
 147             }
 148         }
 149     }
 150 
 151     // Test equals

 152     public void TestEquals()
 153     {
 154         DateFormat fmtA = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.FULL);
 155 
 156         DateFormat fmtB = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.FULL);
 157 
 158         if (!fmtA.equals(fmtB)) {
 159             errln("FAIL");
 160         }
 161     }
 162 
 163     // Check out some specific parsing problem
 164     @SuppressWarnings("deprecation")

 165     public void TestTwoDigitYearDSTParse()
 166     {
 167         SimpleDateFormat fullFmt =
 168             new SimpleDateFormat("EEE MMM dd HH:mm:ss.SSS zzz yyyy G");
 169 
 170         //DateFormat fmt = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.FULL,
 171         //                                                Locale.ENGLISH);
 172         SimpleDateFormat fmt = new SimpleDateFormat("dd-MMM-yy h:mm:ss 'o''clock' a z",
 173                                                     Locale.ENGLISH);
 174         //Date date = new Date(2004-1900, Calendar.APRIL, 3, 2, 20, 47);
 175         //logln(fmt.format(date)); // This shows what the current locale format is
 176         //logln(((SimpleDateFormat)fmt).toPattern());
 177         TimeZone save = TimeZone.getDefault();
 178         TimeZone PST  = TimeZone.getTimeZone("PST");
 179         String s = "03-Apr-04 2:20:47 o'clock AM PST";
 180         int hour = 2;
 181         try {
 182             TimeZone.setDefault(PST);
 183             Date d = fmt.parse(s);
 184             logln(s + " P> " + fullFmt.format(d));
 185             if (d.getHours() != hour) {
 186                 errln("FAIL: Should parse to hour " + hour);
 187             }
 188         }
 189         catch (ParseException e) { errln("FAIL: " + e.getMessage()); }
 190         finally {
 191             TimeZone.setDefault(save);
 192         }
 193     }
 194 
 195     static String escape(String s)
 196     {
 197         StringBuilder buf = new StringBuilder();
 198         for (int i=0; i<s.length(); ++i)
 199         {
 200             char c = s.charAt(i);
 201             if (c <= (char)0x7F) {
 202                 buf.append(c);
 203             } else {
 204                 buf.append("\\u");
 205                 buf.append(Integer.toHexString((c & 0xF000) >> 12));
 206                 buf.append(Integer.toHexString((c & 0x0F00) >> 8));
 207                 buf.append(Integer.toHexString((c & 0x00F0) >> 4));
 208                 buf.append(Integer.toHexString(c & 0x000F));
 209             }

 217         "WEEK_OF_YEAR_FIELD", "WEEK_OF_MONTH_FIELD", "DATE_FIELD",
 218         "DAY_OF_YEAR_FIELD", "DAY_OF_WEEK_FIELD", "DAY_OF_WEEK_IN_MONTH_FIELD",
 219         "AM_PM_FIELD", "HOUR0_FIELD", "HOUR1_FIELD",
 220         "HOUR_OF_DAY0_FIELD", "HOUR_OF_DAY1_FIELD",
 221         "MINUTE_FIELD", "SECOND_FIELD",
 222         "MILLISECOND_FIELD", "TIMEZONE_FIELD",
 223     };
 224     static int fieldIDs[] = {
 225         DateFormat.ERA_FIELD, DateFormat.YEAR_FIELD, DateFormat.MONTH_FIELD,
 226         DateFormat.WEEK_OF_YEAR_FIELD, DateFormat.WEEK_OF_MONTH_FIELD, DateFormat.DATE_FIELD,
 227         DateFormat.DAY_OF_YEAR_FIELD, DateFormat.DAY_OF_WEEK_FIELD, DateFormat.DAY_OF_WEEK_IN_MONTH_FIELD,
 228         DateFormat.AM_PM_FIELD, DateFormat.HOUR0_FIELD, DateFormat.HOUR1_FIELD,
 229         DateFormat.HOUR_OF_DAY0_FIELD, DateFormat.HOUR_OF_DAY1_FIELD,
 230         DateFormat.MINUTE_FIELD, DateFormat.SECOND_FIELD,
 231         DateFormat.MILLISECOND_FIELD, DateFormat.TIMEZONE_FIELD,
 232     };
 233 
 234     /**
 235      * Bug 4089987
 236      */

 237     public void TestFieldPosition()
 238     {
 239         DateFormat[] dateFormats = {
 240             DateFormat.getDateTimeInstance(DateFormat.FULL,DateFormat.FULL,
 241                                            Locale.US),
 242 
 243             DateFormat.getDateTimeInstance(DateFormat.FULL,DateFormat.FULL,Locale.FRANCE),
 244             new SimpleDateFormat("G, y, M, d, k, H, m, s, S, E, D, F, w, W, a, h, K, z"),
 245             new SimpleDateFormat("G, yy, M, d, k, H, m, s, S, E, D, F, w, W, a, h, K, z"),
 246             new SimpleDateFormat( "GGGG, yyyy, MMMM, dddd, kkkk, HHHH, mmmm, ssss, " +
 247                                   "SSSS, EEEE, DDDD, " +
 248                                   "FFFF, wwww, WWWW, aaaa, hhhh, KKKK, zzzz")
 249         };
 250         String[] expected =
 251         {
 252             "", "1997", "August", "", "", "13", "", "Wednesday", "",
 253             "PM", "", "2", "", "", "34", "12", "", "PDT",
 254 
 255             "", "1997", "ao\u00FBt", "", "", "13", "", "mercredi", "", "",
 256             "", "", "14", "", "34", "", "", "PDT" /*"GMT-07:00"*/,
 257 
 258             "AD", "1997", "8", "33", "3", "13", "225", "Wed", "2", "PM",
 259             "2", "2", "14", "14", "34", "12", "513", "PDT",
 260 
 261             "AD", "97", "8", "33", "3", "13", "225", "Wed", "2", "PM",
 262             "2", "2", "14", "14", "34", "12", "513", "PDT",
 263 
 264             "AD", "1997", "August", "0033", "0003", "0013", "0225",
 265             "Wednesday", "0002", "PM", "0002", "0002", "0014", "0014",
 266             "0034", "0012", "0513", "Pacific Daylight Time",
 267         };
 268         Date someDate = new Date(871508052513L);
 269         TimeZone PST = TimeZone.getTimeZone("PST");
 270         for (int j = 0, exp = 0; j < dateFormats.length; ++j) {
 271             DateFormat df = dateFormats[j];
 272             if (!(df instanceof SimpleDateFormat)) {
 273                 continue;
 274             }
 275             df.setTimeZone(PST);
 276             logln(" Pattern = " + ((SimpleDateFormat)df).toPattern());
 277             logln("  Result = " + df.format(someDate));
 278             for (int i = 0; i < fieldIDs.length; ++i)
 279             {
 280                 String field = getFieldText(df, fieldIDs[i], someDate);
 281                 if (!field.equals(expected[exp])) {
 282                     errln("FAIL: field #" + i + " " + fieldNames[i] + " = \"" +
 283                             escape(field) + "\", expected \"" + escape(expected[exp]) + "\"");
 284                 }
 285                 ++exp;
 286             }
 287         }
 288     }
 289     // get the string value for the given field for the given date
 290     static String getFieldText(DateFormat df, int field, Date date)
 291     {
 292         StringBuffer buffer = new StringBuffer();
 293         FieldPosition pos = new FieldPosition(field);
 294         df.format(date, buffer, pos);
 295         return buffer.toString().substring(pos.getBeginIndex(),
 296                                            pos.getEndIndex());
 297     }
 298 
 299     // Test parsing of partial strings
 300     @SuppressWarnings("deprecation")

 301     public void TestPartialParse994()
 302     {
 303         SimpleDateFormat f = new SimpleDateFormat();
 304         Calendar cal = new GregorianCalendar(2014 - 80, JANUARY, 1);
 305         f.set2DigitYearStart(cal.getTime());
 306         tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10:11:42", new Date(97, 1-1, 17, 10, 11, 42));
 307         tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10:", null);
 308         tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10", null);
 309         tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 ", null);
 310         tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17", null);
 311     }
 312 
 313     void tryPat994(SimpleDateFormat format, String pat, String str, Date expected)
 314     {
 315         logln("Pattern \"" + pat + "\"   String \"" + str + "\"");
 316         try {
 317             format.applyPattern(pat);
 318             Date date = format.parse(str);
 319             String f = format.format(date);
 320             logln(" parse(" + str + ") -> " + date.toString());
 321             logln(" format -> " + f);
 322             if (expected == null ||
 323                 !date.equals(expected)) {
 324                 errln("FAIL: Expected " + expected);
 325             }
 326             if (!f.equals(str)) {
 327                 errln("FAIL: Expected " + str);
 328             }
 329         }
 330         catch(ParseException e) {
 331             logln("ParseException: " + e.getMessage());
 332             if (expected != null) {
 333                 errln("FAIL: Expected " + expected);
 334             }
 335         }
 336         catch(Exception e) {
 337             errln("*** Exception:");
 338             e.printStackTrace();
 339         }
 340     }
 341 
 342     // Test pattern with runs things together

 343     public void TestRunTogetherPattern985()
 344     {
 345         String format = "yyyyMMddHHmmssSSSzzzz";
 346         String now, then;
 347 
 348         SimpleDateFormat formatter = new SimpleDateFormat(format);
 349 
 350         Date date1 = new Date();
 351         now = formatter.format(date1);
 352 
 353         logln(now);
 354 
 355         ParsePosition pos = new ParsePosition(0);
 356 
 357         Date date2 = formatter.parse(now, pos);
 358         if (date2 == null) {
 359             then = "Parse stopped at " + pos.getIndex();
 360         } else {
 361             then = formatter.format(date2);
 362         }
 363 
 364         logln(then);
 365 
 366         if (!date2.equals(date1)) {
 367             errln("FAIL");
 368         }
 369     }
 370 
 371     // Test patterns which run numbers together
 372     @SuppressWarnings("deprecation")

 373     public void TestRunTogetherPattern917()
 374     {
 375         SimpleDateFormat fmt;
 376         String myDate;
 377 
 378         fmt = new SimpleDateFormat( "yyyy/MM/dd" );
 379         myDate = "1997/02/03";
 380         _testIt917( fmt, myDate, new Date(97, 2-1, 3) );
 381 
 382         fmt = new SimpleDateFormat( "yyyyMMdd" );
 383         myDate = "19970304";
 384         _testIt917( fmt, myDate, new Date(97, 3-1, 4) );
 385 
 386     }
 387     void _testIt917( SimpleDateFormat fmt, String str, Date expected )
 388     {
 389         logln( "pattern=" + fmt.toPattern() + "   string=" + str );
 390 
 391         Object o;
 392         try {
 393             o = fmt.parseObject( str );
 394         } catch( ParseException e ) {
 395             e.printStackTrace();
 396             return;
 397         }
 398         logln( "Parsed object: " + o );
 399         if (!o.equals(expected)) {
 400             errln("FAIL: Expected " + expected);
 401         }
 402 
 403         String formatted = fmt.format( o );
 404         logln( "Formatted string: " + formatted );
 405         if (!formatted.equals(str)) {
 406             errln("FAIL: Expected " + str);
 407         }
 408     }
 409 
 410     // Test Czech month formatting -- this can cause a problem because the June and
 411     // July month names share a common prefix.
 412     @SuppressWarnings("deprecation")

 413     public void TestCzechMonths459()
 414     {
 415         // Use Czech, which has month names with shared prefixes for June and July
 416         DateFormat fmt = DateFormat.getDateInstance(DateFormat.FULL, Locale.of("cs"));
 417         //((SimpleDateFormat)fmt).applyPattern("MMMM d yyyy");
 418         logln("Pattern " + ((SimpleDateFormat)fmt).toPattern());
 419 
 420         Date june = new Date(97, Calendar.JUNE, 15);
 421         Date july = new Date(97, Calendar.JULY, 15);
 422 
 423         String juneStr = fmt.format(june);
 424         String julyStr = fmt.format(july);
 425 
 426         try {
 427             logln("format(June 15 1997) = " + juneStr);
 428             Date d = fmt.parse(juneStr);
 429             String s = fmt.format(d);
 430             int month = d.getMonth();
 431             logln("  -> parse -> " + s + " (month = " + month + ")");
 432             if (month != JUNE) {
 433                 errln("FAIL: Month should be June");
 434             }
 435 
 436             logln("format(July 15 1997) = " + julyStr);
 437             d = fmt.parse(julyStr);
 438             s = fmt.format(d);
 439             month = d.getMonth();
 440             logln("  -> parse -> " + s + " (month = " + month + ")");
 441             if (month != JULY) {
 442                 errln("FAIL: Month should be July");
 443             }
 444         }
 445         catch (ParseException e) {
 446             errln("Exception: " + e);
 447         }
 448     }
 449 
 450     // Test big D (day of year) versus little d (day of month)
 451     @SuppressWarnings("deprecation")

 452     public void TestLetterDPattern212()
 453     {
 454         String dateString = "1995-040.05:01:29";
 455         String bigD = "yyyy-DDD.hh:mm:ss";
 456         String littleD = "yyyy-ddd.hh:mm:ss";
 457         Date expLittleD = new Date(95, 0, 1, 5, 1, 29);
 458         Date expBigD =  new Date(expLittleD.getTime() + 39*24*3600000L); // 39 days
 459         expLittleD = expBigD; // Expect the same, with default lenient parsing
 460         logln( "dateString= " + dateString );
 461         SimpleDateFormat formatter = new SimpleDateFormat(bigD);
 462         ParsePosition pos = new ParsePosition(0);
 463         Date myDate = formatter.parse( dateString, pos );
 464         logln("Using " + bigD + " -> " + myDate);
 465         if (myDate.getTime() != expBigD.getTime()) {
 466             errln("FAIL: Expected " + expBigD + " got " + myDate);
 467         }
 468 
 469         formatter = new SimpleDateFormat(littleD);
 470         pos = new ParsePosition(0);
 471         myDate = formatter.parse( dateString, pos );
 472         logln("Using " + littleD + " -> " + myDate);
 473         if (myDate.getTime() != expLittleD.getTime()) {
 474             errln("FAIL: Expected " + expLittleD + " got " + myDate);
 475         }
 476     }
 477 
 478     // Test the 'G' day of year pattern
 479     @SuppressWarnings("deprecation")

 480     public void TestDayOfYearPattern195()
 481     {
 482         Date today = new Date();
 483         Date expected = new Date(today.getYear(), today.getMonth(), today.getDate());
 484 
 485         logln("Test Date: " + today);
 486 
 487         SimpleDateFormat sdf =
 488             (SimpleDateFormat)SimpleDateFormat.getDateInstance();
 489 
 490         tryPattern(sdf, today, null, expected);
 491         tryPattern(sdf, today, "G yyyy DDD", expected);
 492     }
 493 
 494     void tryPattern(SimpleDateFormat sdf, Date d, String pattern, Date expected)
 495     {
 496         if (pattern != null) {
 497             sdf.applyPattern(pattern);
 498         }
 499         logln("pattern: " + sdf.toPattern());
 500 
 501         String formatResult = sdf.format(d);
 502         logln(" format -> " + formatResult);
 503         try {
 504             Date d2 = sdf.parse(formatResult);
 505             logln(" parse(" + formatResult +  ") -> " + d2);
 506             if (d2.getTime() != expected.getTime()) {
 507                 errln("FAIL: Expected " + expected);
 508             }
 509             String format2 = sdf.format(d2);
 510             logln(" format -> " + format2);
 511             if (!formatResult.equals(format2)) {
 512                 errln("FAIL: Round trip drift");
 513             }
 514         }
 515         catch(Exception e) {
 516             errln("Error: " + e.getMessage());
 517         }
 518     }
 519 
 520     // Test a pattern with single quotes
 521     @SuppressWarnings("deprecation")

 522     public void TestQuotePattern161()
 523     {
 524         // This pattern used to end in " zzz" but that makes this test zone-dependent
 525         SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy 'at' hh:mm:ss a zzz");
 526         Date currentTime_1 = new Date(97, Calendar.AUGUST, 13, 10, 42, 28);
 527         String dateString = formatter.format(currentTime_1);
 528         String exp = "08/13/1997 at 10:42:28 AM ";
 529         logln("format(" + currentTime_1 + ") = " + dateString);
 530         if (!dateString.regionMatches(0, exp, 0, exp.length())) {
 531             errln("FAIL: Expected " + exp);
 532         }
 533     }
 534 
 535     // Test the parsing of bad input strings
 536     /** Demonstrates a number of bugs in DateFormat.parse(String) where
 537      *  either StringIndexOutOfBoundsException is thrown or null is
 538      *  returned instead of ParseException. To reproduce, run this program
 539      *  and notice all the "SHOULD NOT HAPPEN" errors.  Note also that the
 540      *  1 line that should be correct is off by 100 years.  (In this day
 541      *  and age, no one would assume that 1/1/00 is Jan 1 1900.)
 542      **/

 543     public void TestBadInput135()
 544     {
 545         int        looks[] = { DateFormat.SHORT, DateFormat.MEDIUM,
 546                                DateFormat.LONG,  DateFormat.FULL };
 547         String     strings[] = { "Mar 15", "Mar 15 1997", "asdf",
 548                                  "3/1/97 1:23:", "3/1/00 1:23:45 AM" };
 549         DateFormat full = DateFormat.getDateTimeInstance(DateFormat.LONG,
 550                                                          DateFormat.LONG);
 551         String expected = "March 1, 2000 1:23:45 AM ";
 552         for ( int i = 0;  i < strings.length;  ++i ){
 553             String text = strings[i];
 554             for ( int j = 0;  j < looks.length;  ++j ){
 555                 int dateLook = looks[j];
 556                 for ( int k = 0;  k < looks.length;  ++k ){
 557                     int timeLook = looks[k];
 558                     DateFormat df = DateFormat.getDateTimeInstance(dateLook, timeLook);
 559                     String prefix = text + ", " + dateLook + "/" + timeLook + ": ";
 560                     try {
 561                         Date when = df.parse(text);
 562                         if ( when == null ){
 563                             errln(prefix +
 564                                   "SHOULD NOT HAPPEN: parse returned null.");
 565                             continue;
 566                         }
 567                         String format = full.format(when);
 568                         logln(prefix + "OK: " + format);
 569                         // Only match the start -- not the zone, which could vary
 570                         if (!format.regionMatches(0, expected, 0, expected.length())) {
 571                             errln("FAIL: Expected " + expected);
 572                         }
 573                     }
 574                     catch ( ParseException e ){
 575                         //errln(prefix + e); // This is expected.
 576                     }
 577                     catch ( StringIndexOutOfBoundsException e ){
 578                         errln(prefix + "SHOULD NOT HAPPEN: " + e);
 579                     }
 580                 }
 581             }
 582         }
 583     }
 584 
 585     final private static String parseFormats[] =
 586     {
 587         "MMMM d, yyyy",  // january 1, 1970 or jan 1, 1970
 588         "MMMM d yyyy",   // january 1 1970 or jan 1 1970
 589         "M/d/yy",        // 1/1/70
 590         "d MMMM, yyyy",  // 1 january, 1970 or 1 jan, 1970
 591         "d MMMM yyyy",   // 1 january 1970 or 1 jan 1970
 592         "d MMMM",        // 1 january or 1 jan
 593         "MMMM d",        // january 1 or jan 1
 594         "yyyy",          // 1970
 595         "h:mm a MMMM d, yyyy" // Date and Time
 596     };
 597     final private static String inputStrings[] =
 598     {
 599         "bogus string",         null, null, null, null, null, null, null, null, null,
 600         "April 1, 1997",        "April 1, 1997", null, null, null, null, null, "April 1", null, null,
 601         "Jan 1, 1970",          "January 1, 1970", null, null, null, null, null, "January 1", null, null,
 602         "Jan 1 2037",           null, "January 1 2037", null, null, null, null, "January 1", null, null,
 603         "1/1/70",               null, null, "1/1/70", null, null, null, null, "0001", null,
 604         "5 May 1997",           null, null, null, null, "5 May 1997", "5 May", null, "0005", null,
 605         "16 May",               null, null, null, null, null, "16 May", null, "0016", null,
 606         "April 30",             null, null, null, null, null, null, "April 30", null, null,
 607         "1998",                 null, null, null, null, null, null, null, "1998", null,
 608         "1",                    null, null, null, null, null, null, null, "0001", null, // Bug620
 609         "3:00 pm Jan 1, 1997",  null, null, null, null, null, null, null, "0003", "3:00 PM January 1, 1997",
 610     };
 611     // More testing of the parsing of bad input
 612     @SuppressWarnings("UnusedAssignment")

 613     public void TestBadInput135a()
 614     {
 615         SimpleDateFormat dateParse = new SimpleDateFormat();
 616         String s;
 617         Date date;
 618         int PFLENGTH = parseFormats.length;
 619 
 620         dateParse.applyPattern("d MMMM, yyyy");
 621         dateParse.setTimeZone(TimeZone.getDefault());
 622         s = "not parseable";
 623         logln("Trying to parse \"" + s + "\" with " + dateParse.toPattern());
 624         try {
 625             date = dateParse.parse(s);
 626             errln("FAIL: Expected exception during parse");
 627         } catch (Exception ex) {
 628             logln("Exception during parse: " + ex); // This is expected
 629         }
 630 
 631         for (int i=0; i<inputStrings.length; i += (PFLENGTH+1))
 632         {
 633             ParsePosition parsePosition = new ParsePosition(0);
 634             s = inputStrings[i];
 635 
 636             for (int index=0; index<PFLENGTH; ++index)
 637             {
 638                 String expected = inputStrings[i + 1 + index];
 639                 dateParse.applyPattern(parseFormats[index]);
 640                 dateParse.setTimeZone(TimeZone.getDefault());
 641                 // logln("Trying to parse \"" + s + "\" with " + dateParse.toPattern());
 642                 try {
 643                     parsePosition.setIndex(0);
 644                     date = dateParse.parse(s, parsePosition);
 645                     if (parsePosition.getIndex() != 0) {
 646                         if (date == null) {
 647                             errln("ERROR: null result with pos " +
 648                                     parsePosition.getIndex() + " " +
 649                                     s.substring(0, parsePosition.getIndex()) + "|" +
 650                                     s.substring(parsePosition.getIndex()));
 651                         } else {
 652                             String result = dateParse.format(date);
 653                             logln("Parsed \"" + s + "\" using \"" + dateParse.toPattern() +
 654                                   "\" to: " + result);
 655                             if (expected == null) {
 656                                 errln("FAIL: Expected parse failure");
 657                             } else if (!expected.equals(result)) {
 658                                 errln("FAIL: Expected " + expected);
 659                             }
 660                         }
 661                     } else {
 662                         // logln("Not parsed.");
 663                         if (expected != null) {
 664                             errln("FAIL: Expected " + expected);
 665                         }
 666                     }
 667                 } catch (Exception ex) {
 668                     errln("An exception was thrown during parse: " + ex);
 669                 }
 670             }
 671         }
 672     }
 673 
 674     // Test the handling of 2-digit dates

 675     public void TestTwoDigitYear() {
 676         SimpleDateFormat fmt = new SimpleDateFormat("M/d/yy");
 677 
 678         // find out the expected 2-digit year values for "6/5/17" and "6/4/34"
 679         long start = fmt.get2DigitYearStart().getTime();
 680         Calendar cal = new Calendar.Builder().setInstant(start).build();
 681         int startYear = cal.get(YEAR);
 682         cal.add(YEAR, 100);
 683         long end = cal.getTimeInMillis();
 684         int endYear = cal.get(YEAR);
 685         int xx17 = 0, xx34 = 0;
 686         for (int year = startYear; year <= endYear; year++) {
 687             int yy = year % 100;
 688             if (yy == 17 && xx17 == 0) {
 689                 xx17 = yearValue(start, end, year, JUNE, 5);
 690             } else if (yy == 34 && xx34 == 0) {
 691                 xx34 = yearValue(start, end, year, JUNE, 4);
 692             }
 693             if (xx17 != 0 && xx34 != 0) {
 694                 break;
 695             }
 696         }
 697         if (xx17 == 0 || xx34 == 0) {
 698             errln("Failed: producing expected values: 2DigitYearStart: " + new Date(start)
 699                   + ", xx17 = " + xx17 + ", xx34 = " + xx34);
 700         }
 701         logln("2DigitYearStart: " + new Date(start) + ", xx17 = " + xx17 + ", xx34 = " + xx34);
 702 
 703         parse2DigitYear(fmt, "6/5/17", new GregorianCalendar(xx17, JUNE, 5).getTime());
 704         parse2DigitYear(fmt, "6/4/34", new GregorianCalendar(xx34, JUNE, 4).getTime());
 705     }
 706 
 707     private int yearValue(long start, long end, int year, int month, int dayOfMonth) {
 708         Calendar cal = new GregorianCalendar(year, month, dayOfMonth);
 709         long time = cal.getTimeInMillis();
 710         return (start <= time && time < end) ? year : 0;
 711     }
 712 
 713     private void parse2DigitYear(SimpleDateFormat fmt, String str, Date expected) {
 714         try {
 715             Date d = fmt.parse(str);
 716             logln("Parsing \"" + str + "\" with " +
 717                   fmt.toPattern() +
 718                   "  => " + d.toString());
 719             if (d.getTime() != expected.getTime()) {
 720                 errln("FAIL: Expected " + expected);
 721             }
 722         } catch (ParseException e) {
 723             errln("FAIL: Got exception");
 724         }
 725     }
 726 
 727     // Test behavior of DateFormat with applied time zone

 728     public void TestDateFormatZone061()
 729     {
 730         Date date;
 731         DateFormat formatter;
 732 
 733         // 25-Mar-97 00:00:00 GMT
 734         date = new Date( 859248000000L );
 735         logln( "Date 1997/3/25 00:00 GMT: " + date );
 736         formatter = new SimpleDateFormat("dd-MMM-yyyyy HH:mm", Locale.UK);
 737         formatter.setTimeZone( TimeZone.getTimeZone( "GMT" ) );
 738 
 739         String temp = formatter.format( date );
 740         logln( "Formatted in GMT to: " + temp );
 741 
 742         /* Parse date string */
 743         try {
 744             Date tempDate = formatter.parse( temp );
 745             logln( "Parsed to: " + tempDate );
 746             if (tempDate.getTime() != date.getTime()) {
 747                 errln("FAIL: Expected " + date);
 748             }
 749         }
 750         catch( Throwable t ) {
 751             errln( "Date Formatter throws: " +
 752                    t.toString() );
 753         }
 754     }
 755 
 756     // Make sure DateFormat uses the correct zone.

 757     public void TestDateFormatZone146()
 758     {
 759         TimeZone saveDefault = TimeZone.getDefault();
 760 
 761         try {
 762             TimeZone thedefault = TimeZone.getTimeZone("GMT");
 763             TimeZone.setDefault(thedefault);
 764             // java.util.Locale.setDefault(new java.util.Locale("ar", "", ""));
 765 
 766             // check to be sure... its GMT all right
 767             TimeZone testdefault = TimeZone.getDefault();
 768             String testtimezone = testdefault.getID();
 769             if (testtimezone.equals("GMT")) {
 770                 logln("Test timezone = " + testtimezone);
 771             } else {
 772                 errln("Test timezone should be GMT, not " + testtimezone);
 773             }
 774 
 775             // now try to use the default GMT time zone
 776             GregorianCalendar greenwichcalendar =
 777                 new GregorianCalendar(1997, 3, 4, 23, 0);
 778             //*****************************greenwichcalendar.setTimeZone(TimeZone.getDefault());
 779             //greenwichcalendar.set(1997, 3, 4, 23, 0);
 780             // try anything to set hour to 23:00 !!!
 781             greenwichcalendar.set(Calendar.HOUR_OF_DAY, 23);
 782             // get time
 783             Date greenwichdate = greenwichcalendar.getTime();
 784             // format every way
 785             String[] DATA = {
 786                 "simple format:  ", "04/04/97 23:00 GMT",
 787                     "MM/dd/yy HH:mm z",
 788                 "full format:    ", "Friday, April 4, 1997 11:00:00 o'clock PM GMT",
 789                     "EEEE, MMMM d, yyyy h:mm:ss 'o''clock' a z",
 790                 "long format:    ", "April 4, 1997 11:00:00 PM GMT",
 791                     "MMMM d, yyyy h:mm:ss a z",
 792                 "default format: ", "04-Apr-97 11:00:00 PM",
 793                     "dd-MMM-yy h:mm:ss a",
 794                 "short format:   ", "4/4/97 11:00 PM",
 795                     "M/d/yy h:mm a",
 796             };
 797 
 798             for (int i=0; i<DATA.length; i+=3) {
 799                 DateFormat fmt = new SimpleDateFormat(DATA[i+2], Locale.ENGLISH);
 800                 fmt.setCalendar(greenwichcalendar);
 801                 String result = fmt.format(greenwichdate);
 802                 logln(DATA[i] + result);
 803                 if (!result.equals(DATA[i+1])) {
 804                     errln("FAIL: Expected " + DATA[i+1]
 805                             + ", got " + result);
 806                 }
 807             }
 808         }
 809         finally {
 810             TimeZone.setDefault(saveDefault);
 811         }
 812     }
 813 
 814 /* HS : Commented out for now, need to be changed not to use hardcoded results.

 815     public void TestLocaleDateFormat() // Bug 495
 816     {
 817         Date testDate = new Date (97, Calendar.SEPTEMBER, 15);
 818         DateFormat dfFrench = DateFormat.getDateTimeInstance(DateFormat.FULL,
 819                                                              DateFormat.FULL, Locale.FRENCH);
 820         DateFormat dfUS = DateFormat.getDateTimeInstance(DateFormat.FULL,
 821                                                          DateFormat.FULL, Locale.US);
 822         String expectedFRENCH = "lundi 15 septembre 1997 00 h 00 GMT-07:00";
 823         String expectedUS = "Monday, September 15, 1997 12:00:00 o'clock AM PDT";
 824         logln("Date set to : " + testDate);
 825         String out = dfFrench.format(testDate);
 826         logln("Date Formated with French Locale " + out);
 827         if (!out.equals(expectedFRENCH)) errln("FAIL: Expected " + expectedFRENCH);
 828         out = dfUS.format(testDate);
 829         logln("Date Formated with US Locale " + out);
 830         if (!out.equals(expectedUS)) errln("FAIL: Expected " + expectedUS);
 831     }
 832 */
 833     /**
 834      * Bug 4056591
 835      */
 836 /*
 837 test commented out pending API-change approval

 838     public void Test2YearStartDate() throws ParseException
 839     {
 840         // create a SimpleDateFormat to test with; dump out if it's not a SimpleDateFormat
 841         DateFormat test = DateFormat.getDateInstance(DateFormat.SHORT, Locale.US);
 842 
 843         if (!(test instanceof SimpleDateFormat)) {
 844             errln("DateFormat.getInstance() didn't return an instance of SimpleDateFormat!");
 845             return;
 846         }
 847 
 848         SimpleDateFormat sdf = (SimpleDateFormat)test;
 849         String testString1 = "3/10/67";
 850         String testString2 = "3/16/43";
 851         String testString3 = "7/21/43";
 852 
 853         // set 2-digit start date to 1/1/1900
 854         Calendar cal = Calendar.getInstance(Locale.US);
 855         cal.set(1900, 0, 1);
 856         sdf.set2DigitStartDate(cal.getTime());
 857 
 858         // check to make sure get2DigitStartDate() returns the value we passed to
 859         // set2DigitStartDate()
 860         Date date = sdf.get2DigitStartDate();
 861         cal.setTime(date);
 862         if (cal.get(Calendar.YEAR) != 1900 || cal.get(Calendar.MONTH) != 0 ||
 863                         cal.get(Calendar.DATE) != 1)
 864             errln("SimpleDateFormat.get2DigitStartDate() returned " + (cal.get(Calendar.MONTH)
 865                         + 1) + "/" + cal.get(Calendar.DATE) + "/" + cal.get(Calendar.YEAR) +
 866                         " instead of 1/1/1900.");
 867 
 868         // try parsing "3/10/67" and "3/16/43" with the 2-digit start date set to 1/1/1900
 869         date = sdf.parse(testString1);
 870         cal.setTime(date);
 871         if (cal.get(Calendar.YEAR) != 1967)
 872             errln("Parsing \"3/10/67\" with 2-digit start date set to 1/1/1900 yielded a year of "
 873                             + cal.get(Calendar.YEAR) + " instead of 1967.");
 874         if (cal.get(Calendar.MONTH) != 2 || cal.get(Calendar.DATE) != 10)
 875             errln("Parsing \"3/10/67\" with 2-digit start date set to 1/1/1900 failed: got " +
 876                             (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DATE) +
 877                             " instead of 3/10.");
 878         date = sdf.parse(testString2);
 879         cal.setTime(date);
 880         if (cal.get(Calendar.YEAR) != 1943)
 881             errln("Parsing \"3/16/43\" with 2-digit start date set to 1/1/1900 yielded a year of "
 882                             + cal.get(Calendar.YEAR) + " instead of 1943.");
 883         if (cal.get(Calendar.MONTH) != 2 || cal.get(Calendar.DATE) != 16)
 884             errln("Parsing \"3/16/43\" with 2-digit start date set to 1/1/1900 failed: got " +
 885                             (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DATE) +
 886                             " instead of 3/16.");
 887 
 888         // try parsing "3/10/67" and "3/16/43" with the 2-digit start date set to 1/1/2000
 889         cal.set(2000, 0, 1);
 890         sdf.set2DigitStartDate(cal.getTime());
 891         date = sdf.parse(testString1);
 892         cal.setTime(date);
 893         if (cal.get(Calendar.YEAR) != 2067)
 894             errln("Parsing \"3/10/67\" with 2-digit start date set to 1/1/2000 yielded a year of "
 895                             + cal.get(Calendar.YEAR) + " instead of 2067.");
 896         if (cal.get(Calendar.MONTH) != 2 || cal.get(Calendar.DATE) != 10)
 897             errln("Parsing \"3/10/67\" with 2-digit start date set to 1/1/2000 failed: got " +
 898                             (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DATE) +
 899                             " instead of 3/10.");
 900         date = sdf.parse(testString2);
 901         cal.setTime(date);
 902         if (cal.get(Calendar.YEAR) != 2043)
 903             errln("Parsing \"3/16/43\" with 2-digit start date set to 1/1/2000 yielded a year of "
 904                             + cal.get(Calendar.YEAR) + " instead of 1943.");
 905         if (cal.get(Calendar.MONTH) != 2 || cal.get(Calendar.DATE) != 16)
 906             errln("Parsing \"3/16/43\" with 2-digit start date set to 1/1/2000 failed: got " +
 907                             (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DATE) +
 908                             " instead of 3/16.");
 909 
 910         // try parsing "3/10/67" and "3/16/43" with the 2-digit start date set to 1/1/1950
 911         cal.set(1950, 0, 1);
 912         sdf.set2DigitStartDate(cal.getTime());
 913         date = sdf.parse(testString1);
 914         cal.setTime(date);
 915         if (cal.get(Calendar.YEAR) != 1967)
 916             errln("Parsing \"3/10/67\" with 2-digit start date set to 1/1/1950 yielded a year of "
 917                             + cal.get(Calendar.YEAR) + " instead of 1967.");
 918         if (cal.get(Calendar.MONTH) != 2 || cal.get(Calendar.DATE) != 10)
 919             errln("Parsing \"3/10/67\" with 2-digit start date set to 1/1/1950 failed: got " +
 920                             (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DATE) +
 921                             " instead of 3/10.");
 922         date = sdf.parse(testString2);
 923         cal.setTime(date);
 924         if (cal.get(Calendar.YEAR) != 2043)
 925             errln("Parsing \"3/16/43\" with 2-digit start date set to 1/1/1950 yielded a year of "
 926                             + cal.get(Calendar.YEAR) + " instead of 1943.");
 927         if (cal.get(Calendar.MONTH) != 2 || cal.get(Calendar.DATE) != 16)
 928             errln("Parsing \"3/16/43\" with 2-digit start date set to 1/1/1950 failed: got " +
 929                             (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DATE) +
 930                             " instead of 3/16.");
 931 
 932         // try parsing "3/16/43" and "7/21/43" with the 2-digit start date set to 6/1/1943
 933         cal.set(1943, 5, 1);
 934         sdf.set2DigitStartDate(cal.getTime());
 935         date = sdf.parse(testString2);
 936         cal.setTime(date);
 937         if (cal.get(Calendar.YEAR) != 2043)
 938             errln("Parsing \"3/16/43\" with 2-digit start date set to 6/1/1943 yielded a year of "
 939                             + cal.get(Calendar.YEAR) + " instead of 2043.");
 940         if (cal.get(Calendar.MONTH) != 2 || cal.get(Calendar.DATE) != 16)
 941             errln("Parsing \"3/16/43\" with 2-digit start date set to 6/1/1943 failed: got " +
 942                             (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DATE) +
 943                             " instead of 3/16.");
 944         date = sdf.parse(testString3);
 945         cal.setTime(date);
 946         if (cal.get(Calendar.YEAR) != 1943)
 947             errln("Parsing \"7/21/43\" with 2-digit start date set to 6/1/1943 yielded a year of "
 948                             + cal.get(Calendar.YEAR) + " instead of 1943.");
 949         if (cal.get(Calendar.MONTH) != 6 || cal.get(Calendar.DATE) != 21)
 950             errln("Parsing \"7/21/43\" with 2-digit start date set to 6/1/1943 failed: got " +
 951                             (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DATE) +
 952                             " instead of 7/21.");
 953 
 954         // and finally, check one more time to make sure get2DigitStartDate() returns the last
 955         // value we passed to set2DigitStartDate()
 956         date = sdf.get2DigitStartDate();
 957         cal.setTime(date);
 958         if (cal.get(Calendar.YEAR) != 1943 || cal.get(Calendar.MONTH) != 5 ||
 959                         cal.get(Calendar.DATE) != 1)
 960             errln("SimpleDateFormat.get2DigitStartDate() returned " + (cal.get(Calendar.MONTH)
 961                         + 1) + "/" + cal.get(Calendar.DATE) + "/" + cal.get(Calendar.YEAR) +
 962                         " instead of 6/1/1943.");
 963     }
 964 */
 965 
 966     /**
 967      * ParsePosition.errorIndex tests.
 968      */
 969     @SuppressWarnings("deprecation")

 970     public void Test4052223()
 971     {
 972         String str = "7/SOS/2001";
 973         Date exp = new Date(101, Calendar.SEPTEMBER, 7);
 974         String pat = "d/MMM/yy";
 975         SimpleDateFormat sdf = new SimpleDateFormat(pat);
 976         ParsePosition pos = new ParsePosition(0);
 977         Date d = sdf.parse(str, pos);
 978         logln(str + " parses with " + pat + " to " + d);
 979         if (d == null && pos.getErrorIndex() == 2) {
 980             logln("Expected null returned, failed at : " + pos.getErrorIndex());
 981         } else {
 982             errln("Failed, parse " + str + " got : " + d + ", index=" + pos.getErrorIndex());
 983         }
 984     }
 985 
 986     /**
 987      * Bug4469904 -- th_TH date format doesn't use Thai B.E.
 988      */

 989     public void TestBuddhistEraBugId4469904() {
 990         String era = "\u0e1e.\u0e28.";
 991         Locale loc = Locale.of("th", "TH");
 992         Calendar cal = Calendar.getInstance(Locale.US);
 993         cal.set(2001, 7, 23);
 994         Date date = cal.getTime();
 995         DateFormat df = DateFormat.getDateInstance(DateFormat.FULL, loc);
 996         String output = df.format(date);
 997         int index = output.indexOf(era);
 998         if (index == -1) {
 999             errln("Test4469904: Failed. Buddhist Era abbrev not present.");
1000         }
1001     }
1002 
1003     /**
1004      * 4326988: API: SimpleDateFormat throws NullPointerException when parsing with null pattern
1005      */
1006     @SuppressWarnings("UnusedAssignment")

1007     public void Test4326988() {
1008         String[] wrongPatterns = {
1009             "hh o''clock",
1010             "hh 'o''clock",     // unterminated quote
1011             "''''''''''''oclock",
1012             "efgxyz",
1013         };
1014         String[] goodPatterns = {
1015             "hh 'o''clock'",
1016             "'''''''''''''o'",
1017             "'efgxyz'",
1018             ":;,.-",
1019         };
1020 
1021         // Check NullPointerException
1022         try {
1023             SimpleDateFormat fmt = new SimpleDateFormat(null);
1024             errln("SimpleDateFormat() doesn't throw NPE with null pattern");
1025         } catch (NullPointerException e) {
1026             // Okay
1027         }
1028         try {
1029             Locale loc = null;
1030             SimpleDateFormat fmt = new SimpleDateFormat("yyyy/MM/dd", loc);
1031             errln("SimpleDateFormat() doesn't throw NPE with null locale");
1032         } catch (NullPointerException e) {
1033             // Okay
1034         }
1035         try {
1036             DateFormatSymbols symbols = null;
1037             SimpleDateFormat fmt = new SimpleDateFormat("yyyy/MM/dd", symbols);
1038             errln("SimpleDateFormat() doesn't throw NPE with null DateFormatSymbols");
1039         } catch (NullPointerException e) {
1040             // Okay
1041         }
1042         try {
1043             SimpleDateFormat fmt = new SimpleDateFormat();
1044             fmt.applyPattern(null);
1045             errln("applyPattern() doesn't throw NPE with null pattern");
1046         } catch (NullPointerException e) {
1047             // Okay
1048         }
1049 
1050         // Check IllegalParameterException
1051         for (int i = 0; i < wrongPatterns.length; i++) {
1052             try {
1053                 SimpleDateFormat fmt = new SimpleDateFormat(wrongPatterns[i]);
1054                 errln("SimpleDateFormat(\"" + wrongPatterns[i] + "\")" +
1055                       " doesn't throw an IllegalArgumentException");
1056             } catch (IllegalArgumentException e) {
1057                 // Okay
1058             }
1059             try {
1060                 SimpleDateFormat fmt = new SimpleDateFormat(wrongPatterns[i],
1061                                                             DateFormatSymbols.getInstance());
1062                 errln("SimpleDateFormat(\"" + wrongPatterns[i] + "\", DateFormatSymbols) doesn't " +
1063                       "throw an IllegalArgumentException");
1064             } catch (IllegalArgumentException e) {
1065                 // Okay
1066             }
1067             try {
1068                 SimpleDateFormat fmt = new SimpleDateFormat(wrongPatterns[i],
1069                                                             Locale.US);
1070                 errln("SimpleDateFormat(\"" + wrongPatterns[i] +
1071                       "\", Locale) doesn't throw an IllegalArgumentException");
1072             } catch (IllegalArgumentException e) {
1073                 // Okay
1074             }
1075             try {
1076                 SimpleDateFormat fmt = new SimpleDateFormat();
1077                 fmt.applyPattern(wrongPatterns[i]);
1078                 errln("SimpleDateFormat.applyPattern(\"" + wrongPatterns[i] +
1079                       "\") doesn't throw an IllegalArgumentException");
1080             } catch (IllegalArgumentException e) {
1081                 // Okay
1082             }
1083         }
1084 
1085         for (int i = 0; i < goodPatterns.length; i++) {
1086             SimpleDateFormat fmt;
1087             fmt = new SimpleDateFormat(goodPatterns[i]);
1088             fmt = new SimpleDateFormat(goodPatterns[i],
1089                                        DateFormatSymbols.getInstance());
1090             fmt = new SimpleDateFormat(goodPatterns[i],
1091                                        Locale.US);
1092             fmt = new SimpleDateFormat();
1093             fmt.applyPattern(goodPatterns[i]);
1094         }
1095     }
1096 
1097     /**
1098      * 4486735: RFE: SimpleDateFormat performance improvement
1099      *
1100      * Another round trip test
1101      */
1102     @SuppressWarnings("deprecation")

1103     public void Test4486735() throws Exception {
1104         TimeZone initialTimeZone = TimeZone.getDefault();
1105         TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
1106         Locale[] locales = Locale.getAvailableLocales();
1107         String[] zones = { "GMT", "America/Los_Angeles", "Europe/London", "Asia/Tokyo" };
1108 
1109         // Round to minutes. Some FULL formats don't have seconds.
1110         long time = System.currentTimeMillis()/60000 * 60000;
1111         Date date = new Date(time);
1112         logln("the test date: " + date);
1113 
1114         try {
1115             for (int z = 0; z < zones.length; z++) {
1116                 TimeZone.setDefault(TimeZone.getTimeZone(zones[z]));
1117                 for (int i = 0; i < locales.length; i++) {
1118                     Locale loc = locales[i];
1119                     DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL,
1120                                                                    DateFormat.FULL,
1121                                                                    loc);
1122                     String s = df.format(date);
1123                     logln(s);
1124                     Date parsedDate = df.parse(s);
1125                     long parsedTime = parsedDate.getTime();
1126                     if (time != parsedTime) {
1127                         // See if the time is in daylight-standard time transition. (JDK-8140571)
1128                         // Date-time formats in some locales don't have time zone information.
1129                         TimeZone tz = TimeZone.getDefault();
1130                         if (tz.inDaylightTime(date) && !tz.inDaylightTime(parsedDate)) {
1131                             if (time == parsedTime - tz.getDSTSavings()) {
1132                                 // OK (in "fall-back")
1133                                 continue;
1134                             }
1135                         }
1136                         errln("round trip conversion failed: timezone="+zones[z]+
1137                               ", locale=" + loc +
1138                               ", expected=" + time + ", got=" + parsedTime);
1139                     }
1140                 }
1141             }
1142 
1143             // Long format test
1144             String pat =
1145                "'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +  // 100
1146                 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
1147                 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +  // 200
1148                 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
1149                 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +  // 300
1150                 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
1151                 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +  // 400
1152                 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
1153                 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +  // 500
1154                 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'" +
1155                 "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" +
1156                 "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" +

1174                 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
1175                 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
1176                 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
1177                 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
1178                 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
1179                 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
1180                 "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" +
1181                 "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" +
1182                 "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" +
1183                 "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" +
1184                 "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" +
1185                 "00000000000000000000000000000000000000000000000000" +
1186                 "00000000000000000000000000000000000000000000000000" +
1187                 "00000000000000000000000000000000000000000000000000" +
1188                 "00000000000000000000000000000000000000000000000000" +
1189                 "00000000000000000000000000000000000000000000000000" +
1190                 "00000000000000000000000000000000000000000000002001\u5e74";
1191             SimpleDateFormat sdf = new SimpleDateFormat(pat);
1192             String s = sdf.format(new Date(2001-1900, Calendar.JANUARY, 1));
1193             if (!expected.equals(s)) {
1194                 errln("wrong format result: expected="+expected+", got="+s);
1195             }
1196             Date longday = sdf.parse(s);
1197             GregorianCalendar cal = new GregorianCalendar();
1198             cal.setTime(longday);
1199             if (cal.get(YEAR) != 2001) {
1200                 errln("wrong parse result: expected=2001, got=" + cal.get(YEAR));
1201             }
1202         } catch (Exception e) {
1203             throw e;
1204         } finally {
1205             // Restore the initial time zone
1206             TimeZone.setDefault(initialTimeZone);
1207         }
1208     }
1209 

1210     public void Test8216969() throws Exception {
1211         Locale locale = Locale.of("ru");
1212         String format = "\u0434\u0435\u043a";
1213         String standalone = "\u0434\u0435\u043a.";
1214 
1215         // Check that format form is used so that the dot is parsed correctly.
1216         SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd MMM.yyyy", locale);
1217         System.out.println(simpleDateFormat.parse("28 " + format + ".2018"));
1218 
1219         // Check that standalone form is used.
1220         simpleDateFormat = new SimpleDateFormat("MMM", locale);
1221         System.out.println(simpleDateFormat.parse(standalone));
1222     }
1223 }

   1 /*
   2  * Copyright (c) 1997, 2023, 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 /**
  25  * @test
  26  * @bug 4052223 4089987 4469904 4326988 4486735 8008577 8045998 8140571
  27  *      8190748 8216969
  28  * @summary test DateFormat and SimpleDateFormat.

  29  * @modules jdk.localedata
  30  * @run junit/othervm -Djava.locale.providers=COMPAT,SPI DateFormatTest
  31  */
  32 
  33 import java.util.*;
  34 import java.text.*;
  35 import static java.util.GregorianCalendar.*;
  36 
  37 import org.junit.jupiter.api.Test;
  38 import org.junit.jupiter.api.BeforeAll;
  39 
  40 import static org.junit.jupiter.api.Assertions.fail;
  41 
  42 public class DateFormatTest
  43 {
  44 
  45     // Change JVM default Locale
  46     @BeforeAll
  47     static void initAll() {
  48         Locale.setDefault(Locale.US);




  49     }
  50 
  51     // Test 4 digit year parsing with pattern "yy"
  52     @SuppressWarnings("deprecation")
  53     @Test
  54     public void TestYearParsing()
  55     {
  56         String str = "7/Sep/2001";
  57         Date exp = new Date(2001-1900, SEPTEMBER, 7);
  58         String pat = "d/MMM/yy";
  59         SimpleDateFormat sdf = new SimpleDateFormat(pat, Locale.US);
  60         try {
  61             Date d = sdf.parse(str);
  62             System.out.println(str + " parses with " + pat + " to " + d);
  63             if (d.getTime() != exp.getTime()) {
  64                 fail("FAIL: Expected " + exp);
  65             }
  66         }
  67         catch (ParseException e) {
  68             fail(str + " parse fails with " + pat);
  69         }
  70     }
  71 
  72     // Test written by Wally Wedel and emailed to me.
  73     @Test
  74     public void TestWallyWedel()
  75     {
  76         /*
  77          * Instantiate a TimeZone so we can get the ids.
  78          */
  79         TimeZone tz = new SimpleTimeZone(7,"");
  80         /*
  81          * Computational variables.
  82          */
  83         int offset, hours, minutes;
  84         /*
  85          * Instantiate a SimpleDateFormat set up to produce a full time
  86          zone name.
  87          */
  88         SimpleDateFormat sdf = new SimpleDateFormat("zzzz");
  89         /*
  90          * A String array for the time zone ids.
  91          */
  92         String[] ids = TimeZone.getAvailableIDs();
  93         /*
  94          * How many ids do we have?
  95          */
  96         System.out.println("Time Zone IDs size: " + ids.length);
  97         /*
  98          * Column headings (sort of)
  99          */
 100         System.out.println("Ordinal ID offset(h:m) name");
 101         /*
 102          * Loop through the tzs.
 103          */
 104         Date today = new Date();
 105         Calendar cal = Calendar.getInstance();
 106         for (int i = 0; i < ids.length; i++) {
 107             // logln(i + " " + ids[i]);
 108             TimeZone ttz = TimeZone.getTimeZone(ids[i]);
 109             // offset = ttz.getRawOffset();
 110             cal.setTimeZone(ttz);
 111             cal.setTime(today);
 112             offset = cal.get(Calendar.ZONE_OFFSET) + cal.get(Calendar.DST_OFFSET);
 113             // logln(i + " " + ids[i] + " offset " + offset);
 114             char sign = '+';
 115             if (offset < 0) { sign = '-'; offset = -offset; }
 116             hours = offset/3600000;
 117             minutes = (offset%3600000)/60000;
 118             String dstOffset = "" + sign + (hours < 10 ? "0" : "") +
 119                 hours + ':' + (minutes < 10 ? "0" : "") + minutes;
 120             /*
 121              * Instantiate a date so we can display the time zone name.
 122              */
 123             sdf.setTimeZone(ttz);
 124             /*
 125              * Format the output.
 126              */
 127             StringBuffer tzS = new StringBuffer();
 128             sdf.format(today,tzS, new FieldPosition(0));
 129             String fmtOffset = tzS.toString();
 130             String fmtDstOffset = null;
 131             if (fmtOffset.startsWith("GMT"))
 132             {
 133                 fmtDstOffset = fmtOffset.substring(3);
 134             }
 135             /*
 136              * Show our result.
 137              */
 138             boolean ok = fmtDstOffset == null || fmtDstOffset.equals(dstOffset);
 139             if (ok)
 140             {
 141                 System.out.println(i + " " + ids[i] + " " + dstOffset +
 142                       " " + fmtOffset +
 143                       (fmtDstOffset != null ? " ok" : " ?"));
 144             }
 145             else
 146             {
 147                 fail(i + " " + ids[i] + " " + dstOffset +
 148                       " " + fmtOffset + " *** FAIL ***");
 149             }
 150         }
 151     }
 152 
 153     // Test equals
 154     @Test
 155     public void TestEquals()
 156     {
 157         DateFormat fmtA = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.FULL);
 158 
 159         DateFormat fmtB = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.FULL);
 160 
 161         if (!fmtA.equals(fmtB)) {
 162             fail("FAIL");
 163         }
 164     }
 165 
 166     // Check out some specific parsing problem
 167     @SuppressWarnings("deprecation")
 168     @Test
 169     public void TestTwoDigitYearDSTParse()
 170     {
 171         SimpleDateFormat fullFmt =
 172             new SimpleDateFormat("EEE MMM dd HH:mm:ss.SSS zzz yyyy G");
 173 
 174         //DateFormat fmt = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.FULL,
 175         //                                                Locale.ENGLISH);
 176         SimpleDateFormat fmt = new SimpleDateFormat("dd-MMM-yy h:mm:ss 'o''clock' a z",
 177                                                     Locale.ENGLISH);
 178         //Date date = new Date(2004-1900, Calendar.APRIL, 3, 2, 20, 47);
 179         //logln(fmt.format(date)); // This shows what the current locale format is
 180         //logln(((SimpleDateFormat)fmt).toPattern());
 181         TimeZone save = TimeZone.getDefault();
 182         TimeZone PST  = TimeZone.getTimeZone("PST");
 183         String s = "03-Apr-04 2:20:47 o'clock AM PST";
 184         int hour = 2;
 185         try {
 186             TimeZone.setDefault(PST);
 187             Date d = fmt.parse(s);
 188             System.out.println(s + " P> " + fullFmt.format(d));
 189             if (d.getHours() != hour) {
 190                 fail("FAIL: Should parse to hour " + hour);
 191             }
 192         }
 193         catch (ParseException e) { fail("FAIL: " + e.getMessage()); }
 194         finally {
 195             TimeZone.setDefault(save);
 196         }
 197     }
 198 
 199     static String escape(String s)
 200     {
 201         StringBuilder buf = new StringBuilder();
 202         for (int i=0; i<s.length(); ++i)
 203         {
 204             char c = s.charAt(i);
 205             if (c <= (char)0x7F) {
 206                 buf.append(c);
 207             } else {
 208                 buf.append("\\u");
 209                 buf.append(Integer.toHexString((c & 0xF000) >> 12));
 210                 buf.append(Integer.toHexString((c & 0x0F00) >> 8));
 211                 buf.append(Integer.toHexString((c & 0x00F0) >> 4));
 212                 buf.append(Integer.toHexString(c & 0x000F));
 213             }

 221         "WEEK_OF_YEAR_FIELD", "WEEK_OF_MONTH_FIELD", "DATE_FIELD",
 222         "DAY_OF_YEAR_FIELD", "DAY_OF_WEEK_FIELD", "DAY_OF_WEEK_IN_MONTH_FIELD",
 223         "AM_PM_FIELD", "HOUR0_FIELD", "HOUR1_FIELD",
 224         "HOUR_OF_DAY0_FIELD", "HOUR_OF_DAY1_FIELD",
 225         "MINUTE_FIELD", "SECOND_FIELD",
 226         "MILLISECOND_FIELD", "TIMEZONE_FIELD",
 227     };
 228     static int fieldIDs[] = {
 229         DateFormat.ERA_FIELD, DateFormat.YEAR_FIELD, DateFormat.MONTH_FIELD,
 230         DateFormat.WEEK_OF_YEAR_FIELD, DateFormat.WEEK_OF_MONTH_FIELD, DateFormat.DATE_FIELD,
 231         DateFormat.DAY_OF_YEAR_FIELD, DateFormat.DAY_OF_WEEK_FIELD, DateFormat.DAY_OF_WEEK_IN_MONTH_FIELD,
 232         DateFormat.AM_PM_FIELD, DateFormat.HOUR0_FIELD, DateFormat.HOUR1_FIELD,
 233         DateFormat.HOUR_OF_DAY0_FIELD, DateFormat.HOUR_OF_DAY1_FIELD,
 234         DateFormat.MINUTE_FIELD, DateFormat.SECOND_FIELD,
 235         DateFormat.MILLISECOND_FIELD, DateFormat.TIMEZONE_FIELD,
 236     };
 237 
 238     /**
 239      * Bug 4089987
 240      */
 241     @Test
 242     public void TestFieldPosition()
 243     {
 244         DateFormat[] dateFormats = {
 245             DateFormat.getDateTimeInstance(DateFormat.FULL,DateFormat.FULL,
 246                                            Locale.US),
 247 
 248             DateFormat.getDateTimeInstance(DateFormat.FULL,DateFormat.FULL,Locale.FRANCE),
 249             new SimpleDateFormat("G, y, M, d, k, H, m, s, S, E, D, F, w, W, a, h, K, z"),
 250             new SimpleDateFormat("G, yy, M, d, k, H, m, s, S, E, D, F, w, W, a, h, K, z"),
 251             new SimpleDateFormat( "GGGG, yyyy, MMMM, dddd, kkkk, HHHH, mmmm, ssss, " +
 252                                   "SSSS, EEEE, DDDD, " +
 253                                   "FFFF, wwww, WWWW, aaaa, hhhh, KKKK, zzzz")
 254         };
 255         String[] expected =
 256         {
 257             "", "1997", "August", "", "", "13", "", "Wednesday", "",
 258             "PM", "", "2", "", "", "34", "12", "", "PDT",
 259 
 260             "", "1997", "ao\u00FBt", "", "", "13", "", "mercredi", "", "",
 261             "", "", "14", "", "34", "", "", "PDT" /*"GMT-07:00"*/,
 262 
 263             "AD", "1997", "8", "33", "3", "13", "225", "Wed", "2", "PM",
 264             "2", "2", "14", "14", "34", "12", "513", "PDT",
 265 
 266             "AD", "97", "8", "33", "3", "13", "225", "Wed", "2", "PM",
 267             "2", "2", "14", "14", "34", "12", "513", "PDT",
 268 
 269             "AD", "1997", "August", "0033", "0003", "0013", "0225",
 270             "Wednesday", "0002", "PM", "0002", "0002", "0014", "0014",
 271             "0034", "0012", "0513", "Pacific Daylight Time",
 272         };
 273         Date someDate = new Date(871508052513L);
 274         TimeZone PST = TimeZone.getTimeZone("PST");
 275         for (int j = 0, exp = 0; j < dateFormats.length; ++j) {
 276             DateFormat df = dateFormats[j];
 277             if (!(df instanceof SimpleDateFormat)) {
 278                 continue;
 279             }
 280             df.setTimeZone(PST);
 281             System.out.println(" Pattern = " + ((SimpleDateFormat)df).toPattern());
 282             System.out.println("  Result = " + df.format(someDate));
 283             for (int i = 0; i < fieldIDs.length; ++i)
 284             {
 285                 String field = getFieldText(df, fieldIDs[i], someDate);
 286                 if (!field.equals(expected[exp])) {
 287                     fail("FAIL: field #" + i + " " + fieldNames[i] + " = \"" +
 288                             escape(field) + "\", expected \"" + escape(expected[exp]) + "\"");
 289                 }
 290                 ++exp;
 291             }
 292         }
 293     }
 294     // get the string value for the given field for the given date
 295     static String getFieldText(DateFormat df, int field, Date date)
 296     {
 297         StringBuffer buffer = new StringBuffer();
 298         FieldPosition pos = new FieldPosition(field);
 299         df.format(date, buffer, pos);
 300         return buffer.toString().substring(pos.getBeginIndex(),
 301                                            pos.getEndIndex());
 302     }
 303 
 304     // Test parsing of partial strings
 305     @SuppressWarnings("deprecation")
 306     @Test
 307     public void TestPartialParse994()
 308     {
 309         SimpleDateFormat f = new SimpleDateFormat();
 310         Calendar cal = new GregorianCalendar(2014 - 80, JANUARY, 1);
 311         f.set2DigitYearStart(cal.getTime());
 312         tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10:11:42", new Date(97, 1-1, 17, 10, 11, 42));
 313         tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10:", null);
 314         tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 10", null);
 315         tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17 ", null);
 316         tryPat994(f, "yy/MM/dd HH:mm:ss", "97/01/17", null);
 317     }
 318 
 319     void tryPat994(SimpleDateFormat format, String pat, String str, Date expected)
 320     {
 321         System.out.println("Pattern \"" + pat + "\"   String \"" + str + "\"");
 322         try {
 323             format.applyPattern(pat);
 324             Date date = format.parse(str);
 325             String f = format.format(date);
 326             System.out.println(" parse(" + str + ") -> " + date.toString());
 327             System.out.println(" format -> " + f);
 328             if (expected == null ||
 329                 !date.equals(expected)) {
 330                 fail("FAIL: Expected " + expected);
 331             }
 332             if (!f.equals(str)) {
 333                 fail("FAIL: Expected " + str);
 334             }
 335         }
 336         catch(ParseException e) {
 337             System.out.println("ParseException: " + e.getMessage());
 338             if (expected != null) {
 339                 fail("FAIL: Expected " + expected);
 340             }
 341         }
 342         catch(Exception e) {
 343             fail("*** Exception:");
 344             e.printStackTrace();
 345         }
 346     }
 347 
 348     // Test pattern with runs things together
 349     @Test
 350     public void TestRunTogetherPattern985()
 351     {
 352         String format = "yyyyMMddHHmmssSSSzzzz";
 353         String now, then;
 354 
 355         SimpleDateFormat formatter = new SimpleDateFormat(format);
 356 
 357         Date date1 = new Date();
 358         now = formatter.format(date1);
 359 
 360         System.out.println(now);
 361 
 362         ParsePosition pos = new ParsePosition(0);
 363 
 364         Date date2 = formatter.parse(now, pos);
 365         if (date2 == null) {
 366             then = "Parse stopped at " + pos.getIndex();
 367         } else {
 368             then = formatter.format(date2);
 369         }
 370 
 371         System.out.println(then);
 372 
 373         if (!date2.equals(date1)) {
 374             fail("FAIL");
 375         }
 376     }
 377 
 378     // Test patterns which run numbers together
 379     @SuppressWarnings("deprecation")
 380     @Test
 381     public void TestRunTogetherPattern917()
 382     {
 383         SimpleDateFormat fmt;
 384         String myDate;
 385 
 386         fmt = new SimpleDateFormat( "yyyy/MM/dd" );
 387         myDate = "1997/02/03";
 388         _testIt917( fmt, myDate, new Date(97, 2-1, 3) );
 389 
 390         fmt = new SimpleDateFormat( "yyyyMMdd" );
 391         myDate = "19970304";
 392         _testIt917( fmt, myDate, new Date(97, 3-1, 4) );
 393 
 394     }
 395     void _testIt917( SimpleDateFormat fmt, String str, Date expected )
 396     {
 397         System.out.println( "pattern=" + fmt.toPattern() + "   string=" + str );
 398 
 399         Object o;
 400         try {
 401             o = fmt.parseObject( str );
 402         } catch( ParseException e ) {
 403             e.printStackTrace();
 404             return;
 405         }
 406         System.out.println( "Parsed object: " + o );
 407         if (!o.equals(expected)) {
 408             fail("FAIL: Expected " + expected);
 409         }
 410 
 411         String formatted = fmt.format( o );
 412         System.out.println( "Formatted string: " + formatted );
 413         if (!formatted.equals(str)) {
 414             fail("FAIL: Expected " + str);
 415         }
 416     }
 417 
 418     // Test Czech month formatting -- this can cause a problem because the June and
 419     // July month names share a common prefix.
 420     @SuppressWarnings("deprecation")
 421     @Test
 422     public void TestCzechMonths459()
 423     {
 424         // Use Czech, which has month names with shared prefixes for June and July
 425         DateFormat fmt = DateFormat.getDateInstance(DateFormat.FULL, Locale.of("cs"));
 426         //((SimpleDateFormat)fmt).applyPattern("MMMM d yyyy");
 427         System.out.println("Pattern " + ((SimpleDateFormat)fmt).toPattern());
 428 
 429         Date june = new Date(97, Calendar.JUNE, 15);
 430         Date july = new Date(97, Calendar.JULY, 15);
 431 
 432         String juneStr = fmt.format(june);
 433         String julyStr = fmt.format(july);
 434 
 435         try {
 436             System.out.println("format(June 15 1997) = " + juneStr);
 437             Date d = fmt.parse(juneStr);
 438             String s = fmt.format(d);
 439             int month = d.getMonth();
 440             System.out.println("  -> parse -> " + s + " (month = " + month + ")");
 441             if (month != JUNE) {
 442                 fail("FAIL: Month should be June");
 443             }
 444 
 445             System.out.println("format(July 15 1997) = " + julyStr);
 446             d = fmt.parse(julyStr);
 447             s = fmt.format(d);
 448             month = d.getMonth();
 449             System.out.println("  -> parse -> " + s + " (month = " + month + ")");
 450             if (month != JULY) {
 451                 fail("FAIL: Month should be July");
 452             }
 453         }
 454         catch (ParseException e) {
 455             fail("Exception: " + e);
 456         }
 457     }
 458 
 459     // Test big D (day of year) versus little d (day of month)
 460     @SuppressWarnings("deprecation")
 461     @Test
 462     public void TestLetterDPattern212()
 463     {
 464         String dateString = "1995-040.05:01:29";
 465         String bigD = "yyyy-DDD.hh:mm:ss";
 466         String littleD = "yyyy-ddd.hh:mm:ss";
 467         Date expLittleD = new Date(95, 0, 1, 5, 1, 29);
 468         Date expBigD =  new Date(expLittleD.getTime() + 39*24*3600000L); // 39 days
 469         expLittleD = expBigD; // Expect the same, with default lenient parsing
 470         System.out.println( "dateString= " + dateString );
 471         SimpleDateFormat formatter = new SimpleDateFormat(bigD);
 472         ParsePosition pos = new ParsePosition(0);
 473         Date myDate = formatter.parse( dateString, pos );
 474         System.out.println("Using " + bigD + " -> " + myDate);
 475         if (myDate.getTime() != expBigD.getTime()) {
 476             fail("FAIL: Expected " + expBigD + " got " + myDate);
 477         }
 478 
 479         formatter = new SimpleDateFormat(littleD);
 480         pos = new ParsePosition(0);
 481         myDate = formatter.parse( dateString, pos );
 482         System.out.println("Using " + littleD + " -> " + myDate);
 483         if (myDate.getTime() != expLittleD.getTime()) {
 484             fail("FAIL: Expected " + expLittleD + " got " + myDate);
 485         }
 486     }
 487 
 488     // Test the 'G' day of year pattern
 489     @SuppressWarnings("deprecation")
 490     @Test
 491     public void TestDayOfYearPattern195()
 492     {
 493         Date today = new Date();
 494         Date expected = new Date(today.getYear(), today.getMonth(), today.getDate());
 495 
 496         System.out.println("Test Date: " + today);
 497 
 498         SimpleDateFormat sdf =
 499             (SimpleDateFormat)SimpleDateFormat.getDateInstance();
 500 
 501         tryPattern(sdf, today, null, expected);
 502         tryPattern(sdf, today, "G yyyy DDD", expected);
 503     }
 504 
 505     void tryPattern(SimpleDateFormat sdf, Date d, String pattern, Date expected)
 506     {
 507         if (pattern != null) {
 508             sdf.applyPattern(pattern);
 509         }
 510         System.out.println("pattern: " + sdf.toPattern());
 511 
 512         String formatResult = sdf.format(d);
 513         System.out.println(" format -> " + formatResult);
 514         try {
 515             Date d2 = sdf.parse(formatResult);
 516             System.out.println(" parse(" + formatResult +  ") -> " + d2);
 517             if (d2.getTime() != expected.getTime()) {
 518                 fail("FAIL: Expected " + expected);
 519             }
 520             String format2 = sdf.format(d2);
 521             System.out.println(" format -> " + format2);
 522             if (!formatResult.equals(format2)) {
 523                 fail("FAIL: Round trip drift");
 524             }
 525         }
 526         catch(Exception e) {
 527             fail("Error: " + e.getMessage());
 528         }
 529     }
 530 
 531     // Test a pattern with single quotes
 532     @SuppressWarnings("deprecation")
 533     @Test
 534     public void TestQuotePattern161()
 535     {
 536         // This pattern used to end in " zzz" but that makes this test zone-dependent
 537         SimpleDateFormat formatter = new SimpleDateFormat("MM/dd/yyyy 'at' hh:mm:ss a zzz");
 538         Date currentTime_1 = new Date(97, Calendar.AUGUST, 13, 10, 42, 28);
 539         String dateString = formatter.format(currentTime_1);
 540         String exp = "08/13/1997 at 10:42:28 AM ";
 541         System.out.println("format(" + currentTime_1 + ") = " + dateString);
 542         if (!dateString.regionMatches(0, exp, 0, exp.length())) {
 543             fail("FAIL: Expected " + exp);
 544         }
 545     }
 546 
 547     // Test the parsing of bad input strings
 548     /** Demonstrates a number of bugs in DateFormat.parse(String) where
 549      *  either StringIndexOutOfBoundsException is thrown or null is
 550      *  returned instead of ParseException. To reproduce, run this program
 551      *  and notice all the "SHOULD NOT HAPPEN" errors.  Note also that the
 552      *  1 line that should be correct is off by 100 years.  (In this day
 553      *  and age, no one would assume that 1/1/00 is Jan 1 1900.)
 554      **/
 555     @Test
 556     public void TestBadInput135()
 557     {
 558         int        looks[] = { DateFormat.SHORT, DateFormat.MEDIUM,
 559                                DateFormat.LONG,  DateFormat.FULL };
 560         String     strings[] = { "Mar 15", "Mar 15 1997", "asdf",
 561                                  "3/1/97 1:23:", "3/1/00 1:23:45 AM" };
 562         DateFormat full = DateFormat.getDateTimeInstance(DateFormat.LONG,
 563                                                          DateFormat.LONG);
 564         String expected = "March 1, 2000 1:23:45 AM ";
 565         for ( int i = 0;  i < strings.length;  ++i ){
 566             String text = strings[i];
 567             for ( int j = 0;  j < looks.length;  ++j ){
 568                 int dateLook = looks[j];
 569                 for ( int k = 0;  k < looks.length;  ++k ){
 570                     int timeLook = looks[k];
 571                     DateFormat df = DateFormat.getDateTimeInstance(dateLook, timeLook);
 572                     String prefix = text + ", " + dateLook + "/" + timeLook + ": ";
 573                     try {
 574                         Date when = df.parse(text);
 575                         if ( when == null ){
 576                             fail(prefix +
 577                                   "SHOULD NOT HAPPEN: parse returned null.");
 578                             continue;
 579                         }
 580                         String format = full.format(when);
 581                         System.out.println(prefix + "OK: " + format);
 582                         // Only match the start -- not the zone, which could vary
 583                         if (!format.regionMatches(0, expected, 0, expected.length())) {
 584                             fail("FAIL: Expected " + expected);
 585                         }
 586                     }
 587                     catch ( ParseException e ){
 588                         //errln(prefix + e); // This is expected.
 589                     }
 590                     catch ( StringIndexOutOfBoundsException e ){
 591                         fail(prefix + "SHOULD NOT HAPPEN: " + e);
 592                     }
 593                 }
 594             }
 595         }
 596     }
 597 
 598     final private static String parseFormats[] =
 599     {
 600         "MMMM d, yyyy",  // january 1, 1970 or jan 1, 1970
 601         "MMMM d yyyy",   // january 1 1970 or jan 1 1970
 602         "M/d/yy",        // 1/1/70
 603         "d MMMM, yyyy",  // 1 january, 1970 or 1 jan, 1970
 604         "d MMMM yyyy",   // 1 january 1970 or 1 jan 1970
 605         "d MMMM",        // 1 january or 1 jan
 606         "MMMM d",        // january 1 or jan 1
 607         "yyyy",          // 1970
 608         "h:mm a MMMM d, yyyy" // Date and Time
 609     };
 610     final private static String inputStrings[] =
 611     {
 612         "bogus string",         null, null, null, null, null, null, null, null, null,
 613         "April 1, 1997",        "April 1, 1997", null, null, null, null, null, "April 1", null, null,
 614         "Jan 1, 1970",          "January 1, 1970", null, null, null, null, null, "January 1", null, null,
 615         "Jan 1 2037",           null, "January 1 2037", null, null, null, null, "January 1", null, null,
 616         "1/1/70",               null, null, "1/1/70", null, null, null, null, "0001", null,
 617         "5 May 1997",           null, null, null, null, "5 May 1997", "5 May", null, "0005", null,
 618         "16 May",               null, null, null, null, null, "16 May", null, "0016", null,
 619         "April 30",             null, null, null, null, null, null, "April 30", null, null,
 620         "1998",                 null, null, null, null, null, null, null, "1998", null,
 621         "1",                    null, null, null, null, null, null, null, "0001", null, // Bug620
 622         "3:00 pm Jan 1, 1997",  null, null, null, null, null, null, null, "0003", "3:00 PM January 1, 1997",
 623     };
 624     // More testing of the parsing of bad input
 625     @SuppressWarnings("UnusedAssignment")
 626     @Test
 627     public void TestBadInput135a()
 628     {
 629         SimpleDateFormat dateParse = new SimpleDateFormat();
 630         String s;
 631         Date date;
 632         int PFLENGTH = parseFormats.length;
 633 
 634         dateParse.applyPattern("d MMMM, yyyy");
 635         dateParse.setTimeZone(TimeZone.getDefault());
 636         s = "not parseable";
 637         System.out.println("Trying to parse \"" + s + "\" with " + dateParse.toPattern());
 638         try {
 639             date = dateParse.parse(s);
 640             fail("FAIL: Expected exception during parse");
 641         } catch (Exception ex) {
 642             System.out.println("Exception during parse: " + ex); // This is expected
 643         }
 644 
 645         for (int i=0; i<inputStrings.length; i += (PFLENGTH+1))
 646         {
 647             ParsePosition parsePosition = new ParsePosition(0);
 648             s = inputStrings[i];
 649 
 650             for (int index=0; index<PFLENGTH; ++index)
 651             {
 652                 String expected = inputStrings[i + 1 + index];
 653                 dateParse.applyPattern(parseFormats[index]);
 654                 dateParse.setTimeZone(TimeZone.getDefault());
 655                 // logln("Trying to parse \"" + s + "\" with " + dateParse.toPattern());
 656                 try {
 657                     parsePosition.setIndex(0);
 658                     date = dateParse.parse(s, parsePosition);
 659                     if (parsePosition.getIndex() != 0) {
 660                         if (date == null) {
 661                             fail("ERROR: null result with pos " +
 662                                     parsePosition.getIndex() + " " +
 663                                     s.substring(0, parsePosition.getIndex()) + "|" +
 664                                     s.substring(parsePosition.getIndex()));
 665                         } else {
 666                             String result = dateParse.format(date);
 667                             System.out.println("Parsed \"" + s + "\" using \"" + dateParse.toPattern() +
 668                                   "\" to: " + result);
 669                             if (expected == null) {
 670                                 fail("FAIL: Expected parse failure");
 671                             } else if (!expected.equals(result)) {
 672                                 fail("FAIL: Expected " + expected);
 673                             }
 674                         }
 675                     } else {
 676                         // logln("Not parsed.");
 677                         if (expected != null) {
 678                             fail("FAIL: Expected " + expected);
 679                         }
 680                     }
 681                 } catch (Exception ex) {
 682                     fail("An exception was thrown during parse: " + ex);
 683                 }
 684             }
 685         }
 686     }
 687 
 688     // Test the handling of 2-digit dates
 689     @Test
 690     public void TestTwoDigitYear() {
 691         SimpleDateFormat fmt = new SimpleDateFormat("M/d/yy");
 692 
 693         // find out the expected 2-digit year values for "6/5/17" and "6/4/34"
 694         long start = fmt.get2DigitYearStart().getTime();
 695         Calendar cal = new Calendar.Builder().setInstant(start).build();
 696         int startYear = cal.get(YEAR);
 697         cal.add(YEAR, 100);
 698         long end = cal.getTimeInMillis();
 699         int endYear = cal.get(YEAR);
 700         int xx17 = 0, xx34 = 0;
 701         for (int year = startYear; year <= endYear; year++) {
 702             int yy = year % 100;
 703             if (yy == 17 && xx17 == 0) {
 704                 xx17 = yearValue(start, end, year, JUNE, 5);
 705             } else if (yy == 34 && xx34 == 0) {
 706                 xx34 = yearValue(start, end, year, JUNE, 4);
 707             }
 708             if (xx17 != 0 && xx34 != 0) {
 709                 break;
 710             }
 711         }
 712         if (xx17 == 0 || xx34 == 0) {
 713             fail("Failed: producing expected values: 2DigitYearStart: " + new Date(start)
 714                   + ", xx17 = " + xx17 + ", xx34 = " + xx34);
 715         }
 716         System.out.println("2DigitYearStart: " + new Date(start) + ", xx17 = " + xx17 + ", xx34 = " + xx34);
 717 
 718         parse2DigitYear(fmt, "6/5/17", new GregorianCalendar(xx17, JUNE, 5).getTime());
 719         parse2DigitYear(fmt, "6/4/34", new GregorianCalendar(xx34, JUNE, 4).getTime());
 720     }
 721 
 722     private int yearValue(long start, long end, int year, int month, int dayOfMonth) {
 723         Calendar cal = new GregorianCalendar(year, month, dayOfMonth);
 724         long time = cal.getTimeInMillis();
 725         return (start <= time && time < end) ? year : 0;
 726     }
 727 
 728     private void parse2DigitYear(SimpleDateFormat fmt, String str, Date expected) {
 729         try {
 730             Date d = fmt.parse(str);
 731             System.out.println("Parsing \"" + str + "\" with " +
 732                   fmt.toPattern() +
 733                   "  => " + d.toString());
 734             if (d.getTime() != expected.getTime()) {
 735                 fail("FAIL: Expected " + expected);
 736             }
 737         } catch (ParseException e) {
 738             fail("FAIL: Got exception");
 739         }
 740     }
 741 
 742     // Test behavior of DateFormat with applied time zone
 743     @Test
 744     public void TestDateFormatZone061()
 745     {
 746         Date date;
 747         DateFormat formatter;
 748 
 749         // 25-Mar-97 00:00:00 GMT
 750         date = new Date( 859248000000L );
 751         System.out.println( "Date 1997/3/25 00:00 GMT: " + date );
 752         formatter = new SimpleDateFormat("dd-MMM-yyyyy HH:mm", Locale.UK);
 753         formatter.setTimeZone( TimeZone.getTimeZone( "GMT" ) );
 754 
 755         String temp = formatter.format( date );
 756         System.out.println( "Formatted in GMT to: " + temp );
 757 
 758         /* Parse date string */
 759         try {
 760             Date tempDate = formatter.parse( temp );
 761             System.out.println( "Parsed to: " + tempDate );
 762             if (tempDate.getTime() != date.getTime()) {
 763                 fail("FAIL: Expected " + date);
 764             }
 765         }
 766         catch( Throwable t ) {
 767             fail( "Date Formatter throws: " +
 768                    t.toString() );
 769         }
 770     }
 771 
 772     // Make sure DateFormat uses the correct zone.
 773     @Test
 774     public void TestDateFormatZone146()
 775     {
 776         TimeZone saveDefault = TimeZone.getDefault();
 777 
 778         try {
 779             TimeZone thedefault = TimeZone.getTimeZone("GMT");
 780             TimeZone.setDefault(thedefault);
 781             // java.util.Locale.setDefault(new java.util.Locale("ar", "", ""));
 782 
 783             // check to be sure... its GMT all right
 784             TimeZone testdefault = TimeZone.getDefault();
 785             String testtimezone = testdefault.getID();
 786             if (testtimezone.equals("GMT")) {
 787                 System.out.println("Test timezone = " + testtimezone);
 788             } else {
 789                 fail("Test timezone should be GMT, not " + testtimezone);
 790             }
 791 
 792             // now try to use the default GMT time zone
 793             GregorianCalendar greenwichcalendar =
 794                 new GregorianCalendar(1997, 3, 4, 23, 0);
 795             //*****************************greenwichcalendar.setTimeZone(TimeZone.getDefault());
 796             //greenwichcalendar.set(1997, 3, 4, 23, 0);
 797             // try anything to set hour to 23:00 !!!
 798             greenwichcalendar.set(Calendar.HOUR_OF_DAY, 23);
 799             // get time
 800             Date greenwichdate = greenwichcalendar.getTime();
 801             // format every way
 802             String[] DATA = {
 803                 "simple format:  ", "04/04/97 23:00 GMT",
 804                     "MM/dd/yy HH:mm z",
 805                 "full format:    ", "Friday, April 4, 1997 11:00:00 o'clock PM GMT",
 806                     "EEEE, MMMM d, yyyy h:mm:ss 'o''clock' a z",
 807                 "long format:    ", "April 4, 1997 11:00:00 PM GMT",
 808                     "MMMM d, yyyy h:mm:ss a z",
 809                 "default format: ", "04-Apr-97 11:00:00 PM",
 810                     "dd-MMM-yy h:mm:ss a",
 811                 "short format:   ", "4/4/97 11:00 PM",
 812                     "M/d/yy h:mm a",
 813             };
 814 
 815             for (int i=0; i<DATA.length; i+=3) {
 816                 DateFormat fmt = new SimpleDateFormat(DATA[i+2], Locale.ENGLISH);
 817                 fmt.setCalendar(greenwichcalendar);
 818                 String result = fmt.format(greenwichdate);
 819                 System.out.println(DATA[i] + result);
 820                 if (!result.equals(DATA[i+1])) {
 821                     fail("FAIL: Expected " + DATA[i+1]
 822                             + ", got " + result);
 823                 }
 824             }
 825         }
 826         finally {
 827             TimeZone.setDefault(saveDefault);
 828         }
 829     }
 830 
 831 /* HS : Commented out for now, need to be changed not to use hardcoded results.
 832     @Test
 833     public void TestLocaleDateFormat() // Bug 495
 834     {
 835         Date testDate = new Date (97, Calendar.SEPTEMBER, 15);
 836         DateFormat dfFrench = DateFormat.getDateTimeInstance(DateFormat.FULL,
 837                                                              DateFormat.FULL, Locale.FRENCH);
 838         DateFormat dfUS = DateFormat.getDateTimeInstance(DateFormat.FULL,
 839                                                          DateFormat.FULL, Locale.US);
 840         String expectedFRENCH = "lundi 15 septembre 1997 00 h 00 GMT-07:00";
 841         String expectedUS = "Monday, September 15, 1997 12:00:00 o'clock AM PDT";
 842         System.out.println("Date set to : " + testDate);
 843         String out = dfFrench.format(testDate);
 844         System.out.println("Date Formated with French Locale " + out);
 845         if (!out.equals(expectedFRENCH)) fail("FAIL: Expected " + expectedFRENCH);
 846         out = dfUS.format(testDate);
 847         System.out.println("Date Formated with US Locale " + out);
 848         if (!out.equals(expectedUS)) fail("FAIL: Expected " + expectedUS);
 849     }
 850 */
 851     /**
 852      * Bug 4056591
 853      */
 854 /*
 855 test commented out pending API-change approval
 856     @Test
 857     public void Test2YearStartDate() throws ParseException
 858     {
 859         // create a SimpleDateFormat to test with; dump out if it's not a SimpleDateFormat
 860         DateFormat test = DateFormat.getDateInstance(DateFormat.SHORT, Locale.US);
 861 
 862         if (!(test instanceof SimpleDateFormat)) {
 863             fail("DateFormat.getInstance() didn't return an instance of SimpleDateFormat!");
 864             return;
 865         }
 866 
 867         SimpleDateFormat sdf = (SimpleDateFormat)test;
 868         String testString1 = "3/10/67";
 869         String testString2 = "3/16/43";
 870         String testString3 = "7/21/43";
 871 
 872         // set 2-digit start date to 1/1/1900
 873         Calendar cal = Calendar.getInstance(Locale.US);
 874         cal.set(1900, 0, 1);
 875         sdf.set2DigitStartDate(cal.getTime());
 876 
 877         // check to make sure get2DigitStartDate() returns the value we passed to
 878         // set2DigitStartDate()
 879         Date date = sdf.get2DigitStartDate();
 880         cal.setTime(date);
 881         if (cal.get(Calendar.YEAR) != 1900 || cal.get(Calendar.MONTH) != 0 ||
 882                         cal.get(Calendar.DATE) != 1)
 883             fail("SimpleDateFormat.get2DigitStartDate() returned " + (cal.get(Calendar.MONTH)
 884                         + 1) + "/" + cal.get(Calendar.DATE) + "/" + cal.get(Calendar.YEAR) +
 885                         " instead of 1/1/1900.");
 886 
 887         // try parsing "3/10/67" and "3/16/43" with the 2-digit start date set to 1/1/1900
 888         date = sdf.parse(testString1);
 889         cal.setTime(date);
 890         if (cal.get(Calendar.YEAR) != 1967)
 891             fail("Parsing \"3/10/67\" with 2-digit start date set to 1/1/1900 yielded a year of "
 892                             + cal.get(Calendar.YEAR) + " instead of 1967.");
 893         if (cal.get(Calendar.MONTH) != 2 || cal.get(Calendar.DATE) != 10)
 894             fail("Parsing \"3/10/67\" with 2-digit start date set to 1/1/1900 failed: got " +
 895                             (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DATE) +
 896                             " instead of 3/10.");
 897         date = sdf.parse(testString2);
 898         cal.setTime(date);
 899         if (cal.get(Calendar.YEAR) != 1943)
 900             fail("Parsing \"3/16/43\" with 2-digit start date set to 1/1/1900 yielded a year of "
 901                             + cal.get(Calendar.YEAR) + " instead of 1943.");
 902         if (cal.get(Calendar.MONTH) != 2 || cal.get(Calendar.DATE) != 16)
 903             fail("Parsing \"3/16/43\" with 2-digit start date set to 1/1/1900 failed: got " +
 904                             (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DATE) +
 905                             " instead of 3/16.");
 906 
 907         // try parsing "3/10/67" and "3/16/43" with the 2-digit start date set to 1/1/2000
 908         cal.set(2000, 0, 1);
 909         sdf.set2DigitStartDate(cal.getTime());
 910         date = sdf.parse(testString1);
 911         cal.setTime(date);
 912         if (cal.get(Calendar.YEAR) != 2067)
 913             fail("Parsing \"3/10/67\" with 2-digit start date set to 1/1/2000 yielded a year of "
 914                             + cal.get(Calendar.YEAR) + " instead of 2067.");
 915         if (cal.get(Calendar.MONTH) != 2 || cal.get(Calendar.DATE) != 10)
 916             fail("Parsing \"3/10/67\" with 2-digit start date set to 1/1/2000 failed: got " +
 917                             (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DATE) +
 918                             " instead of 3/10.");
 919         date = sdf.parse(testString2);
 920         cal.setTime(date);
 921         if (cal.get(Calendar.YEAR) != 2043)
 922             fail("Parsing \"3/16/43\" with 2-digit start date set to 1/1/2000 yielded a year of "
 923                             + cal.get(Calendar.YEAR) + " instead of 1943.");
 924         if (cal.get(Calendar.MONTH) != 2 || cal.get(Calendar.DATE) != 16)
 925             fail("Parsing \"3/16/43\" with 2-digit start date set to 1/1/2000 failed: got " +
 926                             (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DATE) +
 927                             " instead of 3/16.");
 928 
 929         // try parsing "3/10/67" and "3/16/43" with the 2-digit start date set to 1/1/1950
 930         cal.set(1950, 0, 1);
 931         sdf.set2DigitStartDate(cal.getTime());
 932         date = sdf.parse(testString1);
 933         cal.setTime(date);
 934         if (cal.get(Calendar.YEAR) != 1967)
 935             fail("Parsing \"3/10/67\" with 2-digit start date set to 1/1/1950 yielded a year of "
 936                             + cal.get(Calendar.YEAR) + " instead of 1967.");
 937         if (cal.get(Calendar.MONTH) != 2 || cal.get(Calendar.DATE) != 10)
 938             fail("Parsing \"3/10/67\" with 2-digit start date set to 1/1/1950 failed: got " +
 939                             (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DATE) +
 940                             " instead of 3/10.");
 941         date = sdf.parse(testString2);
 942         cal.setTime(date);
 943         if (cal.get(Calendar.YEAR) != 2043)
 944             fail("Parsing \"3/16/43\" with 2-digit start date set to 1/1/1950 yielded a year of "
 945                             + cal.get(Calendar.YEAR) + " instead of 1943.");
 946         if (cal.get(Calendar.MONTH) != 2 || cal.get(Calendar.DATE) != 16)
 947             fail("Parsing \"3/16/43\" with 2-digit start date set to 1/1/1950 failed: got " +
 948                             (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DATE) +
 949                             " instead of 3/16.");
 950 
 951         // try parsing "3/16/43" and "7/21/43" with the 2-digit start date set to 6/1/1943
 952         cal.set(1943, 5, 1);
 953         sdf.set2DigitStartDate(cal.getTime());
 954         date = sdf.parse(testString2);
 955         cal.setTime(date);
 956         if (cal.get(Calendar.YEAR) != 2043)
 957             fail("Parsing \"3/16/43\" with 2-digit start date set to 6/1/1943 yielded a year of "
 958                             + cal.get(Calendar.YEAR) + " instead of 2043.");
 959         if (cal.get(Calendar.MONTH) != 2 || cal.get(Calendar.DATE) != 16)
 960             fail("Parsing \"3/16/43\" with 2-digit start date set to 6/1/1943 failed: got " +
 961                             (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DATE) +
 962                             " instead of 3/16.");
 963         date = sdf.parse(testString3);
 964         cal.setTime(date);
 965         if (cal.get(Calendar.YEAR) != 1943)
 966             fail("Parsing \"7/21/43\" with 2-digit start date set to 6/1/1943 yielded a year of "
 967                             + cal.get(Calendar.YEAR) + " instead of 1943.");
 968         if (cal.get(Calendar.MONTH) != 6 || cal.get(Calendar.DATE) != 21)
 969             fail("Parsing \"7/21/43\" with 2-digit start date set to 6/1/1943 failed: got " +
 970                             (cal.get(Calendar.MONTH) + 1) + "/" + cal.get(Calendar.DATE) +
 971                             " instead of 7/21.");
 972 
 973         // and finally, check one more time to make sure get2DigitStartDate() returns the last
 974         // value we passed to set2DigitStartDate()
 975         date = sdf.get2DigitStartDate();
 976         cal.setTime(date);
 977         if (cal.get(Calendar.YEAR) != 1943 || cal.get(Calendar.MONTH) != 5 ||
 978                         cal.get(Calendar.DATE) != 1)
 979             fail("SimpleDateFormat.get2DigitStartDate() returned " + (cal.get(Calendar.MONTH)
 980                         + 1) + "/" + cal.get(Calendar.DATE) + "/" + cal.get(Calendar.YEAR) +
 981                         " instead of 6/1/1943.");
 982     }
 983 */
 984 
 985     /**
 986      * ParsePosition.errorIndex tests.
 987      */
 988     @SuppressWarnings("deprecation")
 989     @Test
 990     public void Test4052223()
 991     {
 992         String str = "7/SOS/2001";
 993         Date exp = new Date(101, Calendar.SEPTEMBER, 7);
 994         String pat = "d/MMM/yy";
 995         SimpleDateFormat sdf = new SimpleDateFormat(pat);
 996         ParsePosition pos = new ParsePosition(0);
 997         Date d = sdf.parse(str, pos);
 998         System.out.println(str + " parses with " + pat + " to " + d);
 999         if (d == null && pos.getErrorIndex() == 2) {
1000             System.out.println("Expected null returned, failed at : " + pos.getErrorIndex());
1001         } else {
1002             fail("Failed, parse " + str + " got : " + d + ", index=" + pos.getErrorIndex());
1003         }
1004     }
1005 
1006     /**
1007      * Bug4469904 -- th_TH date format doesn't use Thai B.E.
1008      */
1009     @Test
1010     public void TestBuddhistEraBugId4469904() {
1011         String era = "\u0e1e.\u0e28.";
1012         Locale loc = Locale.of("th", "TH");
1013         Calendar cal = Calendar.getInstance(Locale.US);
1014         cal.set(2001, 7, 23);
1015         Date date = cal.getTime();
1016         DateFormat df = DateFormat.getDateInstance(DateFormat.FULL, loc);
1017         String output = df.format(date);
1018         int index = output.indexOf(era);
1019         if (index == -1) {
1020             fail("Test4469904: Failed. Buddhist Era abbrev not present.");
1021         }
1022     }
1023 
1024     /**
1025      * 4326988: API: SimpleDateFormat throws NullPointerException when parsing with null pattern
1026      */
1027     @SuppressWarnings("UnusedAssignment")
1028     @Test
1029     public void Test4326988() {
1030         String[] wrongPatterns = {
1031             "hh o''clock",
1032             "hh 'o''clock",     // unterminated quote
1033             "''''''''''''oclock",
1034             "efgxyz",
1035         };
1036         String[] goodPatterns = {
1037             "hh 'o''clock'",
1038             "'''''''''''''o'",
1039             "'efgxyz'",
1040             ":;,.-",
1041         };
1042 
1043         // Check NullPointerException
1044         try {
1045             SimpleDateFormat fmt = new SimpleDateFormat(null);
1046             fail("SimpleDateFormat() doesn't throw NPE with null pattern");
1047         } catch (NullPointerException e) {
1048             // Okay
1049         }
1050         try {
1051             Locale loc = null;
1052             SimpleDateFormat fmt = new SimpleDateFormat("yyyy/MM/dd", loc);
1053             fail("SimpleDateFormat() doesn't throw NPE with null locale");
1054         } catch (NullPointerException e) {
1055             // Okay
1056         }
1057         try {
1058             DateFormatSymbols symbols = null;
1059             SimpleDateFormat fmt = new SimpleDateFormat("yyyy/MM/dd", symbols);
1060             fail("SimpleDateFormat() doesn't throw NPE with null DateFormatSymbols");
1061         } catch (NullPointerException e) {
1062             // Okay
1063         }
1064         try {
1065             SimpleDateFormat fmt = new SimpleDateFormat();
1066             fmt.applyPattern(null);
1067             fail("applyPattern() doesn't throw NPE with null pattern");
1068         } catch (NullPointerException e) {
1069             // Okay
1070         }
1071 
1072         // Check IllegalParameterException
1073         for (int i = 0; i < wrongPatterns.length; i++) {
1074             try {
1075                 SimpleDateFormat fmt = new SimpleDateFormat(wrongPatterns[i]);
1076                 fail("SimpleDateFormat(\"" + wrongPatterns[i] + "\")" +
1077                       " doesn't throw an IllegalArgumentException");
1078             } catch (IllegalArgumentException e) {
1079                 // Okay
1080             }
1081             try {
1082                 SimpleDateFormat fmt = new SimpleDateFormat(wrongPatterns[i],
1083                                                             DateFormatSymbols.getInstance());
1084                 fail("SimpleDateFormat(\"" + wrongPatterns[i] + "\", DateFormatSymbols) doesn't " +
1085                       "throw an IllegalArgumentException");
1086             } catch (IllegalArgumentException e) {
1087                 // Okay
1088             }
1089             try {
1090                 SimpleDateFormat fmt = new SimpleDateFormat(wrongPatterns[i],
1091                                                             Locale.US);
1092                 fail("SimpleDateFormat(\"" + wrongPatterns[i] +
1093                       "\", Locale) doesn't throw an IllegalArgumentException");
1094             } catch (IllegalArgumentException e) {
1095                 // Okay
1096             }
1097             try {
1098                 SimpleDateFormat fmt = new SimpleDateFormat();
1099                 fmt.applyPattern(wrongPatterns[i]);
1100                 fail("SimpleDateFormat.applyPattern(\"" + wrongPatterns[i] +
1101                       "\") doesn't throw an IllegalArgumentException");
1102             } catch (IllegalArgumentException e) {
1103                 // Okay
1104             }
1105         }
1106 
1107         for (int i = 0; i < goodPatterns.length; i++) {
1108             SimpleDateFormat fmt;
1109             fmt = new SimpleDateFormat(goodPatterns[i]);
1110             fmt = new SimpleDateFormat(goodPatterns[i],
1111                                        DateFormatSymbols.getInstance());
1112             fmt = new SimpleDateFormat(goodPatterns[i],
1113                                        Locale.US);
1114             fmt = new SimpleDateFormat();
1115             fmt.applyPattern(goodPatterns[i]);
1116         }
1117     }
1118 
1119     /**
1120      * 4486735: RFE: SimpleDateFormat performance improvement
1121      *
1122      * Another round trip test
1123      */
1124     @SuppressWarnings("deprecation")
1125     @Test
1126     public void Test4486735() throws Exception {
1127         TimeZone initialTimeZone = TimeZone.getDefault();
1128         TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
1129         Locale[] locales = Locale.getAvailableLocales();
1130         String[] zones = { "GMT", "America/Los_Angeles", "Europe/London", "Asia/Tokyo" };
1131 
1132         // Round to minutes. Some FULL formats don't have seconds.
1133         long time = System.currentTimeMillis()/60000 * 60000;
1134         Date date = new Date(time);
1135         System.out.println("the test date: " + date);
1136 
1137         try {
1138             for (int z = 0; z < zones.length; z++) {
1139                 TimeZone.setDefault(TimeZone.getTimeZone(zones[z]));
1140                 for (int i = 0; i < locales.length; i++) {
1141                     Locale loc = locales[i];
1142                     DateFormat df = DateFormat.getDateTimeInstance(DateFormat.FULL,
1143                                                                    DateFormat.FULL,
1144                                                                    loc);
1145                     String s = df.format(date);
1146                     System.out.println(s);
1147                     Date parsedDate = df.parse(s);
1148                     long parsedTime = parsedDate.getTime();
1149                     if (time != parsedTime) {
1150                         // See if the time is in daylight-standard time transition. (JDK-8140571)
1151                         // Date-time formats in some locales don't have time zone information.
1152                         TimeZone tz = TimeZone.getDefault();
1153                         if (tz.inDaylightTime(date) && !tz.inDaylightTime(parsedDate)) {
1154                             if (time == parsedTime - tz.getDSTSavings()) {
1155                                 // OK (in "fall-back")
1156                                 continue;
1157                             }
1158                         }
1159                         fail("round trip conversion failed: timezone="+zones[z]+
1160                               ", locale=" + loc +
1161                               ", expected=" + time + ", got=" + parsedTime);
1162                     }
1163                 }
1164             }
1165 
1166             // Long format test
1167             String pat =
1168                "'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +  // 100
1169                 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
1170                 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +  // 200
1171                 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
1172                 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +  // 300
1173                 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
1174                 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +  // 400
1175                 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
1176                 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +  // 500
1177                 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'" +
1178                 "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" +
1179                 "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" +

1197                 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
1198                 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
1199                 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
1200                 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
1201                 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
1202                 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +
1203                 "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" +
1204                 "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" +
1205                 "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" +
1206                 "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" +
1207                 "\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:\u6642\u9593:" +
1208                 "00000000000000000000000000000000000000000000000000" +
1209                 "00000000000000000000000000000000000000000000000000" +
1210                 "00000000000000000000000000000000000000000000000000" +
1211                 "00000000000000000000000000000000000000000000000000" +
1212                 "00000000000000000000000000000000000000000000000000" +
1213                 "00000000000000000000000000000000000000000000002001\u5e74";
1214             SimpleDateFormat sdf = new SimpleDateFormat(pat);
1215             String s = sdf.format(new Date(2001-1900, Calendar.JANUARY, 1));
1216             if (!expected.equals(s)) {
1217                 fail("wrong format result: expected="+expected+", got="+s);
1218             }
1219             Date longday = sdf.parse(s);
1220             GregorianCalendar cal = new GregorianCalendar();
1221             cal.setTime(longday);
1222             if (cal.get(YEAR) != 2001) {
1223                 fail("wrong parse result: expected=2001, got=" + cal.get(YEAR));
1224             }
1225         } catch (Exception e) {
1226             throw e;
1227         } finally {
1228             // Restore the initial time zone
1229             TimeZone.setDefault(initialTimeZone);
1230         }
1231     }
1232 
1233     @Test
1234     public void Test8216969() throws Exception {
1235         Locale locale = Locale.of("ru");
1236         String format = "\u0434\u0435\u043a";
1237         String standalone = "\u0434\u0435\u043a.";
1238 
1239         // Check that format form is used so that the dot is parsed correctly.
1240         SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd MMM.yyyy", locale);
1241         System.out.println(simpleDateFormat.parse("28 " + format + ".2018"));
1242 
1243         // Check that standalone form is used.
1244         simpleDateFormat = new SimpleDateFormat("MMM", locale);
1245         System.out.println(simpleDateFormat.parse(standalone));
1246     }
1247 }
< prev index next >