]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_2_1-src/src/com/ibm/icu/dev/test/calendar/CompatibilityTest.java
go
[Dictionary.git] / jars / icu4j-4_2_1-src / src / com / ibm / icu / dev / test / calendar / CompatibilityTest.java
1 //##header J2SE15
2 /**
3  *******************************************************************************
4  * Copyright (C) 2000-2009, International Business Machines Corporation and    *
5  * others. All Rights Reserved.                                                *
6  *******************************************************************************
7  */
8 package com.ibm.icu.dev.test.calendar;
9 import com.ibm.icu.util.*;
10 import com.ibm.icu.text.DateFormat;
11
12 import java.util.Date;
13 import java.util.Locale;
14 import java.io.*;
15
16 public class CompatibilityTest extends com.ibm.icu.dev.test.TestFmwk {
17
18     public static void main(String argv[]) throws Exception {
19         new CompatibilityTest().run(argv);
20     }
21
22     static final String[] FIELD_NAME = {
23         "ERA", "YEAR", "MONTH", "WEEK_OF_YEAR", "WEEK_OF_MONTH",
24         "DAY_OF_MONTH", "DAY_OF_YEAR", "DAY_OF_WEEK",
25         "DAY_OF_WEEK_IN_MONTH", "AM_PM", "HOUR", "HOUR_OF_DAY",
26         "MINUTE", "SECOND", "MILLISECOND", "ZONE_OFFSET",
27         "DST_OFFSET", "YEAR_WOY", "DOW_LOCAL", "EXTENDED_YEAR",
28         "JULIAN_DAY", "MILLISECONDS_IN_DAY",
29     };
30
31     /**
32      * Test the behavior of the GregorianCalendar around the changeover.
33      */
34     public void TestGregorianChangeover() {
35     
36         java.util.TimeZone jdkGMT = java.util.TimeZone.getTimeZone("GMT");
37         java.util.Calendar jdkCal = java.util.Calendar.getInstance(jdkGMT);
38         jdkCal.clear();
39         jdkCal.set(1582, Calendar.OCTOBER, 15);
40         
41 //      if(jdkCal instanceof java.util.GregorianCalendar) {
42 //          logln("jdk IS grego");
43 //          java.util.GregorianCalendar jdkgc = (java.util.GregorianCalendar)
44 //          jdkCal;
45 //          logln("jdk change at: " + jdkgc.getGregorianChange() + "(" + jdkgc.getGregorianChange().getTime() +")" );
46 //      } else {
47 //          logln("jdk NOT grego");
48 //      }
49
50         long a = jdkCal.getTime().getTime();
51         Date c = jdkCal.getTime();
52         c.toString();
53         long b = c.getTime();
54         if(a!=b) {
55             logln(" " + a + " != " + b);
56             logln("JDK has Gregorian cutover anomaly (1.5?) - skipping this test.");
57             return;
58         }
59
60         Date co = jdkCal.getTime();
61         logln("Change over (Oct 15 1582) = " + co + " (" + co.getTime() + ")");
62         final int ONE_DAY = 24*60*60*1000;
63         TimeZone gmt = TimeZone.getTimeZone("GMT");
64         GregorianCalendar cal = new GregorianCalendar(gmt);
65         /*
66           Changeover -7 days: 1582/9/28 dow=6
67           Changeover -6 days: 1582/9/29 dow=7
68           Changeover -5 days: 1582/9/30 dow=1
69           Changeover -4 days: 1582/10/1 dow=2
70           Changeover -3 days: 1582/10/2 dow=3
71           Changeover -2 days: 1582/10/3 dow=4
72           Changeover -1 days: 1582/10/4 dow=5
73           Changeover +0 days: 1582/10/15 dow=6
74           Changeover +1 days: 1582/10/16 dow=7
75           Changeover +2 days: 1582/10/17 dow=1
76           Changeover +3 days: 1582/10/18 dow=2
77           Changeover +4 days: 1582/10/19 dow=3
78           Changeover +5 days: 1582/10/20 dow=4
79           Changeover +6 days: 1582/10/21 dow=5
80           Changeover +7 days: 1582/10/22 dow=6
81           */
82         int MON[] = {  9,  9,  9,10,10,10,10, 10, 10, 10, 10, 10, 10, 10, 10 };
83         int DOM[] = { 28, 29, 30, 1, 2, 3, 4, 15, 16, 17, 18, 19, 20, 21, 22 };
84         int DOW[] = {  6,  7,  1, 2, 3, 4, 5,  6,  7,  1,  2,  3,  4,  5,  6 };
85         //                                     ^ <-Changeover Fri Oct 15 1582
86         int j=0;
87         for (int i=-7; i<=7; ++i, ++j) {
88             Date d = new Date(co.getTime() + i*ONE_DAY);
89             cal.setTime(d);
90             int y = cal.get(Calendar.YEAR), mon = cal.get(Calendar.MONTH)+1-Calendar.JANUARY,
91                 dom = cal.get(Calendar.DATE), dow = cal.get(Calendar.DAY_OF_WEEK);
92             logln("Changeover " + (i>=0?"+":"") +
93                   i + " days: " + y + "/" + mon + "/" + dom + " dow=" + dow);
94             if (y != 1582 || mon != MON[j] || dom != DOM[j] || dow != DOW[j])
95                 errln(" Fail: Above line is wrong");
96         }
97     }
98
99     /**
100      * Test the mapping between millis and fields.  For the purposes
101      * of this test, we don't care about timezones and week data
102      * (first day of week, minimal days in first week).
103      */
104     public void TestMapping() {
105         if (false) {
106             Date PURE_GREGORIAN = new Date(Long.MIN_VALUE);
107             Date PURE_JULIAN = new Date(Long.MAX_VALUE);
108             GregorianCalendar cal =
109                 new GregorianCalendar(TimeZone.getTimeZone("UTC"));
110             final int EPOCH_JULIAN = 2440588;
111             final long ONE_DAY = 24*60*60*1000L;
112             com.ibm.icu.text.SimpleDateFormat fmt =
113                 new com.ibm.icu.text.SimpleDateFormat("EEE MMM dd yyyy G");
114                 /*HH:mm:ss.SSS z*/
115
116             for (int type=0; type<2; ++type) {
117                 System.out.println(type==0 ? "Gregorian" : "Julian");
118                 cal.setGregorianChange(type==0 ? PURE_GREGORIAN : PURE_JULIAN);
119                 fmt.setCalendar(cal);
120                 int[] J = {
121                     0x7FFFFFFF,
122                     0x7FFFFFF0,
123                     0x7F000000,
124                     0x78000000,
125                     0x70000000,
126                     0x60000000,
127                     0x50000000,
128                     0x40000000,
129                     0x30000000,
130                     0x20000000,
131                     0x10000000,
132                 };
133                 for (int i=0; i<J.length; ++i) {
134                     String[] lim = new String[2];
135                     long[] ms = new long[2];
136                     int jd = J[i];
137                     for (int sign=0; sign<2; ++sign) {
138                         int julian = jd;
139                         if (sign==0) julian = -julian;
140                         long millis = ((long)julian - EPOCH_JULIAN) * ONE_DAY;
141                         ms[sign] = millis;
142                         cal.setTime(new Date(millis));
143                         lim[sign] = fmt.format(cal.getTime());
144                     }
145                     System.out.println("JD +/-" +
146                                        Long.toString(jd, 16) +
147                                        ": " + ms[0] + ".." + ms[1] +
148                                        ": " + lim[0] + ".." + lim[1]);
149                 }
150             }
151         }
152
153         TimeZone saveZone = TimeZone.getDefault();
154         try {
155             TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
156             //NEWCAL
157             Date PURE_GREGORIAN = new Date(Long.MIN_VALUE);
158             Date PURE_JULIAN = new Date(Long.MAX_VALUE);
159             GregorianCalendar cal = new GregorianCalendar();
160             final int EPOCH_JULIAN = 2440588;
161             final long ONE_DAY = 24*60*60*1000L;
162             int[] DATA = {
163                 // Julian#   Year  Month               DOM   JULIAN:Year, Month,       DOM
164                 2440588,     1970, Calendar.JANUARY,   1,    1969, Calendar.DECEMBER,  19, 
165                 2415080,     1900, Calendar.MARCH,     1,    1900, Calendar.FEBRUARY,  17,
166                 2451604,     2000, Calendar.FEBRUARY,  29,   2000, Calendar.FEBRUARY,  16,
167                 2452269,     2001, Calendar.DECEMBER,  25,   2001, Calendar.DECEMBER,  12,
168                 2416526,     1904, Calendar.FEBRUARY,  15,   1904, Calendar.FEBRUARY,  2,
169                 2416656,     1904, Calendar.JUNE,      24,   1904, Calendar.JUNE,      11,
170                 1721426,        1, Calendar.JANUARY,   1,       1, Calendar.JANUARY,   3,
171                 2000000,      763, Calendar.SEPTEMBER, 18,    763, Calendar.SEPTEMBER, 14,
172                 4000000,     6239, Calendar.JULY,      12,   6239, Calendar.MAY,       28,
173                 8000000,    17191, Calendar.FEBRUARY,  26,  17190, Calendar.OCTOBER,   22,
174                 10000000,   22666, Calendar.DECEMBER,  20,  22666, Calendar.JULY,      5,
175             };
176             for (int i=0; i<DATA.length; i+=7) {
177                 int julian = DATA[i];
178                 int year = DATA[i+1];
179                 int month = DATA[i+2];
180                 int dom = DATA[i+3];
181                 int year2, month2, dom2;
182                 long millis = (julian - EPOCH_JULIAN) * ONE_DAY;
183                 String s;
184
185                 // Test Gregorian computation
186                 cal.setGregorianChange(PURE_GREGORIAN);
187                 cal.clear();
188                 cal.set(year, month, dom);
189                 long calMillis = cal.getTime().getTime();
190                 long delta = calMillis - millis;
191                 cal.setTime(new Date(millis));
192                 year2 = cal.get(Calendar.YEAR);
193                 month2 = cal.get(Calendar.MONTH);
194                 dom2 = cal.get(Calendar.DAY_OF_MONTH);
195                 s = "G " + year + "-" + (month+1-Calendar.JANUARY) + "-" + dom +
196                     " => " + calMillis +
197                     " (" + ((float)delta/ONE_DAY) + " day delta) => " +
198                     year2 + "-" + (month2+1-Calendar.JANUARY) + "-" + dom2;
199                 if (delta != 0 || year != year2 || month != month2 ||
200                     dom != dom2) errln(s + " FAIL");
201                 else logln(s);
202                 
203                 // Test Julian computation
204                 year = DATA[i+4];
205                 month = DATA[i+5];
206                 dom = DATA[i+6];
207                 cal.setGregorianChange(PURE_JULIAN);
208                 cal.clear();
209                 cal.set(year, month, dom);
210                 calMillis = cal.getTime().getTime();
211                 delta = calMillis - millis;
212                 cal.setTime(new Date(millis));
213                 year2 = cal.get(Calendar.YEAR);
214                 month2 = cal.get(Calendar.MONTH);
215                 dom2 = cal.get(Calendar.DAY_OF_MONTH);
216                 s = "J " + year + "-" + (month+1-Calendar.JANUARY) + "-" + dom +
217                     " => " + calMillis +
218                     " (" + ((float)delta/ONE_DAY) + " day delta) => " +
219                     year2 + "-" + (month2+1-Calendar.JANUARY) + "-" + dom2;
220                 if (delta != 0 || year != year2 || month != month2 ||
221                     dom != dom2) errln(s + " FAIL");
222                 else logln(s);
223             }
224
225             java.util.Calendar tempcal = java.util.Calendar.getInstance();
226             tempcal.clear();
227             tempcal.set(1582, Calendar.OCTOBER, 15);
228             cal.setGregorianChange(tempcal.getTime());
229             auxMapping(cal, 1582, Calendar.OCTOBER, 4);
230             auxMapping(cal, 1582, Calendar.OCTOBER, 15);
231             auxMapping(cal, 1582, Calendar.OCTOBER, 16);
232             for (int y=800; y<3000; y+=1+(int)(100*Math.random())) {
233                 for (int m=Calendar.JANUARY; m<=Calendar.DECEMBER; ++m) {
234                     auxMapping(cal, y, m, 15);
235                 }
236             }
237         }
238         finally {
239             TimeZone.setDefault(saveZone);
240         }
241     }
242     private void auxMapping(Calendar cal, int y, int m, int d) {
243         cal.clear();
244         cal.set(y, m, d);
245         long millis = cal.getTime().getTime();
246         cal.setTime(new Date(millis));
247         int year2 = cal.get(Calendar.YEAR);
248         int month2 = cal.get(Calendar.MONTH);
249         int dom2 = cal.get(Calendar.DAY_OF_MONTH);
250         if (y != year2 || m != month2 || dom2 != d)
251             errln("Round-trip failure: " + y + "-" + (m+1) + "-"+d+" =>ms=> " +
252                   year2 + "-" + (month2+1) + "-" + dom2);
253     }
254
255     public void TestGenericAPI() {
256         // not used String str;
257
258         java.util.Calendar tempcal = java.util.Calendar.getInstance();
259         tempcal.clear();
260         tempcal.set(1990, Calendar.APRIL, 15);
261         Date when = tempcal.getTime();
262
263         String tzid = "TestZone";
264         int tzoffset = 123400;
265
266         SimpleTimeZone zone = new SimpleTimeZone(tzoffset, tzid);
267         Calendar cal = (Calendar)Calendar.getInstance((SimpleTimeZone)zone.clone());
268
269         if (!zone.equals(cal.getTimeZone())) errln("FAIL: Calendar.getTimeZone failed");
270
271         Calendar cal2 = Calendar.getInstance(cal.getTimeZone());
272
273         cal.setTime(when);
274         cal2.setTime(when);
275
276         if (!(cal.equals(cal2))) errln("FAIL: Calendar.operator== failed");
277         // if ((*cal != *cal2))  errln("FAIL: Calendar.operator!= failed");
278         if (!cal.equals(cal2) ||
279             cal.before(cal2) ||
280             cal.after(cal2)) errln("FAIL: equals/before/after failed");
281
282         cal2.setTime(new Date(when.getTime() + 1000));
283         if (cal.equals(cal2) ||
284             cal2.before(cal) ||
285             cal.after(cal2)) errln("FAIL: equals/before/after failed");
286
287         cal.roll(Calendar.SECOND, true);
288         if (!cal.equals(cal2) ||
289             cal.before(cal2) ||
290             cal.after(cal2)) errln("FAIL: equals/before/after failed");
291
292         // Roll back to January
293         cal.roll(Calendar.MONTH, (int)(1 + Calendar.DECEMBER - cal.get(Calendar.MONTH)));
294         if (cal.equals(cal2) ||
295             cal2.before(cal) ||
296             cal.after(cal2)) errln("FAIL: equals/before/after failed");
297
298         // C++ only
299         /* TimeZone z = cal.orphanTimeZone();
300            if (z.getID(str) != tzid ||
301            z.getRawOffset() != tzoffset)
302            errln("FAIL: orphanTimeZone failed");
303            */
304
305         for (int i=0; i<2; ++i) {
306             boolean lenient = ( i > 0 );
307             cal.setLenient(lenient);
308             if (lenient != cal.isLenient()) errln("FAIL: setLenient/isLenient failed");
309             // Later: Check for lenient behavior
310         }
311
312         int i;
313         for (i=Calendar.SUNDAY; i<=Calendar.SATURDAY; ++i) {
314             cal.setFirstDayOfWeek(i);
315             if (cal.getFirstDayOfWeek() != i) errln("FAIL: set/getFirstDayOfWeek failed");
316         }
317
318         for (i=1; i<=7; ++i) {
319             cal.setMinimalDaysInFirstWeek(i);
320             if (cal.getMinimalDaysInFirstWeek() != i) errln("FAIL: set/getFirstDayOfWeek failed");
321         }
322
323         for (i=0; i<cal.getFieldCount(); ++i) {
324             if (cal.getMinimum(i) > cal.getGreatestMinimum(i))
325                 errln("FAIL: getMinimum larger than getGreatestMinimum for field " + i);
326             if (cal.getLeastMaximum(i) > cal.getMaximum(i))
327                 errln("FAIL: getLeastMaximum larger than getMaximum for field " + i);
328             if (cal.getMinimum(i) >= cal.getMaximum(i))
329                 errln("FAIL: getMinimum not less than getMaximum for field " + i);
330         }
331
332         cal.setTimeZone(TimeZone.getDefault());
333         cal.clear();
334         cal.set(1984, 5, 24);
335         tempcal.clear();
336         tempcal.set(1984, 5, 24);
337         if (cal.getTime().getTime() != tempcal.getTime().getTime()) {
338             errln("FAIL: Calendar.set(3 args) failed");
339             logln(" Got: " + cal.getTime() + "  Expected: " + tempcal.getTime());
340         }
341
342 //#if defined(FOUNDATION10) || defined(J2SE13)
343 //##        // This test case does not work well with JRE1.3 with
344 //##        // the timezone update for US 2007 rule.  Java 1.3 only
345 //##        // supports single DST rule for all years.  April 2, 1985
346 //##        // was actually not in DST, but with the new rule, the date
347 //##        // is in DST (which is actually wrong).
348 //#else
349         cal.clear();
350         cal.set(1985, 2, 2, 11, 49);
351         tempcal.clear();
352         tempcal.set(1985, 2, 2, 11, 49);
353         if (cal.getTime().getTime() != tempcal.getTime().getTime()) {
354             errln("FAIL: Calendar.set(5 args) failed");
355             logln(" Got: " + cal.getTime() + "  Expected: " + tempcal.getTime());
356         }
357 //#endif
358
359         cal.clear();
360         cal.set(1995, 9, 12, 1, 39, 55);
361         tempcal.clear();
362         tempcal.set(1995, 9, 12, 1, 39, 55);
363         if (cal.getTime().getTime() != tempcal.getTime().getTime()) {
364             errln("FAIL: Calendar.set(6 args) failed");
365             logln(" Got: " + cal.getTime() + "  Expected: " + tempcal.getTime());
366         }
367
368         cal.getTime();
369         // This test is strange -- why do we expect certain fields to be set, and
370         // others not to be?  Revisit the appropriateness of this.  - Alan NEWCAL
371         for (i=0; i<cal.getFieldCount(); ++i) {
372             switch(i) {
373             case Calendar.YEAR: case Calendar.MONTH: case Calendar.DATE:
374             case Calendar.HOUR_OF_DAY: case Calendar.MINUTE: case Calendar.SECOND:
375             case Calendar.EXTENDED_YEAR:
376                 if (!cal.isSet(i)) errln("FAIL: " + FIELD_NAME[i] + " is not set");
377                 break;
378             default:
379                 if (cal.isSet(i)) errln("FAIL: " + FIELD_NAME[i] + " is set");
380             }
381             cal.clear(i);
382             if (cal.isSet(i)) errln("FAIL: Calendar.clear/isSet failed");
383         }
384
385         // delete cal;
386         // delete cal2;
387
388         Locale[] loc = Calendar.getAvailableLocales();
389         long count = loc.length;
390         if (count < 1 || loc == null) {
391             errln("FAIL: getAvailableLocales failed");
392         }
393         else {
394             for (i=0; i<count; ++i) {
395                 cal = Calendar.getInstance(loc[i]);
396                 // delete cal;
397             }
398         }
399
400         cal = Calendar.getInstance(TimeZone.getDefault(), Locale.ENGLISH);
401         // delete cal;
402
403         cal = Calendar.getInstance(zone, Locale.ENGLISH);
404         // delete cal;
405
406         GregorianCalendar gc = new GregorianCalendar(zone);
407         // delete gc;
408
409         gc = new GregorianCalendar(Locale.ENGLISH);
410         // delete gc;
411
412         gc = new GregorianCalendar(Locale.ENGLISH);
413         // delete gc;
414
415         gc = new GregorianCalendar(zone, Locale.ENGLISH);
416         // delete gc;
417
418         gc = new GregorianCalendar(zone);
419         // delete gc;
420
421         gc = new GregorianCalendar(1998, 10, 14, 21, 43);
422         tempcal.clear();
423         tempcal.set(1998, 10, 14, 21, 43);
424         if (gc.getTime().getTime() != tempcal.getTime().getTime())
425             errln("FAIL: new GregorianCalendar(ymdhm) failed");
426         // delete gc;
427
428         gc = new GregorianCalendar(1998, 10, 14, 21, 43, 55);
429         tempcal.clear();
430         tempcal.set(1998, 10, 14, 21, 43, 55);
431         if (gc.getTime().getTime() != tempcal.getTime().getTime())
432             errln("FAIL: new GregorianCalendar(ymdhms) failed");
433
434         // C++ only:
435         // GregorianCalendar gc2 = new GregorianCalendar(Locale.ENGLISH);
436         // gc2 = gc;
437         // if (gc2 != gc || !(gc2 == gc)) errln("FAIL: GregorianCalendar assignment/operator==/operator!= failed");
438         // delete gc;
439         // delete z;
440     }
441
442     // Verify Roger Webster's bug
443     public void TestRog() {
444         GregorianCalendar gc = new GregorianCalendar();
445
446         int year = 1997, month = Calendar.APRIL, date = 1;
447         gc.set(year, month, date); // April 1, 1997
448
449         gc.set(Calendar.HOUR_OF_DAY, 23);
450         gc.set(Calendar.MINUTE, 0);
451         gc.set(Calendar.SECOND, 0);
452         gc.set(Calendar.MILLISECOND, 0);
453
454         for (int i = 0; i < 9; i++, gc.add(Calendar.DATE, 1)) {
455             if (gc.get(Calendar.YEAR) != year ||
456                 gc.get(Calendar.MONTH) != month ||
457                 gc.get(Calendar.DATE) != (date + i))
458                 errln("FAIL: Date " + gc.getTime() + " wrong");
459         }
460     }
461
462     // Verify DAY_OF_WEEK
463     public void TestDOW943() {
464         dowTest(false);
465         dowTest(true);
466     }
467
468     void dowTest(boolean lenient) {
469         GregorianCalendar cal = new GregorianCalendar();
470         cal.set(1997, Calendar.AUGUST, 12); // Wednesday
471         cal.getTime(); // Force update
472         cal.setLenient(lenient);
473         cal.set(1996, Calendar.DECEMBER, 1); // Set the date to be December 1, 1996
474         int dow = cal.get(Calendar.DAY_OF_WEEK);
475         int min = cal.getMinimum(Calendar.DAY_OF_WEEK);
476         int max = cal.getMaximum(Calendar.DAY_OF_WEEK);
477         if (dow < min || dow > max) errln("FAIL: Day of week " + dow + " out of range");
478         if (dow != Calendar.SUNDAY) {
479             errln("FAIL2: Day of week should be SUNDAY; is " + dow + ": " + cal.getTime());
480         }
481         if (min != Calendar.SUNDAY || max != Calendar.SATURDAY) errln("FAIL: Min/max bad");
482     }
483
484     // Verify that the clone method produces distinct objects with no
485     // unintentionally shared fields.
486     public void TestClonesUnique908() {
487         Calendar c = Calendar.getInstance();
488         Calendar d = (Calendar)c.clone();
489         c.set(Calendar.MILLISECOND, 123);
490         d.set(Calendar.MILLISECOND, 456);
491         if (c.get(Calendar.MILLISECOND) != 123 ||
492             d.get(Calendar.MILLISECOND) != 456) {
493             errln("FAIL: Clones share fields");
494         }
495     }
496
497     // Verify effect of Gregorian cutoff value
498     public void TestGregorianChange768() {
499         boolean b;
500         GregorianCalendar c = new GregorianCalendar();
501         logln("With cutoff " + c.getGregorianChange());
502         logln(" isLeapYear(1800) = " + (b=c.isLeapYear(1800)));
503         logln(" (should be FALSE)");
504         if (b != false) errln("FAIL");
505         java.util.Calendar tempcal = java.util.Calendar.getInstance();
506         tempcal.clear();
507         tempcal.set(1900, 0, 1);
508         c.setGregorianChange(tempcal.getTime()); // Jan 1 1900
509         logln("With cutoff " + c.getGregorianChange());
510         logln(" isLeapYear(1800) = " + (b=c.isLeapYear(1800)));
511         logln(" (should be TRUE)");
512         if (b != true) errln("FAIL");
513     }
514
515     // Test the correct behavior of the disambiguation algorithm.
516     public void TestDisambiguation765() throws Exception {
517         Calendar c = Calendar.getInstance();
518         c.setLenient(false);
519
520         c.clear();
521         c.set(Calendar.YEAR, 1997);
522         c.set(Calendar.MONTH, Calendar.JUNE);
523         c.set(Calendar.DATE, 3);
524
525         verify765("1997 third day of June = ", c, 1997, Calendar.JUNE, 3);
526
527         c.clear();
528         c.set(Calendar.YEAR, 1997);
529         c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
530         c.set(Calendar.MONTH, Calendar.JUNE);
531         c.set(Calendar.DAY_OF_WEEK_IN_MONTH, 1);
532         verify765("1997 first Tuesday in June = ", c, 1997, Calendar.JUNE, 3);
533
534         c.clear();
535         c.set(Calendar.YEAR, 1997);
536         c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
537         c.set(Calendar.MONTH, Calendar.JUNE);
538         c.set(Calendar.DAY_OF_WEEK_IN_MONTH, -1);
539         verify765("1997 last Tuesday in June = ", c, 1997, Calendar.JUNE, 24);
540
541         IllegalArgumentException e = null;
542         try {
543             c.clear();
544             c.set(Calendar.YEAR, 1997);
545             c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
546             c.set(Calendar.MONTH, Calendar.JUNE);
547             c.set(Calendar.DAY_OF_WEEK_IN_MONTH, 0);
548             c.getTime();
549         }
550         catch (IllegalArgumentException ex) {
551             e = ex;
552         }
553         verify765("1997 zero-th Tuesday in June = ", e, c);
554
555         c.clear();
556         c.set(Calendar.YEAR, 1997);
557         c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
558         c.set(Calendar.MONTH, Calendar.JUNE);
559         c.set(Calendar.WEEK_OF_MONTH, 1);
560         verify765("1997 Tuesday in week 1 of June = ", c, 1997, Calendar.JUNE, 3);
561
562         c.clear();
563         c.set(Calendar.YEAR, 1997);
564         c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
565         c.set(Calendar.MONTH, Calendar.JUNE);
566         c.set(Calendar.WEEK_OF_MONTH, 5);
567         verify765("1997 Tuesday in week 5 of June = ", c, 1997, Calendar.JULY, 1);
568
569         try {
570             c.clear();
571             c.set(Calendar.YEAR, 1997);
572             c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
573             c.set(Calendar.MONTH, Calendar.JUNE);
574             c.set(Calendar.WEEK_OF_MONTH, 0);
575             c.getTime();
576         }
577         catch (IllegalArgumentException ex) {
578             e = ex;
579         }
580         verify765("1997 Tuesday in week 0 of June = ", e, c);
581
582         c.clear();
583         c.set(Calendar.YEAR, 1997);
584         c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
585         c.set(Calendar.WEEK_OF_YEAR, 1);
586         verify765("1997 Tuesday in week 1 of year = ", c, 1996, Calendar.DECEMBER, 31);
587
588         c.clear();
589         c.set(Calendar.YEAR, 1997);
590         c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
591         c.set(Calendar.WEEK_OF_YEAR, 10);
592         verify765("1997 Tuesday in week 10 of year = ", c, 1997, Calendar.MARCH, 4);
593
594         e = null;
595         try {
596             c.clear();
597             c.set(Calendar.YEAR, 1997);
598             c.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
599             c.set(Calendar.WEEK_OF_YEAR, 0);
600             c.getTime();
601         }
602         catch (IllegalArgumentException ex) {
603             e = ex;
604         }
605         verify765("1997 Tuesday in week 0 of year = ", e, c);
606     }
607     void verify765(String msg, Calendar c, int year, int month, int day) {
608         int cy = c.get(Calendar.YEAR); // NEWCAL
609         int cm = c.get(Calendar.MONTH);
610         int cd = c.get(Calendar.DATE);
611         if (cy == year &&
612             cm == month &&
613             cd == day) {
614             logln("PASS: " + msg + c.getTime());
615         }
616         else {
617             errln("FAIL: " + msg + cy + "/" + (cm+1) + "/" + cd +
618                   "=" + c.getTime() +
619                   "; expected " +
620                   year + "/" + (month+1) + "/" + day);
621         }
622     }
623     // Called when e expected to be non-null
624     void verify765(String msg, IllegalArgumentException e, Calendar c) {
625         if (e == null) errln("FAIL: No IllegalArgumentException for " + msg +
626                              c.getTime());
627         else logln("PASS: " + msg + "IllegalArgument as expected");
628     }
629
630     // Test the behavior of GMT vs. local time
631     public void TestGMTvsLocal4064654() {
632         // Sample output 1:
633         // % /usr/local/java/jdk1.1.3/solaris/bin/java test 1997 1 1 12 0 0
634         // date = Wed Jan 01 04:00:00 PST 1997
635         // offset for Wed Jan 01 04:00:00 PST 1997= -8hr
636         aux4064654(1997, 1, 1, 12, 0, 0);
637
638         // Sample output 2:
639         // % /usr/local/java/jdk1.1.3/solaris/bin/java test 1997 4 16 18 30 0
640         // date = Wed Apr 16 10:30:00 PDT 1997
641         // offset for Wed Apr 16 10:30:00 PDT 1997= -7hr
642
643         // Note that in sample output 2 according to the offset, the gmt time
644         // of the result would be 1997 4 16 17 30 0 which is different from the
645         // input of 1997 4 16 18 30 0.
646         aux4064654(1997, 4, 16, 18, 30, 0);
647     }
648     void aux4064654(int yr, int mo, int dt, int hr, int mn, int sc) {
649         Date date;
650         Calendar gmtcal = Calendar.getInstance();
651         gmtcal.setTimeZone(TimeZone.getTimeZone("Africa/Casablanca"));
652         gmtcal.set(yr, mo-1, dt, hr, mn, sc);
653         gmtcal.set(Calendar.MILLISECOND, 0);
654
655         date = gmtcal.getTime();
656         logln("date = "+date);
657
658         Calendar cal = Calendar.getInstance();
659         cal.setTimeZone(TimeZone.getTimeZone("America/Los_Angels"));
660         cal.setTime(date);
661
662         int offset = cal.getTimeZone().getOffset(cal.get(Calendar.ERA),
663                                                  cal.get(Calendar.YEAR),
664                                                  cal.get(Calendar.MONTH),
665                                                  cal.get(Calendar.DATE),
666                                                  cal.get(Calendar.DAY_OF_WEEK),
667                                                  cal.get(Calendar.MILLISECOND));
668
669         logln("offset for "+date+"= "+(offset/1000/60/60.0) + "hr");
670
671         int utc = ((cal.get(Calendar.HOUR_OF_DAY) * 60 +
672                     cal.get(Calendar.MINUTE)) * 60 +
673                    cal.get(Calendar.SECOND)) * 1000 +
674             cal.get(Calendar.MILLISECOND) - offset;
675
676         int expected = ((hr * 60 + mn) * 60 + sc) * 1000;
677
678         if (utc != expected)
679             errln("FAIL: Discrepancy of " +
680                   (utc - expected) + " millis = " +
681                   ((utc-expected)/1000/60/60.0) + " hr");
682     }
683
684     // Verify that add and set work regardless of the order in which
685     // they are called.
686     public void TestAddSetOrder621() {
687         java.util.Calendar tempcal = java.util.Calendar.getInstance();
688         tempcal.clear();
689         tempcal.set(1997, 4, 14, 13, 23, 45);
690         Date d = tempcal.getTime();
691
692         Calendar cal = Calendar.getInstance ();
693         cal.setTime (d);
694         cal.add (Calendar.DATE, -5);
695         cal.set (Calendar.HOUR_OF_DAY, 0);
696         cal.set (Calendar.MINUTE, 0);
697         cal.set (Calendar.SECOND, 0);
698         // ma feb 03 00:00:00 GMT+00:00 1997
699         String s = cal.getTime ().toString ();
700
701         cal = Calendar.getInstance ();
702         cal.setTime (d);
703         cal.set (Calendar.HOUR_OF_DAY, 0);
704         cal.set (Calendar.MINUTE, 0);
705         cal.set (Calendar.SECOND, 0);
706         cal.add (Calendar.DATE, -5);
707         // ma feb 03 13:11:06 GMT+00:00 1997
708         String s2 = cal.getTime ().toString ();
709
710         if (s.equals(s2))
711             logln("Pass: " + s + " == " + s2);
712         else
713             errln("FAIL: " + s + " != " + s2);
714     }
715
716     // Verify that add works.
717     public void TestAdd520() {
718         int y = 1997, m = Calendar.FEBRUARY, d = 1;
719         GregorianCalendar temp = new GregorianCalendar( y, m, d );
720         check520(temp, y, m, d);
721
722         temp.add( Calendar.YEAR, 1 );
723         y++;
724         check520(temp, y, m, d);
725
726         temp.add( Calendar.MONTH, 1 );
727         m++;
728         check520(temp, y, m, d);
729
730         temp.add( Calendar.DATE, 1 );
731         d++;
732         check520(temp, y, m, d);
733
734         temp.add( Calendar.DATE, 2 );
735         d += 2;
736         check520(temp, y, m, d);
737
738         temp.add( Calendar.DATE, 28 );
739         d = 1; ++m;
740         check520(temp, y, m, d);
741     }
742     void check520(Calendar c, int y, int m, int d) {
743         if (c.get(Calendar.YEAR) != y ||
744             c.get(Calendar.MONTH) != m ||
745             c.get(Calendar.DATE) != d) {
746             errln("FAILURE: Expected YEAR/MONTH/DATE of " +
747                   y + "/" + (m+1) + "/" + d +
748                   "; got " +
749                   c.get(Calendar.YEAR) + "/" +
750                   (c.get(Calendar.MONTH)+1) + "/" +
751                   c.get(Calendar.DATE));
752         }
753         else logln("Confirmed: " +
754                    y + "/" + (m+1) + "/" + d);
755     }
756
757     // Verify that setting fields works.  This test fails when an exception is thrown.
758     public void TestFieldSet4781() {
759         try {
760             GregorianCalendar g = new GregorianCalendar();
761             GregorianCalendar g2 = new GregorianCalendar();
762             // At this point UTC value is set, various fields are not.
763             // Now set to noon.
764             g2.set(Calendar.HOUR, 12);
765             g2.set(Calendar.MINUTE, 0);
766             g2.set(Calendar.SECOND, 0);
767             // At this point the object thinks UTC is NOT set, but fields are set.
768             // The following line will result in IllegalArgumentException because
769             // it thinks the YEAR is set and it is NOT.
770             if (g2.equals(g))
771                 logln("Same");
772             else
773                 logln("Different");
774         }
775         catch (IllegalArgumentException e) {
776             errln("Unexpected exception seen: " + e);
777         }
778     }
779
780     // Test serialization of a Calendar object
781     public void TestSerialize337() {
782         Calendar cal = Calendar.getInstance();
783
784         boolean ok = false;
785
786         try {
787             ByteArrayOutputStream f = new ByteArrayOutputStream();
788             ObjectOutput s = new ObjectOutputStream(f);
789             s.writeObject(PREFIX);
790             s.writeObject(cal);
791             s.writeObject(POSTFIX);
792             f.close();
793
794             ByteArrayInputStream in = new ByteArrayInputStream(f.toByteArray());
795             ObjectInputStream t = new ObjectInputStream(in);
796             String pre = (String)t.readObject();
797             Calendar c = (Calendar)t.readObject();
798             String post = (String)t.readObject();
799             in.close();
800
801             ok = pre.equals(PREFIX) &&
802                 post.equals(POSTFIX) &&
803                 cal.equals(c);
804         }
805         catch (IOException e) {
806             errln("FAIL: Exception received:");
807             // e.printStackTrace(log);
808         }
809         catch (ClassNotFoundException e) {
810             errln("FAIL: Exception received:");
811             // e.printStackTrace(log);
812         }
813
814         if (!ok) errln("Serialization of Calendar object failed.");
815     }
816     static final String PREFIX = "abc";
817     static final String POSTFIX = "def";
818     static final String FILENAME = "tmp337.bin";
819
820     // Try to zero out the seconds field
821     public void TestSecondsZero121() {
822         Calendar        cal = new GregorianCalendar();
823         // Initialize with current date/time
824         cal.setTime(new Date());
825         // Round down to minute
826         cal.set(Calendar.SECOND, 0);
827         Date    d = cal.getTime();
828         String s = d.toString();
829         if (s.indexOf(":00 ") < 0) errln("Expected to see :00 in " + s);
830     }
831
832     // Try various sequences of add, set, and get method calls.
833     public void TestAddSetGet0610() {
834         //
835         // Error case 1:
836         // - Upon initialization calendar fields, millis = System.currentTime
837         // - After set is called fields are initialized, time is not
838         // - Addition uses millis which are still *now*
839         //
840         {
841             Calendar calendar = new GregorianCalendar( ) ;
842             calendar.set( 1993, Calendar.JANUARY, 4 ) ;
843             logln( "1A) " + value( calendar ) ) ;
844             calendar.add( Calendar.DATE, 1 ) ;
845             String v = value(calendar);
846             logln( "1B) " + v );
847             logln( "--) 1993/0/5" ) ;
848             if (!v.equals(EXPECTED_0610)) errln("Expected " + EXPECTED_0610 +
849                                                 "; saw " + v);
850         }
851
852         //
853         // Error case 2:
854         // - Upon initialization calendar fields set, millis = 0
855         // - Addition uses millis which are still 1970, 0, 1
856         //
857
858         {
859             Calendar calendar = new GregorianCalendar( 1993, Calendar.JANUARY, 4 ) ;
860             logln( "2A) " + value( calendar ) ) ;
861             calendar.add( Calendar.DATE, 1 ) ;
862             String v = value(calendar);
863             logln( "2B) " + v );
864             logln( "--) 1993/0/5" ) ;
865             if (!v.equals(EXPECTED_0610)) errln("Expected " + EXPECTED_0610 +
866                                                 "; saw " + v);
867         }
868
869         //
870         // Error case 3:
871         // - Upon initialization calendar fields, millis = 0
872         // - getTime( ) is called which forces the millis to be set
873         // - Addition uses millis which are correct
874         //
875
876         {
877             Calendar calendar = new GregorianCalendar( 1993, Calendar.JANUARY, 4 ) ;
878             logln( "3A) " + value( calendar ) ) ;
879             calendar.getTime( ) ;
880             calendar.add( Calendar.DATE, 1 ) ;
881             String v = value(calendar);
882             logln( "3B) " + v ) ;
883             logln( "--) 1993/0/5" ) ;
884             if (!v.equals(EXPECTED_0610)) errln("Expected " + EXPECTED_0610 +
885                                                 "; saw " + v);
886         }
887     }
888     static String value( Calendar calendar ) {
889         return( calendar.get( Calendar.YEAR )  + "/" +
890                 calendar.get( Calendar.MONTH ) + "/" +
891                 calendar.get( Calendar.DATE ) ) ;
892     }
893     static String EXPECTED_0610 = "1993/0/5";
894
895     // Test that certain fields on a certain date are as expected.
896     public void TestFields060() {
897         int year = 1997;
898         int month = java.util.Calendar.OCTOBER;  //october
899         int dDate = 22;   //DAYOFWEEK should return 3 for Wednesday
900         GregorianCalendar calendar = null;
901
902         calendar = new GregorianCalendar( year, month, dDate);
903         for (int i=0; i<EXPECTED_FIELDS.length; ) {
904             int field = EXPECTED_FIELDS[i++];
905             int expected = EXPECTED_FIELDS[i++];
906             if (calendar.get(field) != expected) {
907                 errln("Expected field " + field + " to have value " + expected +
908                       "; received " + calendar.get(field) + " instead");
909             }
910         }
911     }
912     static int EXPECTED_FIELDS[] = {
913         Calendar.YEAR, 1997,
914         Calendar.MONTH, Calendar.OCTOBER,
915         Calendar.DAY_OF_MONTH, 22,
916         Calendar.DAY_OF_WEEK, Calendar.WEDNESDAY,
917         Calendar.DAY_OF_WEEK_IN_MONTH, 4,
918         Calendar.DAY_OF_YEAR, 295
919     };
920
921     // Verify that the fields are as expected (mostly zero) at the epoch start.
922     // Note that we adjust for the default timezone to get most things to zero.
923     public void TestEpochStartFields() {
924         TimeZone z = TimeZone.getDefault();
925         Calendar c = Calendar.getInstance();
926         Date d = new Date(-z.getRawOffset());
927         if (z.inDaylightTime(d)) {
928             logln("Warning: Skipping test because " + d +
929                   " is in DST.");
930         }
931         else {
932             c.setTime(d);
933             c.setMinimalDaysInFirstWeek(1);
934             for (int i=0; i<Calendar.ZONE_OFFSET; ++i) {
935                 if (c.get(i) != EPOCH_FIELDS[i])
936                     errln("Expected field " + i + " to have value " + EPOCH_FIELDS[i] +
937                           "; saw " + c.get(i) + " instead");
938             }
939             if (c.get(Calendar.ZONE_OFFSET) != z.getRawOffset())
940                 errln("Expected field ZONE_OFFSET to have value " + z.getRawOffset() +
941                       "; saw " + c.get(Calendar.ZONE_OFFSET) + " instead");
942             if (c.get(Calendar.DST_OFFSET) != 0)
943                 errln("Expected field DST_OFFSET to have value 0" +
944                       "; saw " + c.get(Calendar.DST_OFFSET) + " instead");
945         }
946     }
947     // These are the fields at the epoch start
948     static int EPOCH_FIELDS[] = { 1, 1970, 0, 1, 1, 1, 1, 5, 1, 0, 0, 0, 0, 0, 0, -28800000, 0 };
949
950     // Verify that as you add days to the calendar (e.g., 24 day periods),
951     // the day of the week shifts in the expected pattern.
952     public void TestDOWProgression() {
953         Calendar cal =
954             new GregorianCalendar(1972, Calendar.OCTOBER, 26);
955         marchByDelta(cal, 24); // Last parameter must be != 0 modulo 7
956     }
957
958     // Supply a delta which is not a multiple of 7.
959     void marchByDelta(Calendar cal, int delta) {
960         Calendar cur = (Calendar)cal.clone();
961         int initialDOW = cur.get(Calendar.DAY_OF_WEEK);
962         int DOW, newDOW = initialDOW;
963         do {
964             DOW = newDOW;
965             logln("DOW = " + DOW + "  " + cur.getTime());
966
967             cur.add(Calendar.DAY_OF_WEEK, delta);
968             newDOW = cur.get(Calendar.DAY_OF_WEEK);
969             int expectedDOW = 1 + (DOW + delta - 1) % 7;
970             if (newDOW != expectedDOW) {
971                 errln("Day of week should be " + expectedDOW +
972                       " instead of " + newDOW + " on " + cur.getTime());
973                 return;
974             }
975         }
976         while (newDOW != initialDOW);
977     }
978
979     public void TestActualMinMax() {
980         Calendar cal = new GregorianCalendar(1967, Calendar.MARCH, 10);
981         cal.setFirstDayOfWeek(Calendar.SUNDAY);
982         cal.setMinimalDaysInFirstWeek(3);
983
984         if (cal.getActualMinimum(Calendar.DAY_OF_MONTH) != 1)
985             errln("Actual minimum date for 3/10/1967 should have been 1; got " +
986                   cal.getActualMinimum(Calendar.DAY_OF_MONTH));
987         if (cal.getActualMaximum(Calendar.DAY_OF_MONTH) != 31)
988             errln("Actual maximum date for 3/10/1967 should have been 31; got " +
989                   cal.getActualMaximum(Calendar.DAY_OF_MONTH));
990
991         cal.set(Calendar.MONTH, Calendar.FEBRUARY);
992         if (cal.getActualMaximum(Calendar.DAY_OF_MONTH) != 28)
993             errln("Actual maximum date for 2/10/1967 should have been 28; got " +
994                   cal.getActualMaximum(Calendar.DAY_OF_MONTH));
995         if (cal.getActualMaximum(Calendar.DAY_OF_YEAR) != 365)
996             errln("Number of days in 1967 should have been 365; got " +
997                   cal.getActualMaximum(Calendar.DAY_OF_YEAR));
998
999         cal.set(Calendar.YEAR, 1968);
1000         if (cal.getActualMaximum(Calendar.DAY_OF_MONTH) != 29)
1001             errln("Actual maximum date for 2/10/1968 should have been 29; got " +
1002                   cal.getActualMaximum(Calendar.DAY_OF_MONTH));
1003         if (cal.getActualMaximum(Calendar.DAY_OF_YEAR) != 366)
1004             errln("Number of days in 1968 should have been 366; got " +
1005                   cal.getActualMaximum(Calendar.DAY_OF_YEAR));
1006         // Using week settings of SUNDAY/3 (see above)
1007         if (cal.getActualMaximum(Calendar.WEEK_OF_YEAR) != 52)
1008             errln("Number of weeks in 1968 should have been 52; got " +
1009                   cal.getActualMaximum(Calendar.WEEK_OF_YEAR));
1010
1011         cal.set(Calendar.YEAR, 1976);
1012         cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek()); // Added - Liu 11/6/00
1013         // Using week settings of SUNDAY/3 (see above)
1014         if (cal.getActualMaximum(Calendar.WEEK_OF_YEAR) != 53)
1015             errln("Number of weeks in 1976 should have been 53; got " +
1016                   cal.getActualMaximum(Calendar.WEEK_OF_YEAR));
1017     }
1018
1019     public void TestRoll() {
1020         Calendar cal = new GregorianCalendar(1997, Calendar.JANUARY, 31);
1021
1022         int[] dayValues = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31 };
1023         for (int i = 0; i < dayValues.length; i++) {
1024             Calendar cal2 = (Calendar)cal.clone();
1025             cal2.roll(Calendar.MONTH, i);
1026             if (cal2.get(Calendar.DAY_OF_MONTH) != dayValues[i])
1027                 errln("Rolling the month in 1/31/1997 up by " + i + " should have yielded "
1028                       + ((i + 1) % 12) + "/" + dayValues[i] + "/1997, but actually yielded "
1029                       + ((i + 1) % 12) + "/" + cal2.get(Calendar.DAY_OF_MONTH) + "/1997.");
1030         }
1031
1032         cal.set(1996, Calendar.FEBRUARY, 29);
1033
1034         //int[] monthValues = { 1, 2, 2, 2, 1, 2, 2, 2, 1, 2 };
1035         //int[] dayValues2 = { 29, 1, 1, 1, 29, 1, 1, 1, 29, 1 };
1036
1037         // I've revised the expected values to make more sense -- rolling
1038         // the year should pin the DAY_OF_MONTH. - Liu 11/6/00
1039         int[] monthValues = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
1040         int[] dayValues2 = { 29, 28, 28, 28, 29, 28, 28, 28, 29, 28 };
1041
1042         for (int i = 0; i < dayValues2.length; i++) {
1043             Calendar cal2 = (Calendar)cal.clone();
1044             cal2.roll(Calendar.YEAR, i);
1045             if (cal2.get(Calendar.DAY_OF_MONTH) != dayValues2[i] || cal2.get(Calendar.MONTH)
1046                 != monthValues[i])
1047                 errln("Roll 2/29/1996 by " + i + " year: expected "
1048                       + (monthValues[i] + 1) + "/" + dayValues2[i] + "/"
1049                       + (1996 + i) + ", got "
1050                       + (cal2.get(Calendar.MONTH) + 1) + "/" +
1051                       cal2.get(Calendar.DAY_OF_MONTH) + "/" + cal2.get(Calendar.YEAR));
1052         }
1053
1054         // Test rolling hour of day
1055         cal.set(Calendar.HOUR_OF_DAY, 0);
1056         cal.roll(Calendar.HOUR_OF_DAY, -2);
1057         int f = cal.get(Calendar.HOUR_OF_DAY);
1058         if (f != 22) errln("Rolling HOUR_OF_DAY=0 delta=-2 gave " + f + " Wanted 22");
1059         cal.roll(Calendar.HOUR_OF_DAY, 5);
1060         f = cal.get(Calendar.HOUR_OF_DAY);
1061         if (f != 3) errln("Rolling HOUR_OF_DAY=22 delta=5 gave " + f + " Wanted 3");
1062         cal.roll(Calendar.HOUR_OF_DAY, 21);
1063         f = cal.get(Calendar.HOUR_OF_DAY);
1064         if (f != 0) errln("Rolling HOUR_OF_DAY=3 delta=21 gave " + f + " Wanted 0");
1065
1066         // Test rolling hour
1067         cal.set(Calendar.HOUR_OF_DAY, 0);
1068         cal.roll(Calendar.HOUR, -2);
1069         f = cal.get(Calendar.HOUR);
1070         if (f != 10) errln("Rolling HOUR=0 delta=-2 gave " + f + " Wanted 10");
1071         cal.roll(Calendar.HOUR, 5);
1072         f = cal.get(Calendar.HOUR);
1073         if (f != 3) errln("Rolling HOUR=10 delta=5 gave " + f + " Wanted 3");
1074         cal.roll(Calendar.HOUR, 9);
1075         f = cal.get(Calendar.HOUR);
1076         if (f != 0) errln("Rolling HOUR=3 delta=9 gave " + f + " Wanted 0");
1077     }
1078
1079     public void TestComputeJulianDay4406() {
1080         // jb4406 is probably not a bug, this is to document the behavior
1081         GregorianCalendar cal = new GregorianCalendar();
1082         final int MILLIS_IN_DAY = 1000 * 60 * 60 * 24;
1083         
1084         logln("julian day value jumps at changeover");
1085         for (int day = 12; day < 18; ++day) {
1086             cal.set(1582, 9, day);
1087             logln("[" + day + "] " + (cal.getTimeInMillis()/MILLIS_IN_DAY));
1088         }
1089
1090         logln("\njulian days not accurate before 1 March 0004");
1091         for (int day = 1; day < 3; ++day) {
1092             cal.set(1, 0, day);
1093             logln("[" + day + "] " + (cal.getTimeInMillis()/MILLIS_IN_DAY));
1094         }
1095
1096         DateFormat fmt = cal.getDateTimeFormat(DateFormat.LONG, 0, Locale.getDefault());
1097
1098         logln("\nswitchover in 1582");
1099         cal.set(1582, 9, 4);
1100         logln(fmt.format(cal));
1101         cal.add(Calendar.DATE, 1);
1102         logln(fmt.format(cal));
1103         cal.set(Calendar.JULIAN_DAY, 1721426);
1104         logln(fmt.format(cal));
1105
1106         logln("\nlate switchover - proleptic Julian");
1107         cal.set(1582, 9, 4);
1108         cal.setGregorianChange(new Date(Long.MAX_VALUE));
1109         logln(fmt.format(cal));
1110         cal.add(Calendar.DATE, 1);
1111         logln(fmt.format(cal));
1112         cal.set(Calendar.JULIAN_DAY, 1721426);
1113         logln(fmt.format(cal));
1114
1115         logln("\nearly switchover - proleptic Gregorian");
1116         cal.set(1582, 9, 4);
1117         cal.setGregorianChange(new Date(Long.MIN_VALUE));
1118         logln(fmt.format(cal));
1119         cal.add(Calendar.DATE, 1);
1120         logln(fmt.format(cal));
1121         cal.set(Calendar.JULIAN_DAY, 1721426);
1122         logln(fmt.format(cal));
1123     }
1124 }
1125
1126 //eof