1/* GENERATED SOURCE. DO NOT MODIFY. */
2// © 2016 and later: Unicode, Inc. and others.
3// License & terms of use: http://www.unicode.org/copyright.html#License
4/**
5 *******************************************************************************
6 * Copyright (C) 2000-2016, International Business Machines Corporation and    *
7 * others. All Rights Reserved.                                                *
8 *******************************************************************************
9 */
10package android.icu.dev.test.calendar;
11
12import java.io.ByteArrayInputStream;
13import java.io.ByteArrayOutputStream;
14import java.io.IOException;
15import java.io.ObjectInputStream;
16import java.io.ObjectOutputStream;
17import java.text.ParsePosition;
18import java.util.ArrayList;
19import java.util.Arrays;
20import java.util.Date;
21import java.util.HashSet;
22import java.util.List;
23import java.util.Locale;
24import java.util.MissingResourceException;
25
26import org.junit.Test;
27import org.junit.runner.RunWith;
28import org.junit.runners.JUnit4;
29
30import android.icu.text.DateFormat;
31import android.icu.text.NumberFormat;
32import android.icu.text.SimpleDateFormat;
33import android.icu.util.Calendar;
34import android.icu.util.GregorianCalendar;
35import android.icu.util.HebrewCalendar;
36import android.icu.util.IslamicCalendar;
37import android.icu.util.SimpleTimeZone;
38import android.icu.util.TimeZone;
39import android.icu.util.ULocale;
40import android.icu.testsharding.MainTestShard;
41
42/**
43 * @test 1.32 99/11/14
44 * @bug 4031502 4035301 4040996 4051765 4059654 4061476 4070502 4071197 4071385
45 * 4073929 4083167 4086724 4092362 4095407 4096231 4096539 4100311 4103271
46 * 4106136 4108764 4114578 4118384 4125881 4125892 4136399 4141665 4142933
47 * 4145158 4145983 4147269 4149677 4162587 4165343 4166109 4167060 4173516
48 * 4174361 4177484 4197699 4209071 4288792
49 */
50@MainTestShard
51@RunWith(JUnit4.class)
52public class CalendarRegressionTest extends android.icu.dev.test.TestFmwk {
53    static final String[] FIELD_NAME = {
54            "ERA", "YEAR", "MONTH", "WEEK_OF_YEAR", "WEEK_OF_MONTH",
55            "DAY_OF_MONTH", "DAY_OF_YEAR", "DAY_OF_WEEK",
56            "DAY_OF_WEEK_IN_MONTH", "AM_PM", "HOUR", "HOUR_OF_DAY",
57            "MINUTE", "SECOND", "MILLISECOND", "ZONE_OFFSET",
58            "DST_OFFSET", "YEAR_WOY", "DOW_LOCAL", "EXTENDED_YEAR",
59            "JULIAN_DAY", "MILLISECONDS_IN_DAY"
60        };
61
62
63    /*
64      Synopsis: java.sql.Timestamp constructor works wrong on Windows 95
65
66      ==== Here is the test ====
67      public static void main (String args[]) {
68        java.sql.Timestamp t= new java.sql.Timestamp(0,15,5,5,8,13,123456700);
69        logln("expected=1901-04-05 05:08:13.1234567");
70        logln(" result="+t);
71      }
72
73      ==== Here is the output of the test on Solaris or NT ====
74      expected=1901-04-05 05:08:13.1234567
75      result=1901-04-05 05:08:13.1234567
76
77      ==== Here is the output of the test on Windows95 ====
78      expected=1901-04-05 05:08:13.1234567
79      result=1901-04-05 06:08:13.1234567
80      */
81
82    @Test
83    public void Test4031502() {
84        try{
85            // This bug actually occurs on Windows NT as well, and doesn't
86            // require the host zone to be set; it can be set in Java.
87            String[] ids = TimeZone.getAvailableIDs();
88            boolean bad = false;
89            for (int i=0; i<ids.length; ++i) {
90                TimeZone zone = TimeZone.getTimeZone(ids[i]);
91                GregorianCalendar cal = new GregorianCalendar(zone);
92                cal.clear();
93                cal.set(1900, 15, 5, 5, 8, 13);
94                if (cal.get(Calendar.HOUR) != 5) {
95                    logln("Fail: " + zone.getID() + " " +
96                          zone.useDaylightTime() + "; DST_OFFSET = " +
97                          cal.get(Calendar.DST_OFFSET) / (60*60*1000.0) + "; ZONE_OFFSET = " +
98                          cal.get(Calendar.ZONE_OFFSET) / (60*60*1000.0) + "; getRawOffset() = " +
99                          zone.getRawOffset() / (60*60*1000.0) +
100                          "; HOUR = " + cal.get(Calendar.HOUR));
101                    cal.clear();
102                    cal.set(1900, 15, 5, 5, 8, 13);
103                    if (cal.get(Calendar.HOUR) != 5) {
104                        logln("Fail: " + zone.getID() + " " +
105                              zone.useDaylightTime() + "; DST_OFFSET = " +
106                              cal.get(Calendar.DST_OFFSET) / (60*60*1000.0) + "; ZONE_OFFSET = " +
107                              cal.get(Calendar.ZONE_OFFSET) / (60*60*1000.0) + "; getRawOffset() = " +
108                              zone.getRawOffset() / (60*60*1000.0) +
109                              "; HOUR = " + cal.get(Calendar.HOUR));
110                        cal.clear();
111                        cal.set(1900, 15, 5, 5, 8, 13);
112                        logln("ms = " + cal.getTime() + " (" + cal.getTime().getTime() + ")");
113                        cal.get(Calendar.HOUR);
114                        java.util.GregorianCalendar cal2 = new java.util.GregorianCalendar(java.util.TimeZone.getTimeZone(ids[i]));
115                        cal2.clear();
116                        cal2.set(1900, 15, 5, 5, 8, 13);
117                        cal2.get(Calendar.HOUR);
118                        logln("java.util.GC: " + zone.getID() + " " +
119                            zone.useDaylightTime() + "; DST_OFFSET = " +
120                            cal2.get(Calendar.DST_OFFSET) / (60*60*1000.0) + "; ZONE_OFFSET = " +
121                            cal2.get(Calendar.ZONE_OFFSET) / (60*60*1000.0) + "; getRawOffset() = " +
122                            zone.getRawOffset() / (60*60*1000.0) +
123                            "; HOUR = " + cal.get(Calendar.HOUR));
124                        logln("ms = " + cal2.getTime() + " (" + cal2.getTime().getTime() + ")");
125                        bad = true;
126                    } else if (false) { // Change to true to debug
127                        logln("OK: " + zone.getID() + " " +
128                              zone.useDaylightTime() + " " +
129                              cal.get(Calendar.DST_OFFSET) / (60*60*1000) + " " +
130                              zone.getRawOffset() / (60*60*1000) +
131                              ": HOUR = " + cal.get(Calendar.HOUR));
132                    }
133                }
134                if (bad) errln("TimeZone problems with GC");
135            }
136        } catch (MissingResourceException e) {
137            warnln("Could not load data. "+ e.getMessage());
138        }
139    }
140
141    @Test
142    public void Test4035301() {
143
144        try {
145            GregorianCalendar c = new GregorianCalendar(98, 8, 7);
146            GregorianCalendar d = new GregorianCalendar(98, 8, 7);
147            if (c.after(d) ||
148                c.after(c) ||
149                c.before(d) ||
150                c.before(c) ||
151                !c.equals(c) ||
152                !c.equals(d))
153                errln("Fail");
154        } catch (Exception e) {
155            // TODO Auto-generated catch block
156            warnln("Could not load data. "+ e.getMessage());
157        }
158    }
159
160    @Test
161    public void Test4040996() {
162        try {
163            String[] ids = TimeZone.getAvailableIDs(-8 * 60 * 60 * 1000);
164            SimpleTimeZone pdt = new SimpleTimeZone(-8 * 60 * 60 * 1000, ids[0]);
165            pdt.setStartRule(Calendar.APRIL, 1, Calendar.SUNDAY, 2 * 60 * 60 * 1000);
166            pdt.setEndRule(Calendar.OCTOBER, -1, Calendar.SUNDAY, 2 * 60 * 60 * 1000);
167            Calendar calendar = new GregorianCalendar(pdt);
168
169            calendar.set(Calendar.MONTH,3);
170            calendar.set(Calendar.DAY_OF_MONTH,18);
171            calendar.set(Calendar.SECOND, 30);
172
173            logln("MONTH: " + calendar.get(Calendar.MONTH));
174            logln("DAY_OF_MONTH: " +
175                               calendar.get(Calendar.DAY_OF_MONTH));
176            logln("MINUTE: " + calendar.get(Calendar.MINUTE));
177            logln("SECOND: " + calendar.get(Calendar.SECOND));
178
179            calendar.add(Calendar.SECOND,6);
180            //This will print out todays date for MONTH and DAY_OF_MONTH
181            //instead of the date it was set to.
182            //This happens when adding MILLISECOND or MINUTE also
183            logln("MONTH: " + calendar.get(Calendar.MONTH));
184            logln("DAY_OF_MONTH: " +
185                               calendar.get(Calendar.DAY_OF_MONTH));
186            logln("MINUTE: " + calendar.get(Calendar.MINUTE));
187            logln("SECOND: " + calendar.get(Calendar.SECOND));
188            if (calendar.get(Calendar.MONTH) != 3 ||
189                calendar.get(Calendar.DAY_OF_MONTH) != 18 ||
190                calendar.get(Calendar.SECOND) != 36)
191                errln("Fail: Calendar.add misbehaves");
192        } catch (Exception e) {
193            warnln("Could not load data. "+ e.getMessage());
194        }
195    }
196
197    @Test
198    public void Test4051765() {
199        try {
200            Calendar cal = Calendar.getInstance();
201            cal.setLenient(false);
202            cal.set(Calendar.DAY_OF_WEEK, 0);
203            try {
204                cal.getTime();
205                errln("Fail: DAY_OF_WEEK 0 should be disallowed");
206            }
207            catch (IllegalArgumentException e) {
208                return;
209            }
210        } catch (Exception e) {
211            // TODO Auto-generated catch block
212            warnln("Could not load data. "+ e.getMessage());
213        }
214    }
215
216    /*
217     * User error - no bug here public void Test4059524() { // Create calendar
218     * for April 10, 1997 GregorianCalendar calendar = new GregorianCalendar(); //
219     * print out a bunch of interesting things logln("ERA: " +
220     * calendar.get(calendar.ERA)); logln("YEAR: " +
221     * calendar.get(calendar.YEAR)); logln("MONTH: " +
222     * calendar.get(calendar.MONTH)); logln("WEEK_OF_YEAR: " +
223     * calendar.get(calendar.WEEK_OF_YEAR)); logln("WEEK_OF_MONTH: " +
224     * calendar.get(calendar.WEEK_OF_MONTH)); logln("DATE: " +
225     * calendar.get(calendar.DATE)); logln("DAY_OF_MONTH: " +
226     * calendar.get(calendar.DAY_OF_MONTH)); logln("DAY_OF_YEAR: " +
227     * calendar.get(calendar.DAY_OF_YEAR)); logln("DAY_OF_WEEK: " +
228     * calendar.get(calendar.DAY_OF_WEEK)); logln("DAY_OF_WEEK_IN_MONTH: " +
229     * calendar.get(calendar.DAY_OF_WEEK_IN_MONTH)); logln("AM_PM: " +
230     * calendar.get(calendar.AM_PM)); logln("HOUR: " +
231     * calendar.get(calendar.HOUR)); logln("HOUR_OF_DAY: " +
232     * calendar.get(calendar.HOUR_OF_DAY)); logln("MINUTE: " +
233     * calendar.get(calendar.MINUTE)); logln("SECOND: " +
234     * calendar.get(calendar.SECOND)); logln("MILLISECOND: " +
235     * calendar.get(calendar.MILLISECOND)); logln("ZONE_OFFSET: " +
236     * (calendar.get(calendar.ZONE_OFFSET)/(60*60*1000))); logln("DST_OFFSET: " +
237     * (calendar.get(calendar.DST_OFFSET)/(60*60*1000))); calendar = new
238     * GregorianCalendar(1997,3,10); calendar.getTime(); logln("April 10,
239     * 1997"); logln("ERA: " + calendar.get(calendar.ERA)); logln("YEAR: " +
240     * calendar.get(calendar.YEAR)); logln("MONTH: " +
241     * calendar.get(calendar.MONTH)); logln("WEEK_OF_YEAR: " +
242     * calendar.get(calendar.WEEK_OF_YEAR)); logln("WEEK_OF_MONTH: " +
243     * calendar.get(calendar.WEEK_OF_MONTH)); logln("DATE: " +
244     * calendar.get(calendar.DATE)); logln("DAY_OF_MONTH: " +
245     * calendar.get(calendar.DAY_OF_MONTH)); logln("DAY_OF_YEAR: " +
246     * calendar.get(calendar.DAY_OF_YEAR)); logln("DAY_OF_WEEK: " +
247     * calendar.get(calendar.DAY_OF_WEEK)); logln("DAY_OF_WEEK_IN_MONTH: " +
248     * calendar.get(calendar.DAY_OF_WEEK_IN_MONTH)); logln("AM_PM: " +
249     * calendar.get(calendar.AM_PM)); logln("HOUR: " +
250     * calendar.get(calendar.HOUR)); logln("HOUR_OF_DAY: " +
251     * calendar.get(calendar.HOUR_OF_DAY)); logln("MINUTE: " +
252     * calendar.get(calendar.MINUTE)); logln("SECOND: " +
253     * calendar.get(calendar.SECOND)); logln("MILLISECOND: " +
254     * calendar.get(calendar.MILLISECOND)); logln("ZONE_OFFSET: " +
255     * (calendar.get(calendar.ZONE_OFFSET)/(60*60*1000))); // in hours
256     * logln("DST_OFFSET: " + (calendar.get(calendar.DST_OFFSET)/(60*60*1000))); //
257     * in hours }
258     */
259
260    @Test
261    public void Test4059654() {
262   //     try {
263            // work around bug for jdk1.4 on solaris 2.6, which uses funky
264            // timezone names
265            // jdk1.4.1 will drop support for 2.6 so we should be ok when it
266            // comes out
267            java.util.TimeZone javazone = java.util.TimeZone.getTimeZone("GMT");
268            TimeZone icuzone = TimeZone.getTimeZone("GMT");
269
270            GregorianCalendar gc = new GregorianCalendar(icuzone);
271
272            gc.set(1997, 3, 1, 15, 16, 17); // April 1, 1997
273
274            gc.set(Calendar.HOUR, 0);
275            gc.set(Calendar.AM_PM, Calendar.AM);
276            gc.set(Calendar.MINUTE, 0);
277            gc.set(Calendar.SECOND, 0);
278            gc.set(Calendar.MILLISECOND, 0);
279
280            Date cd = gc.getTime();
281            java.util.Calendar cal = java.util.Calendar.getInstance(javazone);
282            cal.clear();
283            cal.set(1997, 3, 1, 0, 0, 0);
284            Date exp = cal.getTime();
285            if (!cd.equals(exp))
286                errln("Fail: Calendar.set broken. Got " + cd + " Want " + exp);
287   //     } catch (RuntimeException e) {
288            // TODO Auto-generated catch block
289   //         e.printStackTrace();
290  //      }
291    }
292
293    @Test
294    public void Test4061476() {
295        SimpleDateFormat fmt = new SimpleDateFormat("ddMMMyy", Locale.UK);
296        Calendar cal = GregorianCalendar.getInstance(TimeZone.getTimeZone("GMT"),
297                                                     Locale.UK);
298        fmt.setCalendar(cal);
299        try
300            {
301                Date date = fmt.parse("29MAY97");
302                cal.setTime(date);
303            }
304        catch (Exception e) {
305            System.out.print("");
306        }
307        cal.set(Calendar.HOUR_OF_DAY, 13);
308        logln("Hour: "+cal.get(Calendar.HOUR_OF_DAY));
309        cal.add(Calendar.HOUR_OF_DAY, 6);
310        logln("Hour: "+cal.get(Calendar.HOUR_OF_DAY));
311        if (cal.get(Calendar.HOUR_OF_DAY) != 19)
312            errln("Fail: Want 19 Got " + cal.get(Calendar.HOUR_OF_DAY));
313    }
314
315    @Test
316    public void Test4070502() {
317        java.util.Calendar tempcal = java.util.Calendar.getInstance();
318        tempcal.clear();
319        tempcal.set(1998, 0, 30);
320        Date d = getAssociatedDate(tempcal.getTime());
321        Calendar cal = new GregorianCalendar();
322        cal.setTime(d);
323        if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY ||
324            cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY)
325            errln("Fail: Want weekday Got " + d);
326    }
327
328    /**
329     * Get the associated date starting from a specified date NOTE: the
330     * unnecessary "getTime()'s" below are a work-around for a bug in jdk 1.1.3
331     * (and probably earlier versions also)
332     * <p>
333     *
334     * @param d
335     *            The date to start from
336     */
337    public static Date getAssociatedDate(Date d) {
338        GregorianCalendar cal = new GregorianCalendar();
339        cal.setTime(d);
340        //cal.add(field, amount); //<-- PROBLEM SEEN WITH field = DATE,MONTH
341        // cal.getTime(); // <--- REMOVE THIS TO SEE BUG
342        while (true) {
343            int wd = cal.get(Calendar.DAY_OF_WEEK);
344            if (wd == Calendar.SATURDAY || wd == Calendar.SUNDAY) {
345                cal.add(Calendar.DATE, 1);
346                // cal.getTime();
347            }
348            else
349                break;
350        }
351        return cal.getTime();
352    }
353
354    @Test
355    public void Test4071197() {
356        dowTest(false);
357        dowTest(true);
358    }
359
360    void dowTest(boolean lenient) {
361        GregorianCalendar cal = new GregorianCalendar();
362        cal.set(1997, Calendar.AUGUST, 12); // Wednesday
363        // cal.getTime(); // Force update
364        cal.setLenient(lenient);
365        cal.set(1996, Calendar.DECEMBER, 1); // Set the date to be December 1,
366                                             // 1996
367        int dow = cal.get(Calendar.DAY_OF_WEEK);
368        int min = cal.getMinimum(Calendar.DAY_OF_WEEK);
369        int max = cal.getMaximum(Calendar.DAY_OF_WEEK);
370        logln(cal.getTime().toString());
371        if (min != Calendar.SUNDAY || max != Calendar.SATURDAY)
372            errln("FAIL: Min/max bad");
373        if (dow < min || dow > max)
374            errln("FAIL: Day of week " + dow + " out of range");
375        if (dow != Calendar.SUNDAY)
376            errln("FAIL: Day of week should be SUNDAY Got " + dow);
377    }
378
379    @Test
380    public void Test4071385() {
381    // work around bug for jdk1.4 on solaris 2.6, which uses funky timezone
382    // names
383    // jdk1.4.1 will drop support for 2.6 so we should be ok when it comes out
384    java.util.TimeZone javazone = java.util.TimeZone.getTimeZone("GMT");
385    TimeZone icuzone = TimeZone.getTimeZone("GMT");
386
387        Calendar cal = Calendar.getInstance(icuzone);
388        java.util.Calendar tempcal = java.util.Calendar.getInstance(javazone);
389        tempcal.clear();
390        tempcal.set(1998, Calendar.JUNE, 24);
391        cal.setTime(tempcal.getTime());
392        cal.set(Calendar.MONTH, Calendar.NOVEMBER); // change a field
393        logln(cal.getTime().toString());
394        tempcal.set(1998, Calendar.NOVEMBER, 24);
395        if (!cal.getTime().equals(tempcal.getTime()))
396            errln("Fail");
397    }
398
399    @Test
400    public void Test4073929() {
401        GregorianCalendar foo1 = new GregorianCalendar(1997, 8, 27);
402        foo1.add(Calendar.DAY_OF_MONTH, +1);
403        int testyear = foo1.get(Calendar.YEAR);
404        int testmonth = foo1.get(Calendar.MONTH);
405        int testday = foo1.get(Calendar.DAY_OF_MONTH);
406        if (testyear != 1997 ||
407            testmonth != 8 ||
408            testday != 28)
409            errln("Fail: Calendar not initialized");
410    }
411
412    @Test
413    public void Test4083167() {
414        TimeZone saveZone = TimeZone.getDefault();
415        try {
416            TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
417            Date firstDate = new Date();
418            Calendar cal = new GregorianCalendar();
419            cal.setTime(firstDate);
420            long firstMillisInDay = cal.get(Calendar.HOUR_OF_DAY) * 3600000L +
421                cal.get(Calendar.MINUTE) * 60000L +
422                cal.get(Calendar.SECOND) * 1000L +
423                cal.get(Calendar.MILLISECOND);
424
425            logln("Current time: " + firstDate.toString());
426
427            for (int validity=0; validity<30; validity++) {
428                Date lastDate = new Date(firstDate.getTime() +
429                                         (long)validity*1000*24*60*60);
430                cal.setTime(lastDate);
431                long millisInDay = cal.get(Calendar.HOUR_OF_DAY) * 3600000L +
432                    cal.get(Calendar.MINUTE) * 60000L +
433                    cal.get(Calendar.SECOND) * 1000L +
434                    cal.get(Calendar.MILLISECOND);
435                if (firstMillisInDay != millisInDay)
436                    errln("Day has shifted " + lastDate);
437            }
438        }
439        finally {
440            TimeZone.setDefault(saveZone);
441        }
442    }
443
444    @Test
445    public void Test4086724() {
446        SimpleDateFormat date;
447        TimeZone saveZone = TimeZone.getDefault();
448        Locale saveLocale = Locale.getDefault();
449        try {
450            Locale.setDefault(Locale.UK);
451            TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
452            date=new SimpleDateFormat("dd MMM yyy (zzzz) 'is in week' ww");
453            Calendar cal=Calendar.getInstance();
454            cal.set(1997,Calendar.SEPTEMBER,30);
455            Date now=cal.getTime();
456            logln(date.format(now));
457            cal.set(1997,Calendar.JANUARY,1);
458            now=cal.getTime();
459            logln(date.format(now));
460            cal.set(1997,Calendar.JANUARY,8);
461            now=cal.getTime();
462            logln(date.format(now));
463            cal.set(1996,Calendar.DECEMBER,31);
464            now=cal.getTime();
465            logln(date.format(now));
466        }
467        finally {
468            Locale.setDefault(saveLocale);
469            TimeZone.setDefault(saveZone);
470        }
471        logln("*** THE RESULTS OF THIS TEST MUST BE VERIFIED MANUALLY ***");
472    }
473
474    @Test
475    public void Test4092362() {
476        GregorianCalendar cal1 = new GregorianCalendar(1997, 10, 11, 10, 20, 40);
477        /*
478         * cal1.set( Calendar.YEAR, 1997 ); cal1.set( Calendar.MONTH, 10 );
479         * cal1.set( Calendar.DATE, 11 ); cal1.set( Calendar.HOUR, 10 );
480         * cal1.set( Calendar.MINUTE, 20 ); cal1.set( Calendar.SECOND, 40 );
481         */
482
483        logln( " Cal1 = " + cal1.getTime().getTime() );
484        logln( " Cal1 time in ms = " + cal1.get(Calendar.MILLISECOND) );
485        for( int k = 0; k < 100 ; k++ ) {
486            System.out.print("");
487        }
488
489        GregorianCalendar cal2 = new GregorianCalendar(1997, 10, 11, 10, 20, 40);
490        /*
491         * cal2.set( Calendar.YEAR, 1997 ); cal2.set( Calendar.MONTH, 10 );
492         * cal2.set( Calendar.DATE, 11 ); cal2.set( Calendar.HOUR, 10 );
493         * cal2.set( Calendar.MINUTE, 20 ); cal2.set( Calendar.SECOND, 40 );
494         */
495
496        logln( " Cal2 = " + cal2.getTime().getTime() );
497        logln( " Cal2 time in ms = " + cal2.get(Calendar.MILLISECOND) );
498        if( !cal1.equals( cal2 ) )
499            errln("Fail: Milliseconds randomized");
500    }
501
502    @Test
503    public void Test4095407() {
504        GregorianCalendar a = new GregorianCalendar(1997,Calendar.NOVEMBER, 13);
505        int dow = a.get(Calendar.DAY_OF_WEEK);
506        if (dow != Calendar.THURSDAY)
507            errln("Fail: Want THURSDAY Got " + dow);
508    }
509
510    @Test
511    public void Test4096231() {
512        TimeZone GMT = TimeZone.getTimeZone("GMT");
513        TimeZone PST = TimeZone.getTimeZone("PST");
514        int sec = 0, min = 0, hr = 0, day = 1, month = 10, year = 1997;
515
516        Calendar cal1 = new GregorianCalendar(PST);
517        cal1.setTime(new Date(880698639000L));
518        int p;
519        logln("PST 1 is: " + (p=cal1.get(Calendar.HOUR_OF_DAY)));
520        cal1.setTimeZone(GMT);
521        // Issue 1: Changing the timezone doesn't change the
522        //          represented time.
523        int h1,h2;
524        logln("GMT 1 is: " + (h1=cal1.get(Calendar.HOUR_OF_DAY)));
525        cal1.setTime(new Date(880698639000L));
526        logln("GMT 2 is: " + (h2=cal1.get(Calendar.HOUR_OF_DAY)));
527        // Note: This test had a bug in it. It wanted h1!=h2, when
528        // what was meant was h1!=p. Fixed this concurrent with fix
529        // to 4177484.
530        if (p == h1 || h1 != h2)
531            errln("Fail: Hour same in different zones");
532
533        Calendar cal2 = new GregorianCalendar(GMT);
534        Calendar cal3 = new GregorianCalendar(PST);
535        cal2.set(Calendar.MILLISECOND, 0);
536        cal3.set(Calendar.MILLISECOND, 0);
537
538        cal2.set(cal1.get(Calendar.YEAR),
539                 cal1.get(Calendar.MONTH),
540                 cal1.get(Calendar.DAY_OF_MONTH),
541                 cal1.get(Calendar.HOUR_OF_DAY),
542                 cal1.get(Calendar.MINUTE),
543                 cal1.get(Calendar.SECOND));
544
545        long t1,t2,t3,t4;
546        logln("RGMT 1 is: " + (t1=cal2.getTime().getTime()));
547        cal3.set(year, month, day, hr, min, sec);
548        logln("RPST 1 is: " + (t2=cal3.getTime().getTime()));
549        cal3.setTimeZone(GMT);
550        logln("RGMT 2 is: " + (t3=cal3.getTime().getTime()));
551        cal3.set(cal1.get(Calendar.YEAR),
552                 cal1.get(Calendar.MONTH),
553                 cal1.get(Calendar.DAY_OF_MONTH),
554                 cal1.get(Calendar.HOUR_OF_DAY),
555                 cal1.get(Calendar.MINUTE),
556                 cal1.get(Calendar.SECOND));
557        // Issue 2: Calendar continues to use the timezone in its
558        //          constructor for set() conversions, regardless
559        //          of calls to setTimeZone()
560        logln("RGMT 3 is: " + (t4=cal3.getTime().getTime()));
561        if (t1 == t2 ||
562            t1 != t4 ||
563            t2 != t3)
564            errln("Fail: Calendar zone behavior faulty");
565    }
566
567    @Test
568    public void Test4096539() {
569        int[] y = {31,28,31,30,31,30,31,31,30,31,30,31};
570
571        for (int x=0;x<12;x++) {
572            GregorianCalendar gc = new
573                GregorianCalendar(1997,x,y[x]);
574            int m1,m2;
575            log((m1=gc.get(Calendar.MONTH)+1)+"/"+
576                             gc.get(Calendar.DATE)+"/"+gc.get(Calendar.YEAR)+
577                             " + 1mo = ");
578
579            gc.add(Calendar.MONTH, 1);
580            logln((m2=gc.get(Calendar.MONTH)+1)+"/"+
581                               gc.get(Calendar.DATE)+"/"+gc.get(Calendar.YEAR)
582                               );
583            int m = (m1 % 12) + 1;
584            if (m2 != m)
585                errln("Fail: Want " + m + " Got " + m2);
586        }
587
588    }
589
590    @Test
591    public void Test4100311() {
592        GregorianCalendar cal = (GregorianCalendar)Calendar.getInstance();
593        cal.set(Calendar.YEAR, 1997);
594        cal.set(Calendar.DAY_OF_YEAR, 1);
595        Date d = cal.getTime();             // Should be Jan 1
596        logln(d.toString());
597        if (cal.get(Calendar.DAY_OF_YEAR) != 1)
598            errln("Fail: DAY_OF_YEAR not set");
599    }
600
601    @Test
602    public void Test4103271() {
603        SimpleDateFormat sdf = new SimpleDateFormat();
604        int numYears=40, startYear=1997, numDays=15;
605        String output, testDesc;
606        GregorianCalendar testCal = (GregorianCalendar)Calendar.getInstance();
607        testCal.clear();
608        sdf.setCalendar(testCal);
609        sdf.applyPattern("d MMM yyyy");
610        boolean fail = false;
611        for (int firstDay=1; firstDay<=2; firstDay++) {
612            for (int minDays=1; minDays<=7; minDays++) {
613                testCal.setMinimalDaysInFirstWeek(minDays);
614                testCal.setFirstDayOfWeek(firstDay);
615                testDesc = ("Test" + String.valueOf(firstDay) + String.valueOf(minDays));
616                logln(testDesc + " => 1st day of week=" +
617                                   String.valueOf(firstDay) +
618                                   ", minimum days in first week=" +
619                                   String.valueOf(minDays));
620                for (int j=startYear; j<=startYear+numYears; j++) {
621                    testCal.set(j,11,25);
622                    for(int i=0; i<numDays; i++) {
623                        testCal.add(Calendar.DATE,1);
624                        String calWOY;
625                        int actWOY = testCal.get(Calendar.WEEK_OF_YEAR);
626                        if (actWOY < 1 || actWOY > 53) {
627                            Date d = testCal.getTime();
628                            calWOY = String.valueOf(actWOY);
629                            output = testDesc + " - " + sdf.format(d) + "\t";
630                            output = output + "\t" + calWOY;
631                            logln(output);
632                            fail = true;
633                        }
634                    }
635                }
636            }
637        }
638
639        int[] DATA = {
640            3, 52, 52, 52, 52, 52, 52, 52,
641                1,  1,  1,  1,  1,  1,  1,
642                2,  2,  2,  2,  2,  2,  2,
643            4, 52, 52, 52, 52, 52, 52, 52,
644               53, 53, 53, 53, 53, 53, 53,
645                1,  1,  1,  1,  1,  1,  1,
646        };
647        testCal.setFirstDayOfWeek(Calendar.SUNDAY);
648        for (int j=0; j<DATA.length; j+=22) {
649            logln("Minimal days in first week = " + DATA[j] +
650                               "  Week starts on Sunday");
651            testCal.setMinimalDaysInFirstWeek(DATA[j]);
652            testCal.set(1997, Calendar.DECEMBER, 21);
653            for (int i=0; i<21; ++i) {
654                int woy = testCal.get(Calendar.WEEK_OF_YEAR);
655                log(testCal.getTime() + " " + woy);
656                if (woy != DATA[j + 1 + i]) {
657                    log(" ERROR");
658                    fail = true;
659                }
660                //logln();
661
662                // Now compute the time from the fields, and make sure we
663                // get the same answer back. This is a round-trip test.
664                Date save = testCal.getTime();
665                testCal.clear();
666                testCal.set(Calendar.YEAR, DATA[j+1+i] < 25 ? 1998 : 1997);
667                testCal.set(Calendar.WEEK_OF_YEAR, DATA[j+1+i]);
668                testCal.set(Calendar.DAY_OF_WEEK, (i%7) + Calendar.SUNDAY);
669                if (!testCal.getTime().equals(save)) {
670                    logln("  Parse failed: " + testCal.getTime());
671                    fail= true;
672                }
673
674                testCal.setTime(save);
675                testCal.add(Calendar.DAY_OF_MONTH, 1);
676            }
677        }
678
679        Date d[] = new Date[8];
680        java.util.Calendar tempcal = java.util.Calendar.getInstance();
681        tempcal.clear();
682        tempcal.set(1997, Calendar.DECEMBER, 28);
683        d[0] = tempcal.getTime();
684        tempcal.set(1998, Calendar.JANUARY, 10);
685        d[1] = tempcal.getTime();
686        tempcal.set(1998, Calendar.DECEMBER, 31);
687        d[2] = tempcal.getTime();
688        tempcal.set(1999, Calendar.JANUARY, 1);
689        d[3] = tempcal.getTime();
690        // Test field disambiguation with a few special hard-coded cases.
691        // This shouldn't fail if the above cases aren't failing.
692        Object[] DISAM = {
693            new Integer(1998), new Integer(1), new Integer(Calendar.SUNDAY),
694                d[0],
695            new Integer(1998), new Integer(2), new Integer(Calendar.SATURDAY),
696                d[1],
697            new Integer(1998), new Integer(53), new Integer(Calendar.THURSDAY),
698                d[2],
699            new Integer(1998), new Integer(53), new Integer(Calendar.FRIDAY),
700                d[3],
701        };
702        testCal.setMinimalDaysInFirstWeek(3);
703        testCal.setFirstDayOfWeek(Calendar.SUNDAY);
704        for (int i=0; i<DISAM.length; i+=4) {
705            int y = ((Integer)DISAM[i]).intValue();
706            int woy = ((Integer)DISAM[i+1]).intValue();
707            int dow = ((Integer)DISAM[i+2]).intValue();
708            Date exp = (Date)DISAM[i+3];
709            testCal.clear();
710            testCal.set(Calendar.YEAR, y);
711            testCal.set(Calendar.WEEK_OF_YEAR, woy);
712            testCal.set(Calendar.DAY_OF_WEEK, dow);
713            log(y + "-W" + woy +
714                             "-DOW" + dow + " expect:" + exp +
715                             " got:" + testCal.getTime());
716            if (!testCal.getTime().equals(exp)) {
717                log("  FAIL");
718                fail = true;
719            }
720            //logln();
721        }
722
723        // Now try adding and rolling
724        Object ADD = new Object();
725        Object ROLL = new Object();
726        tempcal.set(1998, Calendar.DECEMBER, 25);
727        d[0] = tempcal.getTime();
728        tempcal.set(1999, Calendar.JANUARY, 1);
729        d[1] = tempcal.getTime();
730        tempcal.set(1997, Calendar.DECEMBER, 28);
731        d[2] = tempcal.getTime();
732        tempcal.set(1998, Calendar.JANUARY, 4);
733        d[3] = tempcal.getTime();
734        tempcal.set(1998, Calendar.DECEMBER, 27);
735        d[4] = tempcal.getTime();
736        tempcal.set(1997, Calendar.DECEMBER, 28);
737        d[5] = tempcal.getTime();
738        tempcal.set(1999, Calendar.JANUARY, 2);
739        d[6] = tempcal.getTime();
740        tempcal.set(1998, Calendar.JANUARY, 3);
741        d[7] = tempcal.getTime();
742
743        Object[] ADDROLL = {
744            ADD, new Integer(1), d[0], d[1],
745            ADD, new Integer(1), d[2], d[3],
746            ROLL, new Integer(1), d[4], d[5],
747            ROLL, new Integer(1), d[6], d[7],
748        };
749        testCal.setMinimalDaysInFirstWeek(3);
750        testCal.setFirstDayOfWeek(Calendar.SUNDAY);
751        for (int i=0; i<ADDROLL.length; i+=4) {
752            int amount = ((Integer)ADDROLL[i+1]).intValue();
753            Date before = (Date)ADDROLL[i+2];
754            Date after = (Date)ADDROLL[i+3];
755
756            testCal.setTime(before);
757            if (ADDROLL[i] == ADD) testCal.add(Calendar.WEEK_OF_YEAR, amount);
758            else testCal.roll(Calendar.WEEK_OF_YEAR, amount);
759            log((ADDROLL[i]==ADD?"add(WOY,":"roll(WOY,") +
760                             amount + ") " + before + " => " +
761                             testCal.getTime());
762            if (!after.equals(testCal.getTime())) {
763                logln("  exp:" + after + "  FAIL");
764                fail = true;
765            }
766            else logln(" ok");
767
768            testCal.setTime(after);
769            if (ADDROLL[i] == ADD) testCal.add(Calendar.WEEK_OF_YEAR, -amount);
770            else testCal.roll(Calendar.WEEK_OF_YEAR, -amount);
771            log((ADDROLL[i]==ADD?"add(WOY,":"roll(WOY,") +
772                             (-amount) + ") " + after + " => " +
773                             testCal.getTime());
774            if (!before.equals(testCal.getTime())) {
775                logln("  exp:" + before + "  FAIL");
776                fail = true;
777            }
778            else logln(" ok");
779        }
780
781        if (fail) errln("Fail: Week of year misbehaving");
782    }
783
784    @Test
785    public void Test4106136() {
786        Locale saveLocale = Locale.getDefault();
787        String[] names = { "Calendar", "DateFormat", "NumberFormat" };
788        try {
789            Locale[] locales = { Locale.CHINESE, Locale.CHINA };
790            for (int i=0; i<locales.length; ++i) {
791                Locale.setDefault(locales[i]);
792                int[] n = {
793                    Calendar.getAvailableLocales().length,
794                    DateFormat.getAvailableLocales().length,
795                    NumberFormat.getAvailableLocales().length
796                };
797                for (int j=0; j<n.length; ++j) {
798                    if (n[j] == 0)
799                        errln("Fail: " + names[j] + " has no locales for " + locales[i]);
800                }
801            }
802        }
803        finally {
804            Locale.setDefault(saveLocale);
805        }
806    }
807
808    @Test
809    public void Test4108764() {
810        java.util.Calendar tempcal = java.util.Calendar.getInstance();
811        tempcal.clear();
812        tempcal.set(1997, Calendar.FEBRUARY, 15, 12, 00, 00);
813        Date d00 = tempcal.getTime();
814        tempcal.set(1997, Calendar.FEBRUARY, 15, 12, 00, 56);
815        Date d01 = tempcal.getTime();
816        tempcal.set(1997, Calendar.FEBRUARY, 15, 12, 34, 00);
817        Date d10 = tempcal.getTime();
818        tempcal.set(1997, Calendar.FEBRUARY, 15, 12, 34, 56);
819        Date d11 = tempcal.getTime();
820        tempcal.set(1997, Calendar.JANUARY, 15, 12, 34, 56);
821        Date dM  = tempcal.getTime();
822        tempcal.clear();
823        tempcal.set(1970, Calendar.JANUARY, 1);
824        Date epoch = tempcal.getTime();
825
826        Calendar cal = Calendar.getInstance();
827        cal.setTime(d11);
828
829        cal.clear( Calendar.MINUTE );
830        logln(cal.getTime().toString());
831        if (!cal.getTime().equals(d01)) {
832            errln("Fail: " + d11 + " clear(MINUTE) => expect " +
833                  d01 + ", got " + cal.getTime());
834        }
835
836        cal.set( Calendar.SECOND, 0 );
837        logln(cal.getTime().toString());
838        if (!cal.getTime().equals(d00))
839            errln("Fail: set(SECOND, 0) broken");
840
841        cal.setTime(d11);
842        cal.set( Calendar.SECOND, 0 );
843        logln(cal.getTime().toString());
844        if (!cal.getTime().equals(d10))
845            errln("Fail: set(SECOND, 0) broken #2");
846
847        cal.clear( Calendar.MINUTE );
848        logln(cal.getTime().toString());
849        if (!cal.getTime().equals(d00))
850            errln("Fail: clear(MINUTE) broken #2");
851
852        cal.clear();
853        logln(cal.getTime().toString());
854        if (!cal.getTime().equals(epoch))
855            errln("Fail: after clear() expect " + epoch + ", got " + cal.getTime());
856
857        cal.setTime(d11);
858        cal.clear( Calendar.MONTH );
859        logln(cal.getTime().toString());
860        if (!cal.getTime().equals(dM)) {
861            errln("Fail: " + d11 + " clear(MONTH) => expect " +
862                  dM + ", got " + cal.getTime());
863        }
864    }
865
866    @Test
867    public void Test4114578() {
868        int ONE_HOUR = 60*60*1000;
869        Calendar cal = Calendar.getInstance();
870        cal.setTimeZone(TimeZone.getTimeZone("PST"));
871
872        java.util.Calendar tempcal = java.util.Calendar.getInstance();
873        tempcal.clear();
874        tempcal.set(1998, Calendar.APRIL, 5, 1, 0);
875        long onset = tempcal.getTime().getTime() + ONE_HOUR;
876        tempcal.set(1998, Calendar.OCTOBER, 25, 0, 0);
877        long cease = tempcal.getTime().getTime() + 2*ONE_HOUR;
878
879        boolean fail = false;
880
881        final int ADD = 1;
882        final int ROLL = 2;
883
884        long[] DATA = {
885            // Start Action Amt Expected_change
886            onset - ONE_HOUR,   ADD,      1,     ONE_HOUR,
887            onset,              ADD,     -1,    -ONE_HOUR,
888            onset - ONE_HOUR,   ROLL,     1,     ONE_HOUR,
889            onset,              ROLL,    -1,    -ONE_HOUR,
890            cease - ONE_HOUR,   ADD,      1,     ONE_HOUR,
891            cease,              ADD,     -1,    -ONE_HOUR,
892            cease - ONE_HOUR,   ROLL,     1,     ONE_HOUR,
893            cease,              ROLL,    -1,    -ONE_HOUR,
894        };
895
896        for (int i=0; i<DATA.length; i+=4) {
897            Date date = new Date(DATA[i]);
898            int amt = (int) DATA[i+2];
899            long expectedChange = DATA[i+3];
900
901            log(date.toString());
902            cal.setTime(date);
903
904            switch ((int) DATA[i+1]) {
905            case ADD:
906                log(" add (HOUR," + (amt<0?"":"+")+amt + ")= ");
907                cal.add(Calendar.HOUR, amt);
908                break;
909            case ROLL:
910                log(" roll(HOUR," + (amt<0?"":"+")+amt + ")= ");
911                cal.roll(Calendar.HOUR, amt);
912                break;
913            }
914
915            log(cal.getTime().toString());
916
917            long change = cal.getTime().getTime() - date.getTime();
918            if (change != expectedChange) {
919                fail = true;
920                logln(" FAIL");
921            }
922            else logln(" OK");
923        }
924
925        if (fail) errln("Fail: roll/add misbehaves around DST onset/cease");
926    }
927
928    /**
929     * Make sure maximum for HOUR field is 11, not 12.
930     */
931    @Test
932    public void Test4118384() {
933        Calendar cal = Calendar.getInstance();
934        if (cal.getMaximum(Calendar.HOUR) != 11 ||
935            cal.getLeastMaximum(Calendar.HOUR) != 11 ||
936            cal.getActualMaximum(Calendar.HOUR) != 11)
937            errln("Fail: maximum of HOUR field should be 11");
938    }
939
940    /**
941     * Check isLeapYear for BC years.
942     */
943    @Test
944    public void Test4125881() {
945        GregorianCalendar cal = (GregorianCalendar) Calendar.getInstance();
946        DateFormat fmt = new SimpleDateFormat("MMMM d, yyyy G");
947        cal.clear();
948        for (int y=-20; y<=10; ++y) {
949            cal.set(Calendar.ERA, y < 1 ? GregorianCalendar.BC : GregorianCalendar.AD);
950            cal.set(Calendar.YEAR, y < 1 ? 1 - y : y);
951            logln(y + " = " + fmt.format(cal.getTime()) + " " +
952                               cal.isLeapYear(y));
953            if (cal.isLeapYear(y) != ((y+40)%4 == 0))
954                errln("Leap years broken");
955        }
956    }
957
958    // I am disabling this test -- it is currently failing because of a bug
959    // in Sun's latest change to STZ.getOffset(). I have filed a Sun bug
960    // against this problem.
961
962    // Re-enabled after 'porting' TZ and STZ from java.util to android.icu.util.
963    /**
964     * Prove that GregorianCalendar is proleptic (it used to cut off at 45 BC,
965     * and not have leap years before then).
966     */
967    @Test
968    public void Test4125892() {
969        GregorianCalendar cal = (GregorianCalendar) Calendar.getInstance();
970        //DateFormat fmt = new SimpleDateFormat("MMMM d, yyyy G");
971        //fmt = null;
972        cal.clear();
973        cal.set(Calendar.ERA, GregorianCalendar.BC);
974        cal.set(Calendar.YEAR, 81); // 81 BC is a leap year (proleptically)
975        cal.set(Calendar.MONTH, Calendar.FEBRUARY);
976        cal.set(Calendar.DATE, 28);
977        cal.add(Calendar.DATE, 1);
978        if (cal.get(Calendar.DATE) != 29 ||
979            !cal.isLeapYear(-80)) // -80 == 81 BC
980            errln("Calendar not proleptic");
981    }
982
983    /**
984     * Calendar and GregorianCalendar hashCode() methods need improvement.
985     * Calendar needs a good implementation that subclasses can override, and
986     * GregorianCalendar should use that implementation.
987     */
988    @Test
989    public void Test4136399() {
990        /*
991         * Note: This test is actually more strict than it has to be.
992         * Technically, there is no requirement that unequal objects have
993         * unequal hashes. We only require equal objects to have equal hashes.
994         * It is desirable for unequal objects to have distributed hashes, but
995         * there is no hard requirement here.
996         *
997         * In this test we make assumptions about certain attributes of calendar
998         * objects getting represented in the hash, which need not always be the
999         * case (although it does work currently with the given test).
1000         */
1001        Calendar a = Calendar.getInstance();
1002        Calendar b = (Calendar)a.clone();
1003        if (a.hashCode() != b.hashCode()) {
1004            errln("Calendar hash code unequal for cloned objects");
1005        }
1006        TimeZone atz1 = a.getTimeZone();
1007        TimeZone atz2 = (TimeZone)atz1.clone();
1008        if(!atz1.equals(atz2)){
1009            errln("The clone timezones are not equal");
1010        }
1011        if(atz1.hashCode()!=atz2.hashCode()){
1012            errln("TimeZone hash code unequal for cloned objects");
1013        }
1014        b.setMinimalDaysInFirstWeek(7 - a.getMinimalDaysInFirstWeek());
1015        if (a.hashCode() == b.hashCode()) {
1016            errln("Calendar hash code ignores minimal days in first week");
1017        }
1018        b.setMinimalDaysInFirstWeek(a.getMinimalDaysInFirstWeek());
1019
1020        b.setFirstDayOfWeek((a.getFirstDayOfWeek() % 7) + 1); // Next day
1021        if (a.hashCode() == b.hashCode()) {
1022            errln("Calendar hash code ignores first day of week");
1023        }
1024        b.setFirstDayOfWeek(a.getFirstDayOfWeek());
1025
1026        b.setLenient(!a.isLenient());
1027        if (a.hashCode() == b.hashCode()) {
1028            errln("Calendar hash code ignores lenient setting");
1029        }
1030        b.setLenient(a.isLenient());
1031
1032        // Assume getTimeZone() returns a reference, not a clone
1033        // of a reference -- this is true as of this writing
1034        TimeZone atz = a.getTimeZone();
1035        TimeZone btz = b.getTimeZone();
1036
1037        btz.setRawOffset(atz.getRawOffset() + 60*60*1000);
1038        if(atz.hashCode()== btz.hashCode()){
1039            errln(atz.hashCode()+"=="+btz.hashCode());
1040        }
1041        if (a.getTimeZone()!= b.getTimeZone() && a.hashCode() == b.hashCode()) {
1042            errln("Calendar hash code ignores zone");
1043        }
1044        b.getTimeZone().setRawOffset(a.getTimeZone().getRawOffset());
1045
1046        GregorianCalendar c = new GregorianCalendar();
1047        GregorianCalendar d = (GregorianCalendar)c.clone();
1048        if (c.hashCode() != d.hashCode()) {
1049            errln("GregorianCalendar hash code unequal for clones objects");
1050        }
1051        Date cutover = c.getGregorianChange();
1052        d.setGregorianChange(new Date(cutover.getTime() + 24*60*60*1000));
1053        if (c.hashCode() == d.hashCode()) {
1054            errln("GregorianCalendar hash code ignores cutover");
1055        }
1056    }
1057
1058    /**
1059     * GregorianCalendar.equals() ignores cutover date
1060     */
1061    @Test
1062    public void Test4141665() {
1063        GregorianCalendar cal = new GregorianCalendar();
1064        GregorianCalendar cal2 = (GregorianCalendar)cal.clone();
1065        Date cut = cal.getGregorianChange();
1066        Date cut2 = new Date(cut.getTime() + 100*24*60*60*1000L); // 100 days
1067                                                                  // later
1068        if (!cal.equals(cal2)) {
1069            errln("Cloned GregorianCalendars not equal");
1070        }
1071        cal2.setGregorianChange(cut2);
1072        if (cal.equals(cal2)) {
1073            errln("GregorianCalendar.equals() ignores cutover");
1074        }
1075    }
1076
1077    /**
1078     * Bug states that ArrayIndexOutOfBoundsException is thrown by
1079     * GregorianCalendar.roll() when IllegalArgumentException should be.
1080     */
1081    @Test
1082    public void Test4142933() {
1083        GregorianCalendar calendar = new GregorianCalendar();
1084        try {
1085            calendar.roll(-1, true);
1086            errln("Test failed, no exception trown");
1087        }
1088        catch (IllegalArgumentException e) {
1089            // OK: Do nothing
1090            // logln("Test passed");
1091            System.out.print("");
1092        }
1093        catch (Exception e) {
1094            errln("Test failed. Unexpected exception is thrown: " + e);
1095            e.printStackTrace();
1096        }
1097    }
1098
1099    /**
1100     * GregorianCalendar handling of Dates Long.MIN_VALUE and Long.MAX_VALUE is
1101     * confusing; unless the time zone has a raw offset of zero, one or the
1102     * other of these will wrap. We've modified the test given in the bug report
1103     * to therefore only check the behavior of a calendar with a zero raw offset
1104     * zone.
1105     */
1106    @Test
1107    public void Test4145158() {
1108        GregorianCalendar calendar = new GregorianCalendar();
1109
1110        calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
1111
1112        calendar.setTime(new Date(Long.MIN_VALUE));
1113        int year1 = calendar.get(Calendar.YEAR);
1114        int era1 = calendar.get(Calendar.ERA);
1115
1116        calendar.setTime(new Date(Long.MAX_VALUE));
1117        int year2 = calendar.get(Calendar.YEAR);
1118        int era2 = calendar.get(Calendar.ERA);
1119
1120        if (year1 == year2 && era1 == era2) {
1121            errln("Fail: Long.MIN_VALUE or Long.MAX_VALUE wrapping around");
1122        }
1123    }
1124
1125    /**
1126     * Maximum value for YEAR field wrong.
1127     */
1128    @Test
1129    public void Test4145983() {
1130        GregorianCalendar calendar = new GregorianCalendar();
1131        calendar.setTimeZone(TimeZone.getTimeZone("GMT"));
1132        Date[] DATES = { new Date(Long.MAX_VALUE), new Date(Long.MIN_VALUE) };
1133        for (int i=0; i<DATES.length; ++i) {
1134            calendar.setTime(DATES[i]);
1135            int year = calendar.get(Calendar.YEAR);
1136            int maxYear = calendar.getMaximum(Calendar.YEAR);
1137            if (year > maxYear) {
1138                errln("Failed for "+DATES[i].getTime()+" ms: year=" +
1139                      year + ", maxYear=" + maxYear);
1140            }
1141        }
1142    }
1143
1144    /**
1145     * This is a bug in the validation code of GregorianCalendar. As reported,
1146     * the bug seems worse than it really is, due to a bug in the way the bug
1147     * report test was written. In reality the bug is restricted to the
1148     * DAY_OF_YEAR field. - liu 6/29/98
1149     */
1150    @Test
1151    public void Test4147269() {
1152        GregorianCalendar calendar = new GregorianCalendar();
1153        calendar.setLenient(false);
1154        java.util.Calendar tempcal = java.util.Calendar.getInstance();
1155        tempcal.clear();
1156        tempcal.set(1996, Calendar.JANUARY, 3); // Arbitrary date
1157        Date date = tempcal.getTime();
1158        for (int field = 0; field < calendar.getFieldCount(); field++) {
1159            calendar.setTime(date);
1160            // Note: In the bug report, getActualMaximum() was called instead
1161            // of getMaximum() -- this was an error. The validation code doesn't
1162            // use getActualMaximum(), since that's too costly.
1163            int max = calendar.getMaximum(field);
1164            int value = max+1;
1165            calendar.set(field, value);
1166            try {
1167                calendar.getTime(); // Force time computation
1168                // We expect an exception to be thrown. If we fall through
1169                // to the next line, then we have a bug.
1170                errln("Test failed with field " + FIELD_NAME[field] +
1171                      ", date before: " + date +
1172                      ", date after: " + calendar.getTime() +
1173                      ", value: " + value + " (max = " + max +")");
1174            } catch (IllegalArgumentException e) {
1175                System.out.print("");
1176            }
1177        }
1178    }
1179
1180    /**
1181     * Reported bug is that a GregorianCalendar with a cutover of
1182     * Date(Long.MAX_VALUE) doesn't behave as a pure Julian calendar. CANNOT
1183     * REPRODUCE THIS BUG
1184     */
1185    @Test
1186    public void Test4149677() {
1187        TimeZone[] zones = { TimeZone.getTimeZone("GMT"),
1188                             TimeZone.getTimeZone("PST"),
1189                             TimeZone.getTimeZone("EAT") };
1190        for (int i=0; i<zones.length; ++i) {
1191            GregorianCalendar calendar = new GregorianCalendar(zones[i]);
1192
1193            // Make sure extreme values don't wrap around
1194            calendar.setTime(new Date(Long.MIN_VALUE));
1195            if (calendar.get(Calendar.ERA) != GregorianCalendar.BC) {
1196                errln("Fail: Long.MIN_VALUE ms has an AD year");
1197            }
1198            calendar.setTime(new Date(Long.MAX_VALUE));
1199            if (calendar.get(Calendar.ERA) != GregorianCalendar.AD) {
1200                errln("Fail: Long.MAX_VALUE ms has a BC year");
1201            }
1202
1203            calendar.setGregorianChange(new Date(Long.MAX_VALUE));
1204            // to obtain a pure Julian calendar
1205
1206            boolean is100Leap = calendar.isLeapYear(100);
1207            if (!is100Leap) {
1208                errln("test failed with zone " + zones[i].getID());
1209                errln(" cutover date is Calendar.MAX_DATE");
1210                errln(" isLeapYear(100) returns: " + is100Leap);
1211            }
1212        }
1213    }
1214
1215    /**
1216     * Calendar and Date HOUR broken. If HOUR is out-of-range, Calendar and Date
1217     * classes will misbehave.
1218     */
1219    @Test
1220    public void Test4162587() {
1221        TimeZone tz = TimeZone.getTimeZone("PST");
1222        TimeZone.setDefault(tz);
1223        GregorianCalendar cal = new GregorianCalendar(tz);
1224        Date d;
1225
1226        for (int i=0; i<5; ++i) {
1227            if (i>0) logln("---");
1228
1229            cal.clear();
1230            cal.set(1998, Calendar.APRIL, 5, i, 0);
1231            d = cal.getTime();
1232            String s0 = d.toString();
1233            logln("0 " + i + ": " + s0);
1234
1235            cal.clear();
1236            cal.set(1998, Calendar.APRIL, 4, i+24, 0);
1237            d = cal.getTime();
1238            String sPlus = d.toString();
1239            logln("+ " + i + ": " + sPlus);
1240
1241            cal.clear();
1242            cal.set(1998, Calendar.APRIL, 6, i-24, 0);
1243            d = cal.getTime();
1244            String sMinus = d.toString();
1245            logln("- " + i + ": " + sMinus);
1246
1247            if (!s0.equals(sPlus) || !s0.equals(sMinus)) {
1248                errln("Fail: All three lines must match");
1249            }
1250        }
1251    }
1252
1253    /**
1254     * Adding 12 months behaves differently from adding 1 year
1255     */
1256    @Test
1257    public void Test4165343() {
1258        GregorianCalendar calendar = new GregorianCalendar(1996, Calendar.FEBRUARY, 29);
1259        Date start = calendar.getTime();
1260        logln("init date: " + start);
1261        calendar.add(Calendar.MONTH, 12);
1262        Date date1 = calendar.getTime();
1263        logln("after adding 12 months: " + date1);
1264        calendar.setTime(start);
1265        calendar.add(Calendar.YEAR, 1);
1266        Date date2 = calendar.getTime();
1267        logln("after adding one year : " + date2);
1268        if (date1.equals(date2)) {
1269            logln("Test passed");
1270        } else {
1271            errln("Test failed");
1272        }
1273    }
1274
1275    /**
1276     * GregorianCalendar.getActualMaximum() does not account for first day of
1277     * week.
1278     */
1279    @Test
1280    public void Test4166109() {
1281        /*
1282         * Test month:
1283         *
1284         * March 1998 Su Mo Tu We Th Fr Sa 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1285         * 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
1286         */
1287        boolean passed = true;
1288        int field = Calendar.WEEK_OF_MONTH;
1289
1290        GregorianCalendar calendar = new GregorianCalendar(Locale.US);
1291        calendar.set(1998, Calendar.MARCH, 1);
1292        calendar.setMinimalDaysInFirstWeek(1);
1293        logln("Date:  " + calendar.getTime());
1294
1295        int firstInMonth = calendar.get(Calendar.DAY_OF_MONTH);
1296
1297        for (int firstInWeek = Calendar.SUNDAY; firstInWeek <= Calendar.SATURDAY; firstInWeek++) {
1298            calendar.setFirstDayOfWeek(firstInWeek);
1299            int returned = calendar.getActualMaximum(field);
1300            int expected = (31 + ((firstInMonth - firstInWeek + 7)% 7) + 6) / 7;
1301
1302            logln("First day of week = " + firstInWeek +
1303                  "  getActualMaximum(WEEK_OF_MONTH) = " + returned +
1304                  "  expected = " + expected +
1305                  ((returned == expected) ? "  ok" : "  FAIL"));
1306
1307            if (returned != expected) {
1308                passed = false;
1309            }
1310        }
1311        if (!passed) {
1312            errln("Test failed");
1313        }
1314    }
1315
1316    /**
1317     * Calendar.getActualMaximum(YEAR) works wrong.
1318     */
1319    @Test
1320    public void Test4167060() {
1321        int field = Calendar.YEAR;
1322        DateFormat format = new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy G",
1323                                                 Locale.US);
1324
1325        GregorianCalendar calendars[] = {
1326            new GregorianCalendar(100, Calendar.NOVEMBER, 1),
1327            new GregorianCalendar(-99 /* 100BC */, Calendar.JANUARY, 1),
1328            new GregorianCalendar(1996, Calendar.FEBRUARY, 29),
1329        };
1330
1331        String[] id = { "Hybrid", "Gregorian", "Julian" };
1332
1333        for (int k=0; k<3; ++k) {
1334            logln("--- " + id[k] + " ---");
1335
1336            for (int j=0; j<calendars.length; ++j) {
1337                GregorianCalendar calendar = calendars[j];
1338                if (k == 1) {
1339                    calendar.setGregorianChange(new Date(Long.MIN_VALUE));
1340                } else if (k == 2) {
1341                    calendar.setGregorianChange(new Date(Long.MAX_VALUE));
1342                }
1343
1344                format.setCalendar((Calendar)calendar.clone());
1345
1346                Date dateBefore = calendar.getTime();
1347
1348                int maxYear = calendar.getActualMaximum(field);
1349                logln("maxYear: " + maxYear + " for " + format.format(calendar.getTime()));
1350                logln("date before: " + format.format(dateBefore));
1351
1352                int years[] = {2000, maxYear-1, maxYear, maxYear+1};
1353
1354                for (int i = 0; i < years.length; i++) {
1355                    boolean valid = years[i] <= maxYear;
1356                    calendar.set(field, years[i]);
1357                    Date dateAfter = calendar.getTime();
1358                    int newYear = calendar.get(field);
1359                    calendar.setTime(dateBefore); // restore calendar for next
1360                                                  // use
1361
1362                    logln(" Year " + years[i] + (valid? " ok " : " bad") +
1363                          " => " + format.format(dateAfter));
1364                    if (valid && newYear != years[i]) {
1365                        errln("  FAIL: " + newYear + " should be valid; date, month and time shouldn't change");
1366                    } else if (!valid && newYear == years[i]) {
1367                        // We no longer require strict year maxima. That is, the
1368                        // calendar
1369                        // algorithm may work for values > the stated maximum.
1370                        //errln(" FAIL: " + newYear + " should be invalid");
1371                        logln("  Note: " + newYear + " > maximum, but still valid");
1372                    }
1373                }
1374            }
1375        }
1376    }
1377
1378    /**
1379     * Calendar.roll broken This bug relies on the TimeZone bug 4173604 to also
1380     * be fixed.
1381     */
1382    @Test
1383    public void Test4173516() {
1384        int fieldsList[][] = {
1385            { 1997, Calendar.FEBRUARY,  1, 10, 45, 15, 900 },
1386            { 1999, Calendar.DECEMBER, 22, 23, 59, 59, 999 }
1387        };
1388        int limit = 40;
1389        GregorianCalendar cal = new GregorianCalendar();
1390
1391        cal.setTime(new Date(0));
1392        cal.roll(Calendar.HOUR,  0x7F000000);
1393        cal.roll(Calendar.HOUR, -0x7F000000);
1394        if (cal.getTime().getTime() != 0) {
1395            errln("Hour rolling broken");
1396        }
1397
1398        for (int op=0; op<2; ++op) {
1399            logln("Testing GregorianCalendar " +
1400                  (op==0 ? "add" : "roll"));
1401            for (int field=0; field < cal.getFieldCount(); ++field) {
1402                if (field != Calendar.ZONE_OFFSET &&
1403                    field != Calendar.DST_OFFSET &&
1404                    field != Calendar.IS_LEAP_MONTH ) {
1405                    for (int j=0; j<fieldsList.length; ++j) {
1406                        int fields[] = fieldsList[j];
1407                        cal.clear();
1408                        cal.set(fields[0], fields[1], fields[2],
1409                                fields[3], fields[4], fields[5]);
1410                        cal.set(Calendar.MILLISECOND, fields[6]);
1411                        cal.setMinimalDaysInFirstWeek(1);
1412                        for (int i = 0; i < 2*limit; i++) {
1413                            if (op == 0) {
1414                                cal.add(field, i < limit ? 1 : -1);
1415                            } else {
1416                                cal.roll(field, i < limit ? 1 : -1);
1417                            }
1418                        }
1419                        if (cal.get(Calendar.YEAR) != fields[0] ||
1420                            cal.get(Calendar.MONTH) != fields[1] ||
1421                            cal.get(Calendar.DATE) != fields[2] ||
1422                            cal.get(Calendar.HOUR_OF_DAY) != fields[3] ||
1423                            cal.get(Calendar.MINUTE) != fields[4] ||
1424                            cal.get(Calendar.SECOND) != fields[5] ||
1425                            cal.get(Calendar.MILLISECOND) != fields[6]) {
1426                            errln("Field " + field +
1427                                  " (" + FIELD_NAME[field] +
1428                                  ") FAIL, expected " +
1429                                  fields[0] +
1430                                  "/" + (fields[1] + 1) +
1431                                  "/" + fields[2] +
1432                                  " " + fields[3] +
1433                                  ":" + fields[4] +
1434                                  ":" + fields[5] +
1435                                  "." + fields[6] +
1436                                  ", got " + cal.get(Calendar.YEAR) +
1437                                  "/" + (cal.get(Calendar.MONTH) + 1) +
1438                                  "/" + cal.get(Calendar.DATE) +
1439                                  " " + cal.get(Calendar.HOUR_OF_DAY) +
1440                                  ":" + cal.get(Calendar.MINUTE) +
1441                                  ":" + cal.get(Calendar.SECOND) +
1442                                  "." + cal.get(Calendar.MILLISECOND));
1443                            cal.clear();
1444                            cal.set(fields[0], fields[1], fields[2],
1445                                    fields[3], fields[4], fields[5]);
1446                            cal.set(Calendar.MILLISECOND, fields[6]);
1447                            logln("Start date: " + cal.get(Calendar.YEAR) +
1448                                  "/" + (cal.get(Calendar.MONTH) + 1) +
1449                                  "/" + cal.get(Calendar.DATE) +
1450                                  " " + cal.get(Calendar.HOUR_OF_DAY) +
1451                                  ":" + cal.get(Calendar.MINUTE) +
1452                                  ":" + cal.get(Calendar.SECOND) +
1453                                  "." + cal.get(Calendar.MILLISECOND));
1454                            long prev = cal.getTime().getTime();
1455                            for (int i = 0; i < 2*limit; i++) {
1456                                if (op == 0) {
1457                                    cal.add(field, i < limit ? 1 : -1);
1458                                } else {
1459                                    cal.roll(field, i < limit ? 1 : -1);
1460                                }
1461                                long t = cal.getTime().getTime();
1462                                long delta = t - prev;
1463                                prev = t;
1464                                logln((op == 0 ? "add(" : "roll(") + FIELD_NAME[field] +
1465                                      (i < limit ? ", +1) => " : ", -1) => ") +
1466                                      cal.get(Calendar.YEAR) +
1467                                      "/" + (cal.get(Calendar.MONTH) + 1) +
1468                                      "/" + cal.get(Calendar.DATE) +
1469                                      " " + cal.get(Calendar.HOUR_OF_DAY) +
1470                                      ":" + cal.get(Calendar.MINUTE) +
1471                                      ":" + cal.get(Calendar.SECOND) +
1472                                      "." + cal.get(Calendar.MILLISECOND) +
1473                                      " delta=" + delta + " ms");
1474                            }
1475                        }
1476                    }
1477                }
1478            }
1479        }
1480    }
1481
1482    @Test
1483    public void Test4174361() {
1484        GregorianCalendar calendar = new GregorianCalendar(1996, 1, 29);
1485
1486        calendar.add(Calendar.MONTH, 10);
1487        //Date date1 = calendar.getTime();
1488        //date1 = null;
1489        int d1 = calendar.get(Calendar.DAY_OF_MONTH);
1490
1491        calendar = new GregorianCalendar(1996, 1, 29);
1492        calendar.add(Calendar.MONTH, 11);
1493        //Date date2 = calendar.getTime();
1494        //date2 = null;
1495        int d2 = calendar.get(Calendar.DAY_OF_MONTH);
1496
1497        if (d1 != d2) {
1498            errln("adding months to Feb 29 broken");
1499        }
1500    }
1501
1502    /**
1503     * Calendar does not update field values when setTimeZone is called.
1504     */
1505    @Test
1506    public void Test4177484() {
1507        TimeZone PST = TimeZone.getTimeZone("PST");
1508        TimeZone EST = TimeZone.getTimeZone("EST");
1509
1510        Calendar cal = Calendar.getInstance(PST, Locale.US);
1511        cal.clear();
1512        cal.set(1999, 3, 21, 15, 5, 0); // Arbitrary
1513        int h1 = cal.get(Calendar.HOUR_OF_DAY);
1514        cal.setTimeZone(EST);
1515        int h2 = cal.get(Calendar.HOUR_OF_DAY);
1516        if (h1 == h2) {
1517            errln("FAIL: Fields not updated after setTimeZone");
1518        }
1519
1520        // getTime() must NOT change when time zone is changed.
1521        // getTime() returns zone-independent time in ms.
1522        cal.clear();
1523        cal.setTimeZone(PST);
1524        cal.set(Calendar.HOUR_OF_DAY, 10);
1525        Date pst10 = cal.getTime();
1526        cal.setTimeZone(EST);
1527        Date est10 = cal.getTime();
1528        if (!pst10.equals(est10)) {
1529            errln("FAIL: setTimeZone changed time");
1530        }
1531    }
1532
1533    /**
1534     * Week of year is wrong at the start and end of the year.
1535     */
1536    @Test
1537    public void Test4197699() {
1538        GregorianCalendar cal = new GregorianCalendar();
1539        cal.setFirstDayOfWeek(Calendar.MONDAY);
1540        cal.setMinimalDaysInFirstWeek(4);
1541        DateFormat fmt = new SimpleDateFormat("E dd MMM yyyy  'DOY='D 'WOY='w");
1542        fmt.setCalendar(cal);
1543
1544        int[] DATA = {
1545            2000,  Calendar.JANUARY,   1,   52,
1546            2001,  Calendar.DECEMBER,  31,  1,
1547        };
1548
1549        for (int i=0; i<DATA.length; ) {
1550            cal.set(DATA[i++], DATA[i++], DATA[i++]);
1551            int expWOY = DATA[i++];
1552            int actWOY = cal.get(Calendar.WEEK_OF_YEAR);
1553            if (expWOY == actWOY) {
1554                logln("Ok: " + fmt.format(cal.getTime()));
1555            } else {
1556                errln("FAIL: " + fmt.format(cal.getTime())
1557                      + ", expected WOY=" + expWOY);
1558                cal.add(Calendar.DATE, -8);
1559                for (int j=0; j<14; ++j) {
1560                    cal.add(Calendar.DATE, 1);
1561                    logln(fmt.format(cal.getTime()));
1562                }
1563            }
1564        }
1565    }
1566
1567    /**
1568     * Calendar DAY_OF_WEEK_IN_MONTH fields->time broken. The problem is in the
1569     * field disambiguation code in GregorianCalendar. This code is supposed to
1570     * choose the most recent set of fields among the following:
1571     *
1572     * MONTH + DAY_OF_MONTH MONTH + WEEK_OF_MONTH + DAY_OF_WEEK MONTH +
1573     * DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK DAY_OF_YEAR WEEK_OF_YEAR + DAY_OF_WEEK
1574     */
1575    @Test
1576    public void Test4209071() {
1577        Calendar cal = Calendar.getInstance(Locale.US);
1578
1579        // General field setting test
1580        int Y = 1995;
1581
1582        Date d[] = new Date[13];
1583        java.util.Calendar tempcal = java.util.Calendar.getInstance();
1584        tempcal.clear();
1585        tempcal.set(Y, Calendar.JANUARY, 1);
1586        d[0] = tempcal.getTime();
1587        tempcal.set(Y, Calendar.MARCH, 1);
1588        d[1] = tempcal.getTime();
1589        tempcal.set(Y, Calendar.JANUARY, 4);
1590        d[2] = tempcal.getTime();
1591        tempcal.set(Y, Calendar.JANUARY, 18);
1592        d[3] = tempcal.getTime();
1593        tempcal.set(Y, Calendar.JANUARY, 18);
1594        d[4] = tempcal.getTime();
1595        tempcal.set(Y-1, Calendar.DECEMBER, 22);
1596        d[5] = tempcal.getTime();
1597        tempcal.set(Y, Calendar.JANUARY, 26);
1598        d[6] = tempcal.getTime();
1599        tempcal.set(Y, Calendar.JANUARY, 26);
1600        d[7] = tempcal.getTime();
1601        tempcal.set(Y, Calendar.MARCH, 1);
1602        d[8] = tempcal.getTime();
1603        tempcal.set(Y, Calendar.OCTOBER, 6);
1604        d[9] = tempcal.getTime();
1605        tempcal.set(Y, Calendar.OCTOBER, 13);
1606        d[10] = tempcal.getTime();
1607        tempcal.set(Y, Calendar.AUGUST, 10);
1608        d[11] = tempcal.getTime();
1609        tempcal.set(Y, Calendar.DECEMBER, 7);
1610        d[12] = tempcal.getTime();
1611
1612        Object[] FIELD_DATA = {
1613            // Add new test cases as needed.
1614
1615            // 0
1616            new int[] {}, d[0],
1617            // 1
1618            new int[] { Calendar.MONTH, Calendar.MARCH }, d[1],
1619            // 2
1620            new int[] { Calendar.DAY_OF_WEEK, Calendar.WEDNESDAY }, d[2],
1621            // 3
1622            new int[] { Calendar.DAY_OF_WEEK, Calendar.THURSDAY,
1623                        Calendar.DAY_OF_MONTH, 18, }, d[3],
1624            // 4
1625            new int[] { Calendar.DAY_OF_MONTH, 18,
1626                        Calendar.DAY_OF_WEEK, Calendar.THURSDAY, }, d[4],
1627            // 5 (WOM -1 is in previous month)
1628            new int[] { Calendar.DAY_OF_MONTH, 18,
1629                        Calendar.WEEK_OF_MONTH, -1,
1630                        Calendar.DAY_OF_WEEK, Calendar.THURSDAY, }, d[5],
1631            // 6
1632            new int[] { Calendar.DAY_OF_MONTH, 18,
1633                        Calendar.WEEK_OF_MONTH, 4,
1634                        Calendar.DAY_OF_WEEK, Calendar.THURSDAY, }, d[6],
1635            // 7 (DIM -1 is in same month)
1636            new int[] { Calendar.DAY_OF_MONTH, 18,
1637                        Calendar.DAY_OF_WEEK_IN_MONTH, -1,
1638                        Calendar.DAY_OF_WEEK, Calendar.THURSDAY, }, d[7],
1639            // 8
1640            new int[] { Calendar.WEEK_OF_YEAR, 9,
1641                        Calendar.DAY_OF_WEEK, Calendar.WEDNESDAY, }, d[8],
1642            // 9
1643            new int[] { Calendar.MONTH, Calendar.OCTOBER,
1644                        Calendar.DAY_OF_WEEK_IN_MONTH, 1,
1645                        Calendar.DAY_OF_WEEK, Calendar.FRIDAY, }, d[9],
1646            // 10
1647            new int[] { Calendar.MONTH, Calendar.OCTOBER,
1648                        Calendar.WEEK_OF_MONTH, 2,
1649                        Calendar.DAY_OF_WEEK, Calendar.FRIDAY, }, d[10],
1650            // 11
1651            new int[] { Calendar.MONTH, Calendar.OCTOBER,
1652                        Calendar.DAY_OF_MONTH, 15,
1653                        Calendar.DAY_OF_YEAR, 222, }, d[11],
1654            // 12
1655            new int[] { Calendar.DAY_OF_WEEK, Calendar.THURSDAY,
1656                        Calendar.MONTH, Calendar.DECEMBER, }, d[12],
1657        };
1658
1659        for (int i=0; i<FIELD_DATA.length; i+=2) {
1660            int[] fields = (int[]) FIELD_DATA[i];
1661            Date exp = (Date) FIELD_DATA[i+1];
1662
1663            cal.clear();
1664            cal.set(Calendar.YEAR, Y);
1665            for (int j=0; j<fields.length; j+=2) {
1666                cal.set(fields[j], fields[j+1]);
1667            }
1668
1669            Date act = cal.getTime();
1670            if (!act.equals(exp)) {
1671                errln("FAIL: Test " + (i/2) + " got " + act +
1672                      ", want " + exp +
1673                      " (see test/java/util/Calendar/CalendarRegressionTest.java");
1674            }
1675        }
1676
1677        tempcal.set(1997, Calendar.JANUARY, 5);
1678        d[0] = tempcal.getTime();
1679        tempcal.set(1997, Calendar.JANUARY, 26);
1680        d[1] = tempcal.getTime();
1681        tempcal.set(1997, Calendar.FEBRUARY, 23);
1682        d[2] = tempcal.getTime();
1683        tempcal.set(1997, Calendar.JANUARY, 26);
1684        d[3] = tempcal.getTime();
1685        tempcal.set(1997, Calendar.JANUARY, 5);
1686        d[4] = tempcal.getTime();
1687        tempcal.set(1996, Calendar.DECEMBER, 8);
1688        d[5] = tempcal.getTime();
1689        // Test specific failure reported in bug
1690        Object[] DATA = {
1691            new Integer(1), d[0], new Integer(4), d[1],
1692            new Integer(8), d[2], new Integer(-1), d[3],
1693            new Integer(-4), d[4], new Integer(-8), d[5],
1694        };
1695        for (int i=0; i<DATA.length; i+=2) {
1696            cal.clear();
1697            cal.set(Calendar.DAY_OF_WEEK_IN_MONTH,
1698                    ((Number) DATA[i]).intValue());
1699            cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
1700            cal.set(Calendar.MONTH, Calendar.JANUARY);
1701            cal.set(Calendar.YEAR, 1997);
1702            Date actual = cal.getTime();
1703            if (!actual.equals(DATA[i+1])) {
1704                errln("FAIL: Sunday " + DATA[i] +
1705                      " of Jan 1997 -> " + actual +
1706                      ", want " + DATA[i+1]);
1707            }
1708        }
1709    }
1710
1711    /**
1712     * WEEK_OF_YEAR computed incorrectly. A failure of this test can indicate a problem in several different places in
1713     * the
1714     */
1715    @Test
1716    public void Test4288792() throws Exception {
1717        TimeZone savedTZ = TimeZone.getDefault();
1718        TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
1719        GregorianCalendar cal = new GregorianCalendar();
1720
1721        for (int i = 1900; i < 2100; i++) {
1722            for (int j1 = 1; j1 <= 7; j1++) {
1723                // Loop for MinimalDaysInFirstWeek: 1..7
1724                for (int j = Calendar.SUNDAY; j <= Calendar.SATURDAY; j++) {
1725                    // Loop for FirstDayOfWeek: SUNDAY..SATURDAY
1726                    cal.clear();
1727                    cal.setMinimalDaysInFirstWeek(j1);
1728                    cal.setFirstDayOfWeek(j);
1729                    // Set the calendar to the first day of the last week
1730                    // of the year. This may overlap some of the start of
1731                    // the next year; that is, the last week of 1999 may
1732                    // include some of January 2000. Use the add() method
1733                    // to advance through the week. For each day, call
1734                    // get(WEEK_OF_YEAR). The result should be the same
1735                    // for the whole week. Note that a bug in
1736                    // getActualMaximum() will break this test.
1737
1738                    // Set date to the mid year first before getActualMaximum(WEEK_OF_YEAR).
1739                    // getActualMaximum(WEEK_OF_YEAR) is based on the current calendar's
1740                    // year of week of year. After clear(), calendar is set to January 1st,
1741                    // which may belongs to previous year of week of year.
1742                    cal.set(i, Calendar.JULY, 1);
1743                    int maxWeek = cal.getActualMaximum(Calendar.WEEK_OF_YEAR);
1744                    cal.set(Calendar.WEEK_OF_YEAR, maxWeek);
1745                    cal.set(Calendar.DAY_OF_WEEK, j);
1746                    for (int k = 1; k < 7; k++) {
1747                        cal.add(Calendar.DATE, 1);
1748                        int WOY = cal.get(Calendar.WEEK_OF_YEAR);
1749                        if (WOY != maxWeek) {
1750                            errln(cal.getTime() + ",got=" + WOY + ",expected=" + maxWeek + ",min=" + j1 + ",first=" + j);
1751                        }
1752                    }
1753                    // Now advance the calendar one more day. This should
1754                    // put it at the first day of week 1 of the next year.
1755                    cal.add(Calendar.DATE, 1);
1756                    int WOY = cal.get(Calendar.WEEK_OF_YEAR);
1757                    if (WOY != 1) {
1758                        errln(cal.getTime() + ",got=" + WOY + ",expected=1,min=" + j1 + ",first" + j);
1759                    }
1760                }
1761            }
1762        }
1763        TimeZone.setDefault(savedTZ);
1764    }
1765
1766    /**
1767     * Test fieldDifference().
1768     */
1769    @Test
1770    public void TestJ438() throws Exception {
1771        int DATA[] = {
1772            2000, Calendar.JANUARY, 20,   2010, Calendar.JUNE, 15,
1773            2010, Calendar.JUNE, 15,      2000, Calendar.JANUARY, 20,
1774            1964, Calendar.SEPTEMBER, 7,  1999, Calendar.JUNE, 4,
1775            1999, Calendar.JUNE, 4,       1964, Calendar.SEPTEMBER, 7,
1776        };
1777        Calendar cal = Calendar.getInstance(Locale.US);
1778        for (int i=0; i<DATA.length; i+=6) {
1779            int y1 = DATA[i];
1780            int m1 = DATA[i+1];
1781            int d1 = DATA[i+2];
1782            int y2 = DATA[i+3];
1783            int m2 = DATA[i+4];
1784            int d2 = DATA[i+5];
1785
1786            cal.clear();
1787            cal.set(y1, m1, d1);
1788            Date date1 = cal.getTime();
1789            cal.set(y2, m2, d2);
1790            Date date2 = cal.getTime();
1791
1792            cal.setTime(date1);
1793            int dy = cal.fieldDifference(date2, Calendar.YEAR);
1794            int dm = cal.fieldDifference(date2, Calendar.MONTH);
1795            int dd = cal.fieldDifference(date2, Calendar.DATE);
1796
1797            logln("" + date2 + " - " + date1 + " = " +
1798                  dy + "y " + dm + "m " + dd + "d");
1799
1800            cal.setTime(date1);
1801            cal.add(Calendar.YEAR, dy);
1802            cal.add(Calendar.MONTH, dm);
1803            cal.add(Calendar.DATE, dd);
1804            Date date22 = cal.getTime();
1805            if (!date2.equals(date22)) {
1806                errln("FAIL: " + date1 + " + " +
1807                      dy + "y " + dm + "m " + dd + "d = " +
1808                      date22 + ", exp " + date2);
1809            } else {
1810                logln("Ok: " + date1 + " + " +
1811                      dy + "y " + dm + "m " + dd + "d = " +
1812                      date22);
1813            }
1814        }
1815    }
1816
1817    @Test
1818    public void TestT5555() throws Exception
1819    {
1820        Calendar cal = Calendar.getInstance();
1821
1822        // Set date to Wednesday, February 21, 2007
1823        cal.set(2007, Calendar.FEBRUARY, 21);
1824
1825        try {
1826            // Advance month by three years
1827            cal.add(Calendar.MONTH, 36);
1828
1829            // Move to last Wednesday of month.
1830            cal.set(Calendar.DAY_OF_WEEK_IN_MONTH, -1);
1831
1832            cal.getTime();
1833        } catch (Exception e) {
1834            errln("Got an exception calling getTime().");
1835        }
1836
1837        int yy, mm, dd, ee;
1838
1839        yy = cal.get(Calendar.YEAR);
1840        mm = cal.get(Calendar.MONTH);
1841        dd = cal.get(Calendar.DATE);
1842        ee = cal.get(Calendar.DAY_OF_WEEK_IN_MONTH);
1843
1844        if (yy != 2010 || mm != Calendar.FEBRUARY || dd != 24 || ee != Calendar.WEDNESDAY) {
1845            errln("Got date " + yy + "/" + (mm + 1) + "/" + dd + ", expected 2010/2/24");
1846        }
1847    }
1848
1849    /**
1850     * Set behavior of DST_OFFSET field. ICU4J Jitterbug 9.
1851     */
1852    @Test
1853    public void TestJ9() {
1854        int HOURS = 60*60*1000;
1855        Calendar cal = new GregorianCalendar(TimeZone.getTimeZone("PST"),
1856                                             Locale.US);
1857
1858        final int END_FIELDS = 0x1234;
1859
1860        int[] DATA = {
1861            // With no explicit ZONE/DST expect 12:00 am
1862            Calendar.MONTH, Calendar.JUNE,
1863            END_FIELDS,
1864            0, 0, // expected hour, min
1865
1866            // Normal ZONE/DST for June 1 Pacific is 8:00/1:00
1867            Calendar.MONTH, Calendar.JUNE,
1868            Calendar.ZONE_OFFSET, -8*HOURS,
1869            Calendar.DST_OFFSET, HOURS,
1870            END_FIELDS,
1871            0, 0, // expected hour, min
1872
1873            // With ZONE/DST of 8:00/0:30 expect time of 12:30 am
1874            Calendar.MONTH, Calendar.JUNE,
1875            Calendar.ZONE_OFFSET, -8*HOURS,
1876            Calendar.DST_OFFSET, HOURS/2,
1877            END_FIELDS,
1878            0, 30, // expected hour, min
1879
1880            // With ZONE/DST of 8:00/UNSET expect time of 1:00 am
1881            Calendar.MONTH, Calendar.JUNE,
1882            Calendar.ZONE_OFFSET, -8*HOURS,
1883            END_FIELDS,
1884            1, 0, // expected hour, min
1885
1886            // With ZONE/DST of UNSET/0:30 expect 4:30 pm (day before)
1887            Calendar.MONTH, Calendar.JUNE,
1888            Calendar.DST_OFFSET, HOURS/2,
1889            END_FIELDS,
1890            16, 30, // expected hour, min
1891        };
1892
1893        for (int i=0; i<DATA.length; ) {
1894            int start = i;
1895            cal.clear();
1896
1897            // Set fields
1898            while (DATA[i] != END_FIELDS) {
1899                cal.set(DATA[i++], DATA[i++]);
1900            }
1901            ++i; // skip over END_FIELDS
1902
1903            // Get hour/minute
1904            int h = cal.get(Calendar.HOUR_OF_DAY);
1905            int m = cal.get(Calendar.MINUTE);
1906
1907            // Check
1908            if (h != DATA[i] || m != DATA[i+1]) {
1909                errln("Fail: expected " + DATA[i] + ":" + DATA[i+1] +
1910                      ", got " + h + ":" + m + " after:");
1911                while (DATA[start] != END_FIELDS) {
1912                    logln("set(" + FIELD_NAME[DATA[start++]] +
1913                          ", " + DATA[start++] + ");");
1914                }
1915            }
1916
1917            i += 2; // skip over expected hour, min
1918        }
1919    }
1920
1921    /**
1922     * DateFormat class mistakes date style and time style as follows: -
1923     * DateFormat.getDateTimeInstance takes date style as time style, and time
1924     * style as date style - If a Calendar is passed to
1925     * DateFormat.getDateInstance, it returns time instance - If a Calendar is
1926     * passed to DateFormat.getTimeInstance, it returns date instance
1927     */
1928    @Test
1929    public void TestDateFormatFactoryJ26() {
1930        TimeZone zone = TimeZone.getDefault();
1931        try {
1932            Locale loc = Locale.US;
1933            TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles"));
1934            java.util.Calendar tempcal = java.util.Calendar.getInstance();
1935            tempcal.set(2001, Calendar.APRIL, 5, 17, 43, 53);
1936            Date date = tempcal.getTime();
1937            Calendar cal = Calendar.getInstance(loc);
1938            Object[] DATA = {
1939                DateFormat.getDateInstance(DateFormat.SHORT, loc),
1940                "DateFormat.getDateInstance(DateFormat.SHORT, loc)",
1941                "4/5/01",
1942
1943                DateFormat.getTimeInstance(DateFormat.SHORT, loc),
1944                "DateFormat.getTimeInstance(DateFormat.SHORT, loc)",
1945                "5:43 PM",
1946
1947                DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.SHORT, loc),
1948                "DateFormat.getDateTimeInstance(DateFormat.FULL, DateFormat.SHORT, loc)",
1949                "Thursday, April 5, 2001 at 5:43 PM",
1950
1951                DateFormat.getDateInstance(cal, DateFormat.SHORT, loc),
1952                "DateFormat.getDateInstance(cal, DateFormat.SHORT, loc)",
1953                "4/5/01",
1954
1955                DateFormat.getTimeInstance(cal, DateFormat.SHORT, loc),
1956                "DateFormat.getTimeInstance(cal, DateFormat.SHORT, loc)",
1957                "5:43 PM",
1958
1959                DateFormat.getDateTimeInstance(cal, DateFormat.FULL, DateFormat.SHORT, loc),
1960                "DateFormat.getDateTimeInstance(cal, DateFormat.FULL, DateFormat.SHORT, loc)",
1961                "Thursday, April 5, 2001 at 5:43 PM",
1962
1963                cal.getDateTimeFormat(DateFormat.SHORT, DateFormat.FULL, loc),
1964                "cal.getDateTimeFormat(DateFormat.SHORT, DateFormat.FULL, loc)",
1965                "4/5/01, 5:43:53 PM Pacific Daylight Time",
1966
1967                cal.getDateTimeFormat(DateFormat.FULL, DateFormat.SHORT, loc),
1968                "cal.getDateTimeFormat(DateFormat.FULL, DateFormat.SHORT, loc)",
1969                "Thursday, April 5, 2001 at 5:43 PM",
1970            };
1971            for (int i=0; i<DATA.length; i+=3) {
1972                DateFormat df = (DateFormat) DATA[i];
1973                String desc = (String) DATA[i+1];
1974                String exp = (String) DATA[i+2];
1975                String got = df.format(date);
1976                if (got.equals(exp)) {
1977                    logln("Ok: " + desc + " => " + got);
1978                } else {
1979                    errln("FAIL: " + desc + " => " + got + ", expected " + exp);
1980                }
1981            }
1982        } finally {
1983            TimeZone.setDefault(zone);
1984        }
1985    }
1986
1987    @Test
1988    public void TestRegistration() {
1989        /*
1990         * Set names = Calendar.getCalendarFactoryNames();
1991         *
1992         * TimeZone tz = TimeZone.getDefault(); Locale loc =
1993         * Locale.getDefault(); Iterator iter = names.iterator(); while
1994         * (iter.hasNext()) { String name = (String)iter.next(); logln("Testing
1995         * factory: " + name);
1996         *
1997         * Calendar cal = Calendar.getInstance(tz, loc, name); logln("Calendar
1998         * class: " + cal.getClass());
1999         *
2000         * DateFormat fmt = cal.getDateTimeFormat(DateFormat.LONG,
2001         * DateFormat.LONG, loc);
2002         *
2003         * logln("Date: " + fmt.format(cal.getTime())); }
2004         *  // register new default for our locale logln("\nTesting
2005         * registration"); loc = new Locale("en", "US"); Object key =
2006         * Calendar.register(JapaneseCalendar.factory(), loc, true);
2007         *
2008         * loc = new Locale("en", "US", "TEST"); Calendar cal =
2009         * Calendar.getInstance(loc); logln("Calendar class: " +
2010         * cal.getClass()); DateFormat fmt =
2011         * cal.getDateTimeFormat(DateFormat.LONG, DateFormat.LONG, loc);
2012         * logln("Date: " + fmt.format(cal.getTime()));
2013         *  // force to use other default anyway logln("\nOverride
2014         * registration"); cal = Calendar.getInstance(tz, loc, "Gregorian"); fmt =
2015         * cal.getDateTimeFormat(DateFormat.LONG, DateFormat.LONG, loc);
2016         * logln("Date: " + fmt.format(cal.getTime()));
2017         *  // unregister default logln("\nUnregistration"); logln("Unregister
2018         * returned: " + Calendar.unregister(key)); cal =
2019         * Calendar.getInstance(tz, loc, "Gregorian"); fmt =
2020         * cal.getDateTimeFormat(DateFormat.LONG, DateFormat.LONG, loc);
2021         * logln("Date: " + fmt.format(cal.getTime()));
2022         */
2023    }
2024
2025    /**
2026     * test serialize-and-modify.
2027     * @throws ClassNotFoundException
2028     */
2029    @Test
2030    public void TestSerialization3474() {
2031        try {
2032            ByteArrayOutputStream icuStream = new ByteArrayOutputStream();
2033
2034            logln("icu Calendar");
2035
2036            android.icu.util.GregorianCalendar icuCalendar =
2037                new android.icu.util.GregorianCalendar();
2038
2039            icuCalendar.setTimeInMillis(1187912555931L);
2040            long expectMillis = 1187912520931L; // with seconds (not ms) cleared.
2041
2042            logln("instantiated: "+icuCalendar);
2043            logln("getMillis: "+icuCalendar.getTimeInMillis());
2044            icuCalendar.set(android.icu.util.GregorianCalendar.SECOND, 0);
2045            logln("setSecond=0: "+icuCalendar);
2046            {
2047                long gotMillis = icuCalendar.getTimeInMillis();
2048                if(gotMillis != expectMillis) {
2049                    errln("expect millis "+expectMillis+" but got "+gotMillis);
2050                } else {
2051                    logln("getMillis: "+gotMillis);
2052                }
2053            }
2054            ObjectOutputStream icuOut =
2055                new ObjectOutputStream(icuStream);
2056            icuOut.writeObject(icuCalendar);
2057            icuOut.flush();
2058            icuOut.close();
2059
2060            ObjectInputStream icuIn =
2061                new ObjectInputStream(new ByteArrayInputStream(icuStream.toByteArray()));
2062            icuCalendar = null;
2063            icuCalendar = (android.icu.util.GregorianCalendar)icuIn.readObject();
2064
2065            logln("serialized back in: "+icuCalendar);
2066            {
2067                long gotMillis = icuCalendar.getTimeInMillis();
2068                if(gotMillis != expectMillis) {
2069                    errln("expect millis "+expectMillis+" but got "+gotMillis);
2070                } else {
2071                    logln("getMillis: "+gotMillis);
2072                }
2073            }
2074
2075            icuCalendar.set(android.icu.util.GregorianCalendar.SECOND, 0);
2076
2077            logln("setSecond=0: "+icuCalendar);
2078            {
2079                long gotMillis = icuCalendar.getTimeInMillis();
2080                if(gotMillis != expectMillis) {
2081                    errln("expect millis "+expectMillis+" after stream and setSecond but got "+gotMillis);
2082                } else {
2083                    logln("getMillis after stream and setSecond: "+gotMillis);
2084                }
2085            }
2086        } catch(IOException e) {
2087            errln(e.toString());
2088            e.printStackTrace();
2089        } catch(ClassNotFoundException cnf) {
2090            errln(cnf.toString());
2091            cnf.printStackTrace();
2092        }
2093
2094        // JDK works correctly, etc etc.
2095//        ByteArrayOutputStream jdkStream = new ByteArrayOutputStream();
2096
2097//        logln("\nSUN Calendar");
2098//
2099//        java.util.GregorianCalendar sunCalendar =
2100//            new java.util.GregorianCalendar();
2101//
2102//        logln("instanzieren: "+sunCalendar);
2103//        logln("getMillis: "+sunCalendar.getTimeInMillis());
2104//        sunCalendar.set(java.util.GregorianCalendar.SECOND, 0);
2105//        logln("setSecond=0: "+sunCalendar);
2106//        logln("getMillis: "+sunCalendar.getTimeInMillis());
2107//
2108//        ObjectOutputStream sunOut =
2109//            new ObjectOutputStream(jdkStream);
2110//        sunOut.writeObject(sunCalendar);
2111//        sunOut.flush();
2112//        sunOut.close();
2113//
2114//        ObjectInputStream sunIn =
2115//            new ObjectInputStream(new ByteArrayInputStream(jdkStream.toByteArray()));
2116//        sunCalendar = null;
2117//        sunCalendar = (java.util.GregorianCalendar)sunIn.readObject();
2118//
2119//        logln("serialized: "+sunCalendar);
2120//        logln("getMillis: "+sunCalendar.getTimeInMillis());
2121//
2122//        sunCalendar.set(java.util.GregorianCalendar.SECOND, 0);
2123//        logln("setSecond=0: "+sunCalendar);
2124//        logln("getMillis: "+sunCalendar.getTimeInMillis());
2125
2126    }
2127
2128    @Test
2129    public void TestYearJump3279() {
2130        final long time = 1041148800000L;
2131        Calendar c = new GregorianCalendar();
2132        DateFormat fmt = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG, Locale.US);
2133
2134        c.setTimeInMillis(time);
2135        int year1 = c.get(Calendar.YEAR);
2136
2137        logln("time: " + fmt.format(new Date(c.getTimeInMillis())));
2138
2139        logln("setting DOW to " + c.getFirstDayOfWeek());
2140        c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek());
2141        logln("week: " + c.getTime());
2142        logln("week adjust: " + fmt.format(new Date(c.getTimeInMillis())));
2143        int year2 = c.get(Calendar.YEAR);
2144
2145        if(year1 != year2) {
2146            errln("Error: adjusted day of week, and year jumped from " + year1 + " to " + year2);
2147        } else {
2148            logln("Year remained " + year2 + " - PASS.");
2149        }
2150    }
2151    @Test
2152    public void TestCalendarType6816() {
2153        Locale loc = new Locale("en", "TH");
2154        Calendar cal = Calendar.getInstance(loc);
2155        String calType = cal.getType();
2156        // Android patch: Force default Gregorian calendar.
2157        if ( !calType.equals("gregorian")) {
2158            errln("FAIL: Calendar type for en_TH should still be gregorian");
2159        }
2160        // Android patch end.
2161    }
2162
2163    @Test
2164    public void TestGetKeywordValuesForLocale(){
2165
2166        // Android patch: Force default Gregorian calendar.
2167        final String[][] PREFERRED = {
2168            {"root",        "gregorian"},
2169            {"und",         "gregorian"},
2170            {"en_US",       "gregorian"},
2171            {"en_029",      "gregorian"},
2172            {"th_TH",       "gregorian", "buddhist"},
2173            {"und_TH",      "gregorian", "buddhist"},
2174            {"en_TH",       "gregorian", "buddhist"},
2175            {"he_IL",       "gregorian", "hebrew", "islamic", "islamic-civil", "islamic-tbla"},
2176            {"ar_EG",       "gregorian", "coptic", "islamic", "islamic-civil", "islamic-tbla"},
2177            {"ja",          "gregorian", "japanese"},
2178            {"ps_Guru_IN",  "gregorian", "indian"},
2179            {"th@calendar=gregorian",   "gregorian", "buddhist"},
2180            {"en@calendar=islamic",     "gregorian"},
2181            {"zh_TW",       "gregorian", "roc", "chinese"},
2182            {"ar_IR",       "gregorian", "persian", "islamic", "islamic-civil", "islamic-tbla"},
2183            {"th@rg=SAZZZZ", "gregorian", "islamic-umalqura", "islamic", "islamic-rgsa"},
2184        };
2185        // Android patch end.
2186
2187        String[] ALL = Calendar.getKeywordValuesForLocale("calendar", ULocale.getDefault(), false);
2188        HashSet ALLSET = new HashSet();
2189        for (int i = 0; i < ALL.length; i++) {
2190            ALLSET.add(ALL[i]);
2191        }
2192
2193        for (int i = 0; i < PREFERRED.length; i++) {
2194            ULocale loc = new ULocale(PREFERRED[i][0]);
2195            String[] expected = new String[PREFERRED[i].length - 1];
2196            System.arraycopy(PREFERRED[i], 1, expected, 0, expected.length);
2197
2198            String[] pref = Calendar.getKeywordValuesForLocale("calendar", loc, true);
2199            boolean matchPref = false;
2200            if (pref.length == expected.length) {
2201                matchPref = true;
2202                for (int j = 0; j < pref.length; j++) {
2203                    if (!pref[j].equals(expected[j])) {
2204                        matchPref = false;
2205                    }
2206                }
2207            }
2208            if (!matchPref) {
2209                errln("FAIL: Preferred values for locale " + loc
2210                        + " got:" + Arrays.toString(pref) + " expected:" + Arrays.toString(expected));
2211            }
2212
2213            String[] all = Calendar.getKeywordValuesForLocale("calendar", loc, false);
2214            boolean matchAll = false;
2215            if (all.length == ALLSET.size()) {
2216                matchAll = true;
2217                for (int j = 0; j < all.length; j++) {
2218                    if (!ALLSET.contains(all[j])) {
2219                        matchAll = false;
2220                        break;
2221                    }
2222                }
2223            }
2224            if (!matchAll) {
2225                errln("FAIL: All values for locale " + loc
2226                        + " got:" + Arrays.toString(all));
2227            }
2228        }
2229    }
2230
2231    @Test
2232    public void TestTimeStamp() {
2233        long start = 0, time;
2234
2235        // Create a new Gregorian Calendar.
2236        Calendar cal = Calendar.getInstance(Locale.US);
2237
2238        for (int i = 0; i < 20000; i++) {
2239            cal.set(2009, Calendar.JULY, 3, 0, 49, 46);
2240
2241            time = cal.getTime().getTime();
2242
2243            if (i == 0) {
2244                start = time;
2245            } else {
2246                if (start != time) {
2247                    errln("start and time not equal");
2248                    return;
2249                }
2250            }
2251        }
2252    }
2253
2254    /*
2255     * Test case for add/roll with non-lenient calendar reported by ticket#8057.
2256     * Calendar#add may result internal fields out of valid range. ICU used to
2257     * trigger field range validation also for internal field changes triggered
2258     * by add/roll, then throws IllegalArgumentException. The field value range
2259     * validation should be done only for fields set by user code explicitly
2260     * in non-lenient mode.
2261     */
2262    @Test
2263    public void TestT8057() {
2264        // Set the calendar to the last day in a leap year
2265        GregorianCalendar cal = new GregorianCalendar();
2266        cal.setLenient(false);
2267        cal.clear();
2268        cal.set(2008, Calendar.DECEMBER, 31);
2269
2270        // Force calculating then fields once.
2271        long t = cal.getTimeInMillis();
2272
2273        long expected = 1262246400000L; // 2009-12-31 00:00 PST
2274
2275        try {
2276            cal.add(Calendar.YEAR, 1);
2277            t = cal.getTimeInMillis();
2278            if (t != expected) {
2279                errln("FAIL: wrong date after add: expected=" + expected + " returned=" + t);
2280            }
2281        } catch (IllegalArgumentException e) {
2282            errln("FAIL: add method should not throw IllegalArgumentException");
2283        }
2284    }
2285
2286    /*
2287     * Test case for ticket#8596.
2288     * Setting an year followed by getActualMaximum(Calendar.WEEK_OF_YEAR)
2289     * may result wrong maximum week.
2290     */
2291    @Test
2292    public void TestT8596() {
2293        GregorianCalendar gc = new GregorianCalendar(TimeZone.getTimeZone("Etc/GMT"));
2294        gc.setFirstDayOfWeek(Calendar.MONDAY);
2295        gc.setMinimalDaysInFirstWeek(4);
2296
2297        // Force the calender to resolve the fields once.
2298        // The maximum week number in 2011 is 52.
2299        gc.set(Calendar.YEAR, 2011);
2300        gc.get(Calendar.YEAR);
2301
2302        // Set a date in year 2009, but not calling get to resolve
2303        // the calendar's internal field yet.
2304        gc.set(2009, Calendar.JULY, 1);
2305
2306        // Then call getActuamMaximum for week of year.
2307        // #8596 was caused by conflict between year set
2308        // above and internal work calendar field resolution.
2309        int maxWeeks = gc.getActualMaximum(Calendar.WEEK_OF_YEAR);
2310        if (maxWeeks != 53) {
2311            errln("FAIL: Max week in 2009 in ISO calendar is 53, but got " + maxWeeks);
2312        }
2313    }
2314
2315    /**
2316     * Test case for ticket:9019
2317     */
2318    @Test
2319    public void Test9019() {
2320        GregorianCalendar cal1 = new GregorianCalendar(TimeZone.GMT_ZONE,ULocale.US);
2321        GregorianCalendar cal2 = new GregorianCalendar(TimeZone.GMT_ZONE,ULocale.US);
2322        cal1.clear();
2323        cal2.clear();
2324        cal1.set(2011,Calendar.MAY,06);
2325        cal2.set(2012,Calendar.JANUARY,06);
2326        cal1.setLenient(false);
2327        cal1.add(Calendar.MONTH, 8);
2328        if(!cal1.getTime().equals(cal2.getTime())) {
2329            errln("Error: Calendar is " + cal1.getTime() + " but expected " + cal2.getTime());
2330        } else {
2331            logln("Pass: rolled calendar is " + cal1.getTime());
2332        }
2333    }
2334
2335    /**
2336     * Test case for ticket 9452
2337     * Calendar addition fall onto the missing date - 2011-12-30 in Samoa
2338     */
2339    @Test
2340    public void TestT9452() {
2341        TimeZone samoaTZ = TimeZone.getTimeZone("Pacific/Apia");
2342        GregorianCalendar cal = new GregorianCalendar(samoaTZ);
2343
2344        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZZZZZ");
2345        sdf.setTimeZone(samoaTZ);
2346
2347        // Set date to 2011-12-29 00:00
2348        cal.clear();
2349        cal.set(2011, Calendar.DECEMBER, 29, 0, 0, 0);
2350
2351        Date d = cal.getTime();
2352        String dstr = sdf.format(d);
2353        logln("Initial date: " + dstr);
2354
2355        // Add 1 day
2356        cal.add(Calendar.DATE, 1);
2357        d = cal.getTime();
2358        dstr = sdf.format(d);
2359        logln("+1 day: " + dstr);
2360        assertEquals("Add 1 day", "2011-12-31T00:00:00+14:00", dstr);
2361
2362        // Subtract 1 day
2363        cal.add(Calendar.DATE, -1);
2364        d = cal.getTime();
2365        dstr = sdf.format(d);
2366        logln("-1 day: " + dstr);
2367        assertEquals("Subtract 1 day", "2011-12-29T00:00:00-10:00", dstr);
2368    }
2369
2370    /**
2371     * Test case for ticket 9403
2372     * semantic API change when attempting to call setTimeInMillis(long) with a value outside the bounds.
2373     * In strict mode an IllegalIcuArgumentException will be thrown
2374     * In lenient mode the value will be pinned to the relative min/max
2375     */
2376    @Test
2377    public void TestT9403() {
2378    	Calendar myCal = Calendar.getInstance();
2379    	long dateBit1, dateBit2, testMillis = 0L;
2380    	boolean missedException = true;
2381
2382    	testMillis = -184303902611600000L;
2383        logln("Testing invalid setMillis value in lienent mode - using value: " + testMillis);
2384
2385    	try {
2386    		myCal.setTimeInMillis(testMillis);
2387    	} catch (IllegalArgumentException e) {
2388    		logln("Fail: detected as bad millis");
2389    		missedException = false;
2390    	}
2391    	assertTrue("Fail: out of bound millis did not trigger exception!", missedException);
2392   	    dateBit1 = myCal.get(Calendar.MILLISECOND);
2393   	    assertNotEquals("Fail: millis not changed to MIN_MILLIS", testMillis, dateBit1);
2394
2395
2396        logln("Testing invalid setMillis value in strict mode - using value: " + testMillis);
2397        myCal.setLenient(false);
2398        try {
2399            myCal.setTimeInMillis(testMillis);
2400        } catch (IllegalArgumentException e) {
2401            logln("Pass: correctly detected bad millis");
2402            missedException = false;
2403        }
2404        dateBit1 = myCal.get(Calendar.DAY_OF_MONTH);
2405        dateBit2 = myCal.getTimeInMillis();
2406        assertFalse("Fail: error in setMillis, allowed invalid value : " + testMillis + "...returned dayOfMonth : " + dateBit1 + " millis : " + dateBit2, missedException);
2407    }
2408
2409    /**
2410     * Test case for ticket 9968
2411     * subparse fails to return an error indication when start pos is 0
2412     */
2413    @Test
2414    public void TestT9968() {
2415        SimpleDateFormat sdf0 = new SimpleDateFormat("-MMMM");
2416        ParsePosition pos0 = new ParsePosition(0);
2417        /* Date d0 = */ sdf0.parse("-September", pos0);
2418        logln("sdf0: " + pos0.getErrorIndex() + "/" + pos0.getIndex());
2419        assertTrue("Fail: failed a good test", pos0.getErrorIndex() == -1);
2420
2421        SimpleDateFormat sdf1 = new SimpleDateFormat("-MMMM");
2422        ParsePosition pos1 = new ParsePosition(0);
2423        /* Date d1 = */ sdf1.parse("-????", pos1);
2424        logln("sdf1: " + pos1.getErrorIndex() + "/" + pos1.getIndex());
2425        assertTrue("Fail: failed to detect bad parse", pos1.getErrorIndex() == 1);
2426
2427        SimpleDateFormat sdf2 = new SimpleDateFormat("MMMM");
2428        ParsePosition pos2 = new ParsePosition(0);
2429        /* Date d2 = */ sdf2.parse("????", pos2);
2430        logln("sdf2: " + pos2.getErrorIndex() + "/" + pos2.getIndex());
2431        assertTrue("Fail: failed to detect bad parse", pos2.getErrorIndex() == 0);
2432    }
2433
2434    @Test
2435    public void TestWeekendData_10560() {
2436        final Calendar.WeekData worldWeekData = new Calendar.WeekData(2, 1, 7, 0, 1, 86400000);
2437        final Calendar.WeekData usWeekData = new Calendar.WeekData(1, 1, 7, 0, 1, 86400000);
2438        final Calendar.WeekData testWeekData = new Calendar.WeekData(1, 2, 3, 4, 5, 86400000);
2439
2440        assertEquals("World", worldWeekData, Calendar.getWeekDataForRegion("001"));
2441        assertEquals("Illegal code => world", Calendar.getWeekDataForRegion("001"), Calendar.getWeekDataForRegion("xx"));
2442        assertEquals("FR = DE", Calendar.getWeekDataForRegion("FR"), Calendar.getWeekDataForRegion("DE"));
2443        assertNotEquals("IN ≠ world", Calendar.getWeekDataForRegion("001"), Calendar.getWeekDataForRegion("IN"));
2444        assertNotEquals("FR ≠ EG", Calendar.getWeekDataForRegion("FR"), Calendar.getWeekDataForRegion("EG"));
2445
2446        Calendar aCalendar = Calendar.getInstance(Locale.US);
2447        assertEquals("US", usWeekData, aCalendar.getWeekData());
2448        Calendar rgusCalendar = Calendar.getInstance(new ULocale("hi_IN@rg=USzzzz"));
2449        assertEquals("IN@rg=US", usWeekData, rgusCalendar.getWeekData());
2450
2451        aCalendar.setWeekData(testWeekData);
2452        assertEquals("Custom", testWeekData, aCalendar.getWeekData());
2453    }
2454
2455    /**
2456     * Test case for Ticket 13080
2457     * DateFormat#getDateTimeInstance() with the desired calendar type ignores the first parameter Calendar cal.
2458     */
2459    @Test
2460    public void TestT13080() {
2461        Calendar setCal = Calendar.getInstance();
2462        setCal.clear();
2463        setCal.set(Calendar.YEAR, 2017);
2464        setCal.set(Calendar.MONTH, 4);
2465        setCal.set(Calendar.DATE, 5);
2466        Calendar calArr[] = {
2467                Calendar.getInstance(),
2468                new IslamicCalendar(),
2469                new HebrewCalendar(),
2470                new GregorianCalendar()
2471        };
2472
2473        String[] expectedFormat = {
2474                "Friday, May 5, 2017",
2475                "Friday, Shaʻban 8, 1438 AH",
2476                "Friday, 9 Iyar 5777",
2477                "Friday, May 5, 2017"
2478        };
2479
2480        List<String> formattedDateList = new ArrayList<String>();
2481        for (Calendar cal : calArr) {
2482            cal.setTime(setCal.getTime());
2483            DateFormat format = DateFormat.getDateInstance(cal, DateFormat.FULL,
2484                                Locale.getDefault());
2485            formattedDateList.add(format.format(cal.getTime()));
2486        }
2487
2488        String[] actualFormat = formattedDateList.toArray(new String[0]);
2489        assertEquals("Fail: dateformat doesn't interpret calendar correctly", expectedFormat, actualFormat);
2490    }
2491
2492    @Test
2493    public void TestTicket11632() {
2494        Calendar cal = Calendar.getInstance();
2495        cal.clear();
2496        cal.set(Calendar.HOUR, 596);
2497        // hour value set upto 596 lies within the integer range for millisecond calculations
2498        assertEquals("Incorrect time for integer range milliseconds","Sun Jan 25 20:00:00 PST 1970", cal.getTime().toString());
2499        cal.clear();
2500        //  hour value set above 596 lies outside the integer range for millisecond calculations. This will invoke
2501        // the long version of the compute millis in day method in the ICU internal API
2502        cal.set(Calendar.HOUR, 597);
2503        assertEquals("Incorrect time for long range milliseconds","Sun Jan 25 21:00:00 PST 1970", cal.getTime().toString());
2504        cal.clear();
2505        cal.set(Calendar.HOUR, 597);
2506        cal.set(Calendar.MINUTE, 60*24);
2507        assertEquals("Incorrect time for long range milliseconds","Mon Jan 26 21:00:00 PST 1970", cal.getTime().toString());
2508        cal.clear();
2509        cal.set(Calendar.HOUR_OF_DAY, 597);
2510        assertEquals("Incorrect time for long range milliseconds","Sun Jan 25 21:00:00 PST 1970", cal.getTime().toString());
2511    }
2512
2513    @Test
2514    public void TestPersianCalOverflow() {
2515        String localeID = "bs_Cyrl@calendar=persian";
2516        Calendar cal = Calendar.getInstance(new ULocale(localeID));
2517        int maxMonth = cal.getMaximum(Calendar.MONTH);
2518        int maxDayOfMonth = cal.getMaximum(Calendar.DATE);
2519        int jd, month, dayOfMonth;
2520        for (jd = 67023580; jd <= 67023584; jd++) { // year 178171, int32_t overflow if jd >= 67023582
2521            cal.clear();
2522            cal.set(Calendar.JULIAN_DAY, jd);
2523            month = cal.get(Calendar.MONTH);
2524            dayOfMonth = cal.get(Calendar.DATE);
2525            if (month > maxMonth || dayOfMonth > maxDayOfMonth) {
2526                errln("Error: localeID " + localeID + ", julianDay " + jd + "; maxMonth " + maxMonth + ", got month " + month +
2527                        "; maxDayOfMonth " + maxDayOfMonth + ", got dayOfMonth " + dayOfMonth);
2528            }
2529        }
2530    }
2531 }
2532//eof
2533