]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_8_1_1/main/tests/core/src/com/ibm/icu/dev/test/calendar/CompatibilityTest.java
Added flags.
[Dictionary.git] / jars / icu4j-4_8_1_1 / main / tests / core / src / com / ibm / icu / dev / test / calendar / CompatibilityTest.java
1 /**
2  *******************************************************************************
3  * Copyright (C) 2000-2009, International Business Machines Corporation and    *
4  * others. All Rights Reserved.                                                *
5  *******************************************************************************
6  */
7 package com.ibm.icu.dev.test.calendar;
8
9 import java.io.ByteArrayInputStream;
10 import java.io.ByteArrayOutputStream;
11 import java.io.IOException;
12 import java.io.ObjectInputStream;
13 import java.io.ObjectOutput;
14 import java.io.ObjectOutputStream;
15 import java.util.Date;
16 import java.util.Locale;
17
18 import com.ibm.icu.text.DateFormat;
19 import com.ibm.icu.util.Calendar;
20 import com.ibm.icu.util.GregorianCalendar;
21 import com.ibm.icu.util.SimpleTimeZone;
22 import com.ibm.icu.util.TimeZone;
23
24 public class CompatibilityTest extends com.ibm.icu.dev.test.TestFmwk {
25
26     public static void main(String argv[]) throws Exception {
27         new CompatibilityTest().run(argv);
28     }
29
30     static final String[] FIELD_NAME = {
31         "ERA", "YEAR", "MONTH", "WEEK_OF_YEAR", "WEEK_OF_MONTH",
32         "DAY_OF_MONTH", "DAY_OF_YEAR", "DAY_OF_WEEK",
33         "DAY_OF_WEEK_IN_MONTH", "AM_PM", "HOUR", "HOUR_OF_DAY",
34         "MINUTE", "SECOND", "MILLISECOND", "ZONE_OFFSET",
35         "DST_OFFSET", "YEAR_WOY", "DOW_LOCAL", "EXTENDED_YEAR",
36         "JULIAN_DAY", "MILLISECONDS_IN_DAY",
37     };
38
39     /**
40      * Test the behavior of the GregorianCalendar around the changeover.
41      */
42     public void TestGregorianChangeover() {
43     
44         java.util.TimeZone jdkGMT = java.util.TimeZone.getTimeZone("GMT");
45         java.util.Calendar jdkCal = java.util.Calendar.getInstance(jdkGMT);
46         jdkCal.clear();
47         jdkCal.set(1582, Calendar.OCTOBER, 15);
48         
49 //      if(jdkCal instanceof java.util.GregorianCalendar) {
50 //          logln("jdk IS grego");
51 //          java.util.GregorianCalendar jdkgc = (java.util.GregorianCalendar)
52 //          jdkCal;
53 //          logln("jdk change at: " + jdkgc.getGregorianChange() + "(" + jdkgc.getGregorianChange().getTime() +")" );
54 //      } else {
55 //          logln("jdk NOT grego");
56 //      }
57
58         long a = jdkCal.getTime().getTime();
59         Date c = jdkCal.getTime();
60         c.toString();
61         long b = c.getTime();
62         if(a!=b) {
63             logln(" " + a + " != " + b);
64             logln("JDK has Gregorian cutover anomaly (1.5?) - skipping this test.");
65             return;
66         }
67
68         Date co = jdkCal.getTime();
69         logln("Change over (Oct 15 1582) = " + co + " (" + co.getTime() + ")");
70         final int ONE_DAY = 24*60*60*1000;
71         TimeZone gmt = TimeZone.getTimeZone("GMT");
72         GregorianCalendar cal = new GregorianCalendar(gmt);
73         /*
74           Changeover -7 days: 1582/9/28 dow=6
75           Changeover -6 days: 1582/9/29 dow=7
76           Changeover -5 days: 1582/9/30 dow=1
77           Changeover -4 days: 1582/10/1 dow=2
78           Changeover -3 days: 1582/10/2 dow=3
79           Changeover -2 days: 1582/10/3 dow=4
80           Changeover -1 days: 1582/10/4 dow=5
81           Changeover +0 days: 1582/10/15 dow=6
82           Changeover +1 days: 1582/10/16 dow=7
83           Changeover +2 days: 1582/10/17 dow=1
84           Changeover +3 days: 1582/10/18 dow=2
85           Changeover +4 days: 1582/10/19 dow=3
86           Changeover +5 days: 1582/10/20 dow=4
87           Changeover +6 days: 1582/10/21 dow=5
88           Changeover +7 days: 1582/10/22 dow=6
89           */
90         int MON[] = {  9,  9,  9,10,10,10,10, 10, 10, 10, 10, 10, 10, 10, 10 };
91         int DOM[] = { 28, 29, 30, 1, 2, 3, 4, 15, 16, 17, 18, 19, 20, 21, 22 };
92         int DOW[] = {  6,  7,  1, 2, 3, 4, 5,  6,  7,  1,  2,  3,  4,  5,  6 };
93         //                                     ^ <-Changeover Fri Oct 15 1582
94         int j=0;
95         for (int i=-7; i<=7; ++i, ++j) {
96             Date d = new Date(co.getTime() + i*ONE_DAY);
97             cal.setTime(d);
98             int y = cal.get(Calendar.YEAR), mon = cal.get(Calendar.MONTH)+1-Calendar.JANUARY,
99                 dom = cal.get(Calendar.DATE), dow = cal.get(Calendar.DAY_OF_WEEK);
100             logln("Changeover " + (i>=0?"+":"") +
101                   i + " days: " + y + "/" + mon + "/" + dom + " dow=" + dow);
102             if (y != 1582 || mon != MON[j] || dom != DOM[j] || dow != DOW[j])
103                 errln(" Fail: Above line is wrong");
104         }
105     }
106
107     /**
108      * Test the mapping between millis and fields.  For the purposes
109      * of this test, we don't care about timezones and week data
110      * (first day of week, minimal days in first week).
111      */
112     public void TestMapping() {
113         if (false) {
114             Date PURE_GREGORIAN = new Date(Long.MIN_VALUE);
115             Date PURE_JULIAN = new Date(Long.MAX_VALUE);
116             GregorianCalendar cal =
117                 new GregorianCalendar(TimeZone.getTimeZone("UTC"));
118             final int EPOCH_JULIAN = 2440588;
119             final long ONE_DAY = 24*60*60*1000L;
120             com.ibm.icu.text.SimpleDateFormat fmt =
121                 new com.ibm.icu.text.SimpleDateFormat("EEE MMM dd yyyy G");
122                 /*HH:mm:ss.SSS z*/
123
124             for (int type=0; type<2; ++type) {
125                 System.out.println(type==0 ? "Gregorian" : "Julian");
126                 cal.setGregorianChange(type==0 ? PURE_GREGORIAN : PURE_JULIAN);
127                 fmt.setCalendar(cal);
128                 int[] J = {
129                     0x7FFFFFFF,
130                     0x7FFFFFF0,
131                     0x7F000000,
132                     0x78000000,
133                     0x70000000,
134                     0x60000000,
135                     0x50000000,
136                     0x40000000,
137                     0x30000000,
138                     0x20000000,
139                     0x10000000,
140                 };
141                 for (int i=0; i<J.length; ++i) {
142                     String[] lim = new String[2];
143                     long[] ms = new long[2];
144                     int jd = J[i];
145                     for (int sign=0; sign<2; ++sign) {
146                         int julian = jd;
147                         if (sign==0) julian = -julian;
148                         long millis = ((long)julian - EPOCH_JULIAN) * ONE_DAY;
149                         ms[sign] = millis;
150                         cal.setTime(new Date(millis));
151                         lim[sign] = fmt.format(cal.getTime());
152                     }
153                     System.out.println("JD +/-" +
154                                        Long.toString(jd, 16) +
155                                        ": " + ms[0] + ".." + ms[1] +
156                                        ": " + lim[0] + ".." + lim[1]);
157                 }
158             }
159         }
160
161         TimeZone saveZone = TimeZone.getDefault();
162         try {
163             TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
164             //NEWCAL
165             Date PURE_GREGORIAN = new Date(Long.MIN_VALUE);
166             Date PURE_JULIAN = new Date(Long.MAX_VALUE);
167             GregorianCalendar cal = new GregorianCalendar();
168             final int EPOCH_JULIAN = 2440588;
169             final long ONE_DAY = 24*60*60*1000L;
170             int[] DATA = {
171                 // Julian#   Year  Month               DOM   JULIAN:Year, Month,       DOM
172                 2440588,     1970, Calendar.JANUARY,   1,    1969, Calendar.DECEMBER,  19, 
173                 2415080,     1900, Calendar.MARCH,     1,    1900, Calendar.FEBRUARY,  17,
174                 2451604,     2000, Calendar.FEBRUARY,  29,   2000, Calendar.FEBRUARY,  16,
175                 2452269,     2001, Calendar.DECEMBER,  25,   2001, Calendar.DECEMBER,  12,
176                 2416526,     1904, Calendar.FEBRUARY,  15,   1904, Calendar.FEBRUARY,  2,
177                 2416656,     1904, Calendar.JUNE,      24,   1904, Calendar.JUNE,      11,
178                 1721426,        1, Calendar.JANUARY,   1,       1, Calendar.JANUARY,   3,
179                 2000000,      763, Calendar.SEPTEMBER, 18,    763, Calendar.SEPTEMBER, 14,
180                 4000000,     6239, Calendar.JULY,      12,   6239, Calendar.MAY,       28,
181                 8000000,    17191, Calendar.FEBRUARY,  26,  17190, Calendar.OCTOBER,   22,
182                 10000000,   22666, Calendar.DECEMBER,  20,  22666, Calendar.JULY,      5,
183             };
184             for (int i=0; i<DATA.length; i+=7) {
185                 int julian = DATA[i];
186                 int year = DATA[i+1];
187                 int month = DATA[i+2];
188                 int dom = DATA[i+3];
189                 int year2, month2, dom2;
190                 long millis = (julian - EPOCH_JULIAN) * ONE_DAY;
191                 String s;
192
193                 // Test Gregorian computation
194                 cal.setGregorianChange(PURE_GREGORIAN);
195                 cal.clear();
196                 cal.set(year, month, dom);
197                 long calMillis = cal.getTime().getTime();
198                 long delta = calMillis - millis;
199                 cal.setTime(new Date(millis));
200                 year2 = cal.get(Calendar.YEAR);
201                 month2 = cal.get(Calendar.MONTH);
202                 dom2 = cal.get(Calendar.DAY_OF_MONTH);
203                 s = "G " + year + "-" + (month+1-Calendar.JANUARY) + "-" + dom +
204                     " => " + calMillis +
205                     " (" + ((float)delta/ONE_DAY) + " day delta) => " +
206                     year2 + "-" + (month2+1-Calendar.JANUARY) + "-" + dom2;
207                 if (delta != 0 || year != year2 || month != month2 ||
208                     dom != dom2) errln(s + " FAIL");
209                 else logln(s);
210                 
211                 // Test Julian computation
212                 year = DATA[i+4];
213                 month = DATA[i+5];
214                 dom = DATA[i+6];
215                 cal.setGregorianChange(PURE_JULIAN);
216                 cal.clear();
217                 cal.set(year, month, dom);
218                 calMillis = cal.getTime().getTime();
219                 delta = calMillis - millis;
220                 cal.setTime(new Date(millis));
221                 year2 = cal.get(Calendar.YEAR);
222                 month2 = cal.get(Calendar.MONTH);
223                 dom2 = cal.get(Calendar.DAY_OF_MONTH);
224                 s = "J " + year + "-" + (month+1-Calendar.JANUARY) + "-" + dom +
225                     " => " + calMillis +
226                     " (" + ((float)delta/ONE_DAY) + " day delta) => " +
227                     year2 + "-" + (month2+1-Calendar.JANUARY) + "-" + dom2;
228                 if (delta != 0 || year != year2 || month != month2 ||
229                     dom != dom2) errln(s + " FAIL");
230                 else logln(s);
231             }
232
233             java.util.Calendar tempcal = java.util.Calendar.getInstance();
234             tempcal.clear();
235             tempcal.set(1582, Calendar.OCTOBER, 15);
236             cal.setGregorianChange(tempcal.getTime());
237             auxMapping(cal, 1582, Calendar.OCTOBER, 4);
238             auxMapping(cal, 1582, Calendar.OCTOBER, 15);
239             auxMapping(cal, 1582, Calendar.OCTOBER, 16);
240             for (int y=800; y<3000; y+=1+(int)(100*Math.random())) {
241                 for (int m=Calendar.JANUARY; m<=Calendar.DECEMBER; ++m) {
242                     auxMapping(cal, y, m, 15);
243                 }
244             }
245         }
246         finally {
247             TimeZone.setDefault(saveZone);
248         }
249     }
250     private void auxMapping(Calendar cal, int y, int m, int d) {
251         cal.clear();
252         cal.set(y, m, d);
253         long millis = cal.getTime().getTime();
254         cal.setTime(new Date(millis));
255         int year2 = cal.get(Calendar.YEAR);
256         int month2 = cal.get(Calendar.MONTH);
257         int dom2 = cal.get(Calendar.DAY_OF_MONTH);
258         if (y != year2 || m != month2 || dom2 != d)
259             errln("Round-trip failure: " + y + "-" + (m+1) + "-"+d+" =>ms=> " +
260                   year2 + "-" + (month2+1) + "-" + dom2);
261     }
262
263     public void TestGenericAPI() {
264         // not used String str;
265
266         java.util.Calendar tempcal = java.util.Calendar.getInstance();
267         tempcal.clear();
268         tempcal.set(1990, Calendar.APRIL, 15);
269         Date when = tempcal.getTime();
270
271         String tzid = "TestZone";
272         int tzoffset = 123400;
273
274         SimpleTimeZone zone = new SimpleTimeZone(tzoffset, tzid);
275         Calendar cal = (Calendar)Calendar.getInstance((SimpleTimeZone)zone.clone());
276
277         if (!zone.equals(cal.getTimeZone())) errln("FAIL: Calendar.getTimeZone failed");
278
279         Calendar cal2 = Calendar.getInstance(cal.getTimeZone());
280
281         cal.setTime(when);
282         cal2.setTime(when);
283
284         if (!(cal.equals(cal2))) errln("FAIL: Calendar.operator== failed");
285         // if ((*cal != *cal2))  errln("FAIL: Calendar.operator!= failed");
286         if (!cal.equals(cal2) ||
287             cal.before(cal2) ||
288             cal.after(cal2)) errln("FAIL: equals/before/after failed");
289
290         cal2.setTime(new Date(when.getTime() + 1000));
291         if (cal.equals(cal2) ||
292             cal2.before(cal) ||
293             cal.after(cal2)) errln("FAIL: equals/before/after failed");
294
295         cal.roll(Calendar.SECOND, true);
296         if (!cal.equals(cal2) ||
297             cal.before(cal2) ||
298             cal.after(cal2)) errln("FAIL: equals/before/after failed");
299
300         // Roll back to January
301         cal.roll(Calendar.MONTH, (int)(1 + Calendar.DECEMBER - cal.get(Calendar.MONTH)));
302         if (cal.equals(cal2) ||
303             cal2.before(cal) ||
304             cal.after(cal2)) errln("FAIL: equals/before/after failed");
305
306         // C++ only
307         /* TimeZone z = cal.orphanTimeZone();
308            if (z.getID(str) != tzid ||
309            z.getRawOffset() != tzoffset)
310            errln("FAIL: orphanTimeZone failed");
311            */
312
313         for (int i=0; i<2; ++i) {
314             boolean lenient = ( i > 0 );
315             cal.setLenient(lenient);
316             if (lenient != cal.isLenient()) errln("FAIL: setLenient/isLenient failed");
317             // Later: Check for lenient behavior
318         }
319
320         int i;
321         for (i=Calendar.SUNDAY; i<=Calendar.SATURDAY; ++i) {
322             cal.setFirstDayOfWeek(i);
323             if (cal.getFirstDayOfWeek() != i) errln("FAIL: set/getFirstDayOfWeek failed");
324         }
325
326         for (i=1; i<=7; ++i) {
327             cal.setMinimalDaysInFirstWeek(i);
328             if (cal.getMinimalDaysInFirstWeek() != i) errln("FAIL: set/getFirstDayOfWeek failed");
329         }
330
331         for (i=0; i<cal.getFieldCount(); ++i) {
332             if (cal.getMinimum(i) > cal.getGreatestMinimum(i))
333                 errln("FAIL: getMinimum larger than getGreatestMinimum for field " + i);
334             if (cal.getLeastMaximum(i) > cal.getMaximum(i))
335                 errln("FAIL: getLeastMaximum larger than getMaximum for field " + i);
336             if (cal.getMinimum(i) >= cal.getMaximum(i))
337                 errln("FAIL: getMinimum not less than getMaximum for field " + i);
338         }
339
340         cal.setTimeZone(TimeZone.getDefault());
341         cal.clear();
342         cal.set(1984, 5, 24);
343         tempcal.clear();
344         tempcal.set(1984, 5, 24);
345         if (cal.getTime().getTime() != tempcal.getTime().getTime()) {
346             errln("FAIL: Calendar.set(3 args) failed");
347             logln(" Got: " + cal.getTime() + "  Expected: " + tempcal.getTime());
348         }
349
350         cal.clear();
351         cal.set(1985, 2, 2, 11, 49);
352         tempcal.clear();
353         tempcal.set(1985, 2, 2, 11, 49);
354         if (cal.getTime().getTime() != tempcal.getTime().getTime()) {
355             errln("FAIL: Calendar.set(5 args) failed");
356             logln(" Got: " + cal.getTime() + "  Expected: " + tempcal.getTime());
357         }
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