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