OSDN Git Service

c54691c36a67bd28711bc7dbb69620374abbc7ac
[pf3gnuchains/gcc-fork.git] / libjava / java / util / GregorianCalendar.java
1 /* java.util.GregorianCalendar
2    Copyright (C) 1998, 1999, 2001, 2002, 2003, 2004
3    Free Software Foundation, Inc.
4
5 This file is part of GNU Classpath.
6
7 GNU Classpath is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GNU Classpath is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GNU Classpath; see the file COPYING.  If not, write to the
19 Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 02111-1307 USA.
21
22 Linking this library statically or dynamically with other modules is
23 making a combined work based on this library.  Thus, the terms and
24 conditions of the GNU General Public License cover the whole
25 combination.
26
27 As a special exception, the copyright holders of this library give you
28 permission to link this library with independent modules to produce an
29 executable, regardless of the license terms of these independent
30 modules, and to copy and distribute the resulting executable under
31 terms of your choice, provided that you also meet, for each linked
32 independent module, the terms and conditions of the license of that
33 module.  An independent module is a module which is not derived from
34 or based on this library.  If you modify this library, you may extend
35 this exception to your version of the library, but you are not
36 obligated to do so.  If you do not wish to do so, delete this
37 exception statement from your version. */
38
39
40 package java.util;
41
42 import java.io.IOException;
43 import java.io.ObjectInputStream;
44
45 /**
46  * <p>
47  * This class represents the Gregorian calendar, that is used in most
48  * countries all over the world.  It does also handle the Julian calendar
49  * for dates smaller than the date of the change to the Gregorian calendar.
50  * The Gregorian calendar differs from the Julian calendar by a different
51  * leap year rule (no leap year every 100 years, except if year is divisible
52  * by 400).  
53  * </p>
54  * <p>
55  * This change date is different from country to country, and can be changed with
56  * <code>setGregorianChange</code>.  The first countries to adopt the Gregorian
57  * calendar did so on the 15th of October, 1582.  This date followed October
58  * the 4th, 1582 in the Julian calendar system.  The non-existant days that were
59  * omitted when the change took place are interpreted as Gregorian dates.
60  * </p>
61  * <p>
62  * Prior to the changeover date, New Year's Day occurred on the 25th of March.
63  * However, this class always takes New Year's Day as being the 1st of January.
64  * Client code should manually adapt the year value, if required, for dates
65  * between January the 1st and March the 24th in years prior to the changeover.
66  * </p>
67  * <p>
68  * Any date infinitely forwards or backwards in time can be represented by
69  * this class.  A <em>proleptic</em> calendar system is used, which allows
70  * future dates to be created via the existing rules.  This allows meaningful
71  * and consistent dates to be produced for all years.  However, dates are only
72  * historically accurate following March the 1st, 4AD when the Julian calendar
73  * system was adopted.  Prior to this, leap year rules were applied erraticly.
74  * </p>
75  * <p>
76  * There are two eras available for the Gregorian calendar, namely BC and AD.
77  * </p>
78  * <p>
79  * Weeks are defined as a period of seven days, beginning on the first day
80  * of the week, as returned by <code>getFirstDayOfWeek()</code>, and ending
81  * on the day prior to this.
82  * </p>
83  * <p>
84  * The weeks of the year are numbered from 1 to a possible 53.  The first week
85  * of the year is defined as the first week that contains at least the minimum
86  * number of days of the first week in the new year (retrieved via
87  * <code>getMinimalDaysInFirstWeek()</code>).  All weeks after this are numbered
88  * from 2 onwards.
89  * </p>
90  * <p>
91  * For example, take the year 2004.  It began on a Thursday.  The first week
92  * of 2004 depends both on where a week begins and how long it must minimally
93  * last.  Let's say that the week begins on a Monday and must have a minimum
94  * of 5 days.  In this case, the first week begins on Monday, the 5th of January.
95  * The first 4 days (Thursday to Sunday) are not eligible, as they are too few
96  * to make up the minimum number of days of the first week which must be in
97  * the new year.  If the minimum was lowered to 4 days, then the first week
98  * would instead begin on Monday, the 29th of December, 2003.  This first week
99  * has 4 of its days in the new year, and is now eligible.
100  * </p>
101  * <p>
102  * The weeks of the month are numbered from 0 to a possible 6.  The first week
103  * of the month (numbered 1) is a set of days, prior to the first day of the week,
104  * which number at least the minimum number of days in a week.  Unlike the first
105  * week of the year, the first week of the month only uses days from that particular
106  * month.  As a consequence, it may have a variable number of days (from the minimum
107  * number required up to a full week of 7) and it need not start on the first day of
108  * the week.  It must, however, be following by the first day of the week, as this
109  * marks the beginning of week 2.  Any days of the month which occur prior to the
110  * first week (because the first day of the week occurs before the minimum number
111  * of days is met) are seen as week 0.
112  * </p>
113  * <p>
114  * Again, we will take the example of the year 2004 to demonstrate this.  September
115  * 2004 begins on a Wednesday.  Taking our first day of the week as Monday, and the
116  * minimum length of the first week as 6, we find that week 1 runs from Monday,
117  * the 6th of September to Sunday the 12th.  Prior to the 6th, there are only
118  * 5 days (Wednesday through to Sunday).  This is too small a number to meet the
119  * minimum, so these are classed as being days in week 0.  Week 2 begins on the
120  * 13th, and so on.  This changes if we reduce the minimum to 5.  In this case,
121  * week 1 is a truncated week from Wednesday the 1st to Sunday the 5th, and week
122  * 0 doesn't exist.  The first seven day week is week 2, starting on the 6th.
123  * </p>
124  * <p>
125  * On using the <code>clear()</code> method, the Gregorian calendar returns
126  * to its default value of the 1st of January, 1970 AD 00:00:00 (the epoch).
127  * The day of the week is set to the correct day for that particular time.
128  * The day is also the first of the month, and the date is in week 0.
129  * </p>
130  *
131  * @see Calendar
132  * @see TimeZone
133  * @see Calendar#getFirstDayOfWeek()
134  * @see Calendar#getMinimalDaysInFirstWeek()
135  */
136 public class GregorianCalendar extends Calendar
137 {
138   /**
139    * Constant representing the era BC (Before Christ).
140    */
141   public static final int BC = 0;
142   
143   /**
144    * Constant representing the era AD (Anno Domini).
145    */
146   public static final int AD = 1;
147
148   /**
149    * The point at which the Gregorian calendar rules were used.
150    * This is locale dependent; the default for most catholic
151    * countries is midnight (UTC) on October 5, 1582 (Julian),
152    * or October 15, 1582 (Gregorian).
153    *
154    * @serial the changeover point from the Julian calendar
155    *         system to the Gregorian.
156    */
157   private long gregorianCutover;
158
159   /**
160    * For compatability with Sun's JDK.
161    */
162   static final long serialVersionUID = -8125100834729963327L;
163
164   /**
165    * The name of the resource bundle. Used only by getBundle()
166    */
167   private static final String bundleName = "gnu.java.locale.Calendar";
168
169   /**
170    * Retrieves the resource bundle.  The resources should be loaded
171    * via this method only. Iff an application uses this method, the
172    * resourcebundle is required.
173    *
174    * @param locale the locale in use for this calendar.
175    * @return A resource bundle for the calendar for the specified locale.
176    */
177   private static ResourceBundle getBundle(Locale locale) 
178   {
179     return ResourceBundle.getBundle(bundleName, locale,
180       ClassLoader.getSystemClassLoader());
181   }
182
183   /**
184    * Constructs a new GregorianCalender representing the current
185    * time, using the default time zone and the default locale.  
186    */
187   public GregorianCalendar()
188   {
189     this(TimeZone.getDefault(), Locale.getDefault());
190   }
191   
192   /**
193    * Constructs a new GregorianCalender representing the current
194    * time, using the specified time zone and the default locale. 
195    * 
196    * @param zone a time zone.
197    */
198   public GregorianCalendar(TimeZone zone)
199   {
200     this(zone, Locale.getDefault());
201   }
202   
203   /**
204    * Constructs a new GregorianCalender representing the current
205    * time, using the default time zone and the specified locale.
206    *  
207    * @param locale a locale.
208    */
209   public GregorianCalendar(Locale locale)
210   {
211     this(TimeZone.getDefault(), locale);
212   }
213
214   /**
215    * Constructs a new GregorianCalender representing the current
216    * time with the given time zone and the given locale.
217    *
218    * @param zone a time zone.  
219    * @param locale a locale.  
220    */
221   public GregorianCalendar(TimeZone zone, Locale locale)
222   {
223     super(zone, locale);
224     ResourceBundle rb = getBundle(locale);
225     gregorianCutover = ((Date) rb.getObject("gregorianCutOver")).getTime();
226     setTimeInMillis(System.currentTimeMillis());
227   }
228
229   /**
230    * Constructs a new GregorianCalendar representing midnight on the
231    * given date with the default time zone and locale.
232    * @param year corresponds to the YEAR time field.
233    * @param month corresponds to the MONTH time field.
234    * @param day corresponds to the DAY time field.
235    */
236   public GregorianCalendar(int year, int month, int day)
237   {
238     super();
239     set(year, month, day);
240   }
241
242   /**
243    * Constructs a new GregorianCalendar representing midnight on the
244    * given date with the default time zone and locale.
245    *
246    * @param year corresponds to the YEAR time field.
247    * @param month corresponds to the MONTH time field.
248    * @param day corresponds to the DAY time field.
249    * @param hour corresponds to the HOUR_OF_DAY time field.
250    * @param minute corresponds to the MINUTE time field.
251    */
252   public GregorianCalendar(int year, int month, int day, int hour, int minute)
253   {
254     super();
255     set(year, month, day, hour, minute);
256   }
257
258   /**
259    * Constructs a new GregorianCalendar representing midnight on the
260    * given date with the default time zone and locale.
261    *
262    *
263    * @param year corresponds to the YEAR time field.
264    * @param month corresponds to the MONTH time field.
265    * @param day corresponds to the DAY time field.
266    * @param hour corresponds to the HOUR_OF_DAY time field.
267    * @param minute corresponds to the MINUTE time field.
268    * @param second corresponds to the SECOND time field.
269    */
270   public GregorianCalendar(int year, int month, int day,
271                            int hour, int minute, int second)
272   {
273     super();
274     set(year, month, day, hour, minute, second);
275   }
276
277   /**
278    * Sets the date of the switch from Julian dates to Gregorian dates.
279    * You can use <code>new Date(Long.MAX_VALUE)</code> to use a pure
280    * Julian calendar, or <code>Long.MIN_VALUE</code> for a pure Gregorian
281    * calendar.
282    *
283    * @param date the date of the change.
284    */
285   public void setGregorianChange(Date date)
286   {
287     gregorianCutover = date.getTime();
288   }
289
290   /**
291    * Gets the date of the switch from Julian dates to Gregorian dates.
292    *
293    * @return the date of the change.
294    */
295   public final Date getGregorianChange()
296   {
297     return new Date(gregorianCutover);
298   }
299
300   /**
301    * <p>
302    * Determines if the given year is a leap year.  The result is
303    * undefined if the Gregorian change took place in 1800, so that
304    * the end of February is skipped, and that year is specified.
305    * (well...).
306    * </p>
307    * <p>
308    * To specify a year in the BC era, use a negative value calculated
309    * as 1 - y, where y is the required year in BC.  So, 1 BC is 0,
310    * 2 BC is -1, 3 BC is -2, etc.
311    * </p>
312    *
313    * @param year a year (use a negative value for BC).
314    * @return true, if the given year is a leap year, false otherwise.  
315    */
316   public boolean isLeapYear(int year)
317   {
318     if ((year & 3) != 0)
319       // Only years divisible by 4 can be leap years
320       return false;
321
322     // compute the linear day of the 29. February of that year.
323     // The 13 is the number of days, that were omitted in the Gregorian
324     // Calender until the epoch.
325     int julianDay = (((year-1) * (365*4+1)) >> 2) + (31+29 - 
326         (((1970-1) * (365*4+1)) / 4 + 1 - 13));
327     
328     // If that day is smaller than the gregorianChange the julian
329     // rule applies:  This is a leap year since it is divisible by 4.
330     if (julianDay * (24 * 60 * 60 * 1000L) < gregorianCutover)
331       return true;
332
333     return ((year % 100) != 0 || (year % 400) == 0);
334   }
335
336   /**
337    * Get the linear time in milliseconds since the epoch.  If you
338    * specify a nonpositive year it is interpreted as BC as
339    * following: 0 is 1 BC, -1 is 2 BC and so on.  The date is
340    * interpreted as gregorian if the change occurred before that date.
341    *
342    * @param year the year of the date.
343    * @param dayOfYear the day of year of the date; 1 based.
344    * @param millis the millisecond in that day.
345    * @return the days since the epoch, may be negative.  
346    */
347   private long getLinearTime(int year, int dayOfYear, int millis)
348   {
349     // The 13 is the number of days, that were omitted in the Gregorian
350     // Calendar until the epoch.
351     // We shift right by 2 instead of dividing by 4, to get correct
352     // results for negative years (and this is even more efficient).
353     int julianDay = ((year * (365 * 4 + 1)) >> 2) + dayOfYear -
354       ((1970 * (365 * 4 + 1)) / 4 + 1 - 13);
355     long time = julianDay * (24 * 60 * 60 * 1000L) + millis;
356
357     if (time >= gregorianCutover)
358       {
359         // subtract the days that are missing in gregorian calendar
360         // with respect to julian calendar.
361         //
362         // Okay, here we rely on the fact that the gregorian
363         // calendar was introduced in the AD era.  This doesn't work
364         // with negative years.
365         //
366         // The additional leap year factor accounts for the fact that
367         // a leap day is not seen on Jan 1 of the leap year.
368         // And on and after the leap day, the leap day has already been
369         // included in dayOfYear. 
370         int gregOffset = (year / 400) - (year / 100) + 2;
371         if (isLeapYear (year, true))
372           --gregOffset;
373         time += gregOffset * (24 * 60 * 60 * 1000L);
374       }
375     return time;
376   }
377
378   /**
379    * Retrieves the day of the week corresponding to the specified
380    * day of the specified year.
381    *
382    * @param year the year in which the dayOfYear occurs.
383    * @param dayOfYear the day of the year (an integer between 0 and
384    *        and 366)
385    */
386   private int getWeekDay(int year, int dayOfYear)
387   {
388     int day =
389       (int) (getLinearTime(year, dayOfYear, 0) / (24 * 60 * 60 * 1000L));
390
391     // The epoch was a thursday.
392     int weekday = (day + THURSDAY) % 7;
393     if (weekday <= 0)
394       weekday += 7;
395     return weekday;
396   }
397
398   /**
399    * <p>
400    * Calculate the dayOfYear from the fields array.  
401    * The relativeDays is used, to account for weeks that begin before
402    * the Gregorian change and end after it.
403    * </p>
404    * <p>
405    * We return two values.  The first is used to determine, if we
406    * should use the Gregorian calendar or the Julian calendar, in order
407    * to handle the change year. The second is a relative day after the given
408    * day.  This is necessary for week calculation in the year in
409    * which the Gregorian change occurs. 
410    * </p>
411    * 
412    * @param year the year, negative for BC.
413    * @return an array of two integer values, the first containing a reference
414    * day in the current year, the second a relative count since this reference
415    * day.  
416    */
417   private int[] getDayOfYear(int year)
418   {
419     if (isSet[MONTH])
420       {
421         int dayOfYear;
422         if (fields[MONTH] > FEBRUARY)
423           {
424
425             // The months after February are regular:
426             // 9 is an offset found by try and error.
427             dayOfYear = (fields[MONTH] * (31 + 30 + 31 + 30 + 31) - 9) / 5;
428             if (isLeapYear(year))
429               dayOfYear++;
430           }
431         else
432             dayOfYear = 31 * fields[MONTH];
433
434         if (isSet[DAY_OF_MONTH])
435           {
436             return new int[]
437             {
438             dayOfYear + fields[DAY_OF_MONTH], 0};
439           }
440         if (isSet[WEEK_OF_MONTH] && isSet[DAY_OF_WEEK])
441           {
442             // the weekday of the first day in that month is:
443             int weekday = getWeekDay(year, ++dayOfYear);
444
445             return new int[]
446             {
447               dayOfYear,
448                 // the day of week in the first week
449                 // (weeks starting on sunday) is:
450               fields[DAY_OF_WEEK] - weekday +
451                 // Now jump to the right week and correct the possible
452                 // error made by assuming sunday is the first week day.
453               7 * (fields[WEEK_OF_MONTH]
454                    + (fields[DAY_OF_WEEK] < getFirstDayOfWeek()? 0 : -1)
455                    + (weekday < getFirstDayOfWeek()? -1 : 0))};
456           }
457         if (isSet[DAY_OF_WEEK] && isSet[DAY_OF_WEEK_IN_MONTH])
458           {
459             // the weekday of the first day in that month is:
460             int weekday = getWeekDay(year, ++dayOfYear);
461             return new int[] { 
462                   dayOfYear,
463                   fields[DAY_OF_WEEK] - weekday +
464                   7 * (fields[DAY_OF_WEEK_IN_MONTH]
465                        + (fields[DAY_OF_WEEK] < weekday ? 0 : -1))};
466           }
467       }
468
469     // MONTH + something did not succeed.
470     if (isSet[DAY_OF_YEAR])
471       {
472         return new int[] {0, fields[DAY_OF_YEAR]};
473       }
474       
475     if (isSet[DAY_OF_WEEK] && isSet[WEEK_OF_YEAR])
476       {
477         int dayOfYear = getMinimalDaysInFirstWeek();
478         // the weekday of the day, that begins the first week 
479         // in that year is:
480         int weekday = getWeekDay(year, dayOfYear);
481
482         return new int[] { 
483             dayOfYear,
484               // the day of week in the first week
485               // (weeks starting on sunday) is:
486             fields[DAY_OF_WEEK] - weekday
487               // Now jump to the right week and correct the possible
488               // error made by assuming sunday is the first week day.
489             + 7 * (fields[WEEK_OF_YEAR]
490                    + (fields[DAY_OF_WEEK] < getFirstDayOfWeek()? 0 : -1)
491                    + (weekday < getFirstDayOfWeek()? -1 : 0))};
492       }
493
494     // As last resort return Jan, 1st.
495     return new int[] {1, 0};
496   }
497
498   /**
499    * Converts the time field values (<code>fields</code>) to
500    * milliseconds since the epoch UTC (<code>time</code>). 
501    *
502    * @throws IllegalArgumentException if any calendar fields
503    *         are invalid.
504    */
505   protected synchronized void computeTime()
506   {
507     int era = isSet[ERA] ? fields[ERA] : AD;
508     int year = isSet[YEAR] ? fields[YEAR] : 1970;
509     if (era == BC)
510       year = 1 - year;
511
512     int[] daysOfYear = getDayOfYear(year);
513
514     int hour = 0;
515     if (isSet[HOUR_OF_DAY])
516       hour = fields[HOUR_OF_DAY];
517     else if (isSet[HOUR])
518       {
519         hour = fields[HOUR];
520         if (isSet[AM_PM] && fields[AM_PM] == PM)
521           if (hour != 12) /* not Noon */
522             hour += 12;
523         /* Fix the problem of the status of 12:00 AM (midnight). */
524         if (isSet[AM_PM] && fields[AM_PM] == AM && hour == 12)
525           hour = 0;
526       }
527
528     int minute = isSet[MINUTE] ? fields[MINUTE] : 0;
529     int second = isSet[SECOND] ? fields[SECOND] : 0;
530     int millis = isSet[MILLISECOND] ? fields[MILLISECOND] : 0;
531     int millisInDay;
532
533     if (isLenient())
534       {
535         // prevent overflow
536         long allMillis = (((hour * 60L) + minute) * 60L + second) * 1000L
537           + millis;
538         daysOfYear[1] += allMillis / (24 * 60 * 60 * 1000L);
539         millisInDay = (int) (allMillis % (24 * 60 * 60 * 1000L));
540       }
541     else
542       {
543         if (hour < 0 || hour >= 24 || minute < 0 || minute > 59
544             || second < 0 || second > 59 || millis < 0 || millis >= 1000)
545           throw new IllegalArgumentException();
546         millisInDay = (((hour * 60) + minute) * 60 + second) * 1000 + millis;
547       }
548     time = getLinearTime(year, daysOfYear[0], millisInDay);
549
550     // Add the relative days after calculating the linear time, to
551     // get right behaviour when jumping over the gregorianCutover.
552     time += daysOfYear[1] * (24 * 60 * 60 * 1000L);
553
554
555     TimeZone zone = getTimeZone();
556     int rawOffset = isSet[ZONE_OFFSET]
557       ? fields[ZONE_OFFSET] : zone.getRawOffset();
558
559     int dayOfYear = daysOfYear[0] + daysOfYear[1];
560     // This formula isn't right, so check for month as a quick fix.
561     // It doesn't compensate for leap years and puts day 30 in month 1
562     // instead of month 0.
563     int month = isSet[MONTH]
564         ? fields[MONTH] : (dayOfYear * 5 + 3) / (31 + 30 + 31 + 30 + 31);
565     // This formula isn't right, so check for day as a quick fix.  It
566     // doesn't compensate for leap years, either.
567     int day = isSet[DAY_OF_MONTH] ? fields[DAY_OF_MONTH]
568         : (6 + (dayOfYear * 5 + 3) % (31 + 30 + 31 + 30 + 31)) / 5;
569     int weekday = ((int) (time / (24 * 60 * 60 * 1000L)) + THURSDAY) % 7;
570     if (weekday <= 0)
571       weekday += 7;
572     int dstOffset = isSet[DST_OFFSET]
573       ? fields[DST_OFFSET] : (zone.getOffset((year < 0) ? BC : AD,
574                                              (year < 0) ? 1 - year : year,
575                                              month, day, weekday, millisInDay)
576                               - zone.getRawOffset());
577     time -= rawOffset + dstOffset;
578     isTimeSet = true;
579   }
580
581   /**
582    * <p>
583    * Determines if the given year is a leap year.  
584    * </p>
585    * <p>
586    * To specify a year in the BC era, use a negative value calculated
587    * as 1 - y, where y is the required year in BC.  So, 1 BC is 0,
588    * 2 BC is -1, 3 BC is -2, etc.
589    * </p>
590    *
591    * @param year a year (use a negative value for BC).
592    * @param gregorian if true, use the gregorian leap year rule.
593    * @return true, if the given year is a leap year, false otherwise.  
594    */
595   private boolean isLeapYear(int year, boolean gregorian)
596   {
597     if ((year & 3) != 0)
598       // Only years divisible by 4 can be leap years
599       return false;
600
601     if (!gregorian)
602       return true;
603
604     // We rely on AD area here.
605     return ((year % 100) != 0 || (year % 400) == 0);
606   }
607
608   /**
609    * Get the linear day in days since the epoch, using the
610    * Julian or Gregorian calendar as specified.  If you specify a
611    * nonpositive year it is interpreted as BC as following: 0 is 1
612    * BC, -1 is 2 BC and so on.  
613    *
614    * @param year the year of the date.
615    * @param dayOfYear the day of year of the date; 1 based.
616    * @param gregorian <code>true</code>, if we should use the Gregorian rules.
617    * @return the days since the epoch, may be negative.
618    */
619   private int getLinearDay(int year, int dayOfYear, boolean gregorian)
620   {
621     // The 13 is the number of days, that were omitted in the Gregorian
622     // Calender until the epoch.
623     // We shift right by 2 instead of dividing by 4, to get correct
624     // results for negative years (and this is even more efficient).
625     int julianDay = ((year * (365 * 4 + 1)) >> 2) + dayOfYear -
626       ((1970 * (365 * 4 + 1)) / 4 + 1 - 13);
627
628     if (gregorian)
629       {
630         // subtract the days that are missing in gregorian calendar
631         // with respect to julian calendar.
632         //
633         // Okay, here we rely on the fact that the gregorian
634         // calendar was introduced in the AD era.  This doesn't work
635         // with negative years.
636         //
637         // The additional leap year factor accounts for the fact that
638         // a leap day is not seen on Jan 1 of the leap year.
639         int gregOffset = (year / 400) - (year / 100) + 2;
640         if (isLeapYear (year, true) && dayOfYear < 31 + 29)
641           --gregOffset;
642         julianDay += gregOffset;
643       }
644     return julianDay;
645   }
646
647   /**
648    * Converts the given linear day into era, year, month,
649    * day_of_year, day_of_month, day_of_week, and writes the result
650    * into the fields array.
651    *
652    * @param day the linear day.  
653    * @param gregorian true, if we should use Gregorian rules.
654    */
655   private void calculateDay(int day, boolean gregorian)
656   {
657     // the epoch is a Thursday.
658     int weekday = (day + THURSDAY) % 7;
659     if (weekday <= 0)
660       weekday += 7;
661     fields[DAY_OF_WEEK] = weekday;
662
663     // get a first approximation of the year.  This may be one 
664     // year too big.
665     int year = 1970 + (gregorian
666                        ? ((day - 100) * 400) / (365 * 400 + 100 - 4 + 1)
667                        : ((day - 100) * 4) / (365 * 4 + 1));
668     if (day >= 0)
669       year++;
670
671     int firstDayOfYear = getLinearDay(year, 1, gregorian);
672
673     // Now look in which year day really lies.
674     if (day < firstDayOfYear)
675       {
676         year--;
677         firstDayOfYear = getLinearDay(year, 1, gregorian);
678       }
679
680     day -= firstDayOfYear - 1;  // day of year,  one based.
681
682     fields[DAY_OF_YEAR] = day;
683     if (year <= 0)
684       {
685         fields[ERA] = BC;
686         fields[YEAR] = 1 - year;
687       }
688     else
689       {
690         fields[ERA] = AD;
691         fields[YEAR] = year;
692       }
693
694     int leapday = isLeapYear(year, gregorian) ? 1 : 0;
695     if (day <= 31 + 28 + leapday)
696       {
697         fields[MONTH] = day / 32;       // 31->JANUARY, 32->FEBRUARY
698         fields[DAY_OF_MONTH] = day - 31 * fields[MONTH];
699       }
700     else
701       {
702         // A few more magic formulas
703         int scaledDay = (day - leapday) * 5 + 8;
704         fields[MONTH] = scaledDay / (31 + 30 + 31 + 30 + 31);
705         fields[DAY_OF_MONTH] = (scaledDay % (31 + 30 + 31 + 30 + 31)) / 5 + 1;
706       }
707   }
708
709   /**
710    * Converts the milliseconds since the epoch UTC
711    * (<code>time</code>) to time fields
712    * (<code>fields</code>).
713    */
714   protected synchronized void computeFields()
715   {
716     boolean gregorian = (time >= gregorianCutover);
717
718     TimeZone zone = getTimeZone();
719     fields[ZONE_OFFSET] = zone.getRawOffset();
720     long localTime = time + fields[ZONE_OFFSET];
721
722     int day = (int) (localTime / (24 * 60 * 60 * 1000L));
723     int millisInDay = (int) (localTime % (24 * 60 * 60 * 1000L));
724     if (millisInDay < 0)
725       {
726         millisInDay += (24 * 60 * 60 * 1000);
727         day--;
728       }
729
730     calculateDay(day, gregorian);
731     fields[DST_OFFSET] =
732       zone.getOffset(fields[ERA], fields[YEAR], fields[MONTH],
733                      fields[DAY_OF_MONTH], fields[DAY_OF_WEEK],
734                      millisInDay) - fields[ZONE_OFFSET];
735
736     millisInDay += fields[DST_OFFSET];
737     if (millisInDay >= 24 * 60 * 60 * 1000)
738       {
739         millisInDay -= 24 * 60 * 60 * 1000;
740         calculateDay(++day, gregorian);
741       }
742
743     fields[DAY_OF_WEEK_IN_MONTH] = (fields[DAY_OF_MONTH] + 6) / 7;
744
745     // which day of the week are we (0..6), relative to getFirstDayOfWeek
746     int relativeWeekday = (7 + fields[DAY_OF_WEEK] - getFirstDayOfWeek()) % 7;
747
748     fields[WEEK_OF_MONTH] = (fields[DAY_OF_MONTH] - relativeWeekday + 12) / 7;
749
750     int weekOfYear = (fields[DAY_OF_YEAR] - relativeWeekday + 6) / 7;
751
752     // Do the Correction: getMinimalDaysInFirstWeek() is always in the 
753     // first week.
754     int minDays = getMinimalDaysInFirstWeek();
755     int firstWeekday =
756       (7 + getWeekDay(fields[YEAR], minDays) - getFirstDayOfWeek()) % 7;
757     if (minDays - firstWeekday < 1)
758       weekOfYear++;
759     fields[WEEK_OF_YEAR] = weekOfYear;
760
761
762     int hourOfDay = millisInDay / (60 * 60 * 1000);
763     fields[AM_PM] = (hourOfDay < 12) ? AM : PM;
764     int hour = hourOfDay % 12;
765     fields[HOUR] = (hour == 0) ? 12 : hour;
766     fields[HOUR_OF_DAY] = hourOfDay;
767     millisInDay %= (60 * 60 * 1000);
768     fields[MINUTE] = millisInDay / (60 * 1000);
769     millisInDay %= (60 * 1000);
770     fields[SECOND] = millisInDay / (1000);
771     fields[MILLISECOND] = millisInDay % 1000;
772
773
774     areFieldsSet = isSet[ERA] = isSet[YEAR] = isSet[MONTH] =
775       isSet[WEEK_OF_YEAR] = isSet[WEEK_OF_MONTH] =
776       isSet[DAY_OF_MONTH] = isSet[DAY_OF_YEAR] = isSet[DAY_OF_WEEK] =
777       isSet[DAY_OF_WEEK_IN_MONTH] = isSet[AM_PM] = isSet[HOUR] =
778       isSet[HOUR_OF_DAY] = isSet[MINUTE] = isSet[SECOND] =
779       isSet[MILLISECOND] = isSet[ZONE_OFFSET] = isSet[DST_OFFSET] = true;
780
781   }
782
783   /**
784    * Compares the given calendar with this.  An object, o, is
785    * equivalent to this if it is also a <code>GregorianCalendar</code>
786    * with the same time since the epoch under the same conditions
787    * (same change date and same time zone).
788    *  
789    * @param o the object to that we should compare.
790    * @return true, if the given object is a calendar, that represents
791    * the same time (but doesn't necessarily have the same fields).
792    * @throws IllegalArgumentException if one of the fields
793    *         <code>ZONE_OFFSET</code> or <code>DST_OFFSET</code> is
794    *         specified, if an unknown field is specified or if one
795    *         of the calendar fields receives an illegal value when
796    *         leniancy is not enabled.
797    */
798   public boolean equals(Object o)
799   {
800     if (!(o instanceof GregorianCalendar))
801       return false;
802
803     GregorianCalendar cal = (GregorianCalendar) o;
804     return (cal.getTimeInMillis() == getTimeInMillis());
805   }
806
807 //     /**
808 //      * Compares the given calender with this.  
809 //      * @param o the object to that we should compare.
810 //      * @return true, if the given object is a calendar, and this calendar
811 //      * represents a smaller time than the calender o.
812 //      */
813 //     public boolean before(Object o) {
814 //         if (!(o instanceof GregorianCalendar))
815 //             return false;
816
817 //         GregorianCalendar cal = (GregorianCalendar) o;
818 //         return (cal.getTimeInMillis() < getTimeInMillis());
819 //     }
820
821 //     /**
822 //      * Compares the given calender with this.  
823 //      * @param o the object to that we should compare.
824 //      * @return true, if the given object is a calendar, and this calendar
825 //      * represents a bigger time than the calender o.
826 //      */
827 //     public boolean after(Object o) {
828 //         if (!(o instanceof GregorianCalendar))
829 //             return false;
830
831 //         GregorianCalendar cal = (GregorianCalendar) o;
832 //         return (cal.getTimeInMillis() > getTimeInMillis());
833 //     }
834
835   /**
836    * Adds the specified amount of time to the given time field.  The
837    * amount may be negative to subtract the time.  If the field overflows
838    * it does what you expect: Jan, 25 + 10 Days is Feb, 4.
839    * @param field one of the time field constants.
840    * @param amount the amount of time to add.
841    * @exception IllegalArgumentException if <code>field</code> is 
842    *   <code>ZONE_OFFSET</code>, <code>DST_OFFSET</code>, or invalid; or
843    *   if <code>amount</code> contains an out-of-range value and the calendar
844    *   is not in lenient mode.
845    */
846   public void add(int field, int amount)
847   {
848     switch (field)
849       {
850       case YEAR:
851         complete();
852         fields[YEAR] += amount;
853         isTimeSet = false;
854         break;
855       case MONTH:
856         complete();
857         int months = fields[MONTH] + amount;
858         fields[YEAR] += months / 12;
859         fields[MONTH] = months % 12;
860         if (fields[MONTH] < 0)
861           {
862             fields[MONTH] += 12;
863             fields[YEAR]--;
864           }
865         isTimeSet = false;
866         int maxDay = getActualMaximum(DAY_OF_MONTH);
867         if (fields[DAY_OF_MONTH] > maxDay)
868           {
869             fields[DAY_OF_MONTH] = maxDay;
870             isTimeSet = false;
871           }
872         break;
873       case DAY_OF_MONTH:
874       case DAY_OF_YEAR:
875       case DAY_OF_WEEK:
876         if (!isTimeSet)
877           computeTime();
878         time += amount * (24 * 60 * 60 * 1000L);
879         areFieldsSet = false;
880         break;
881       case WEEK_OF_YEAR:
882       case WEEK_OF_MONTH:
883       case DAY_OF_WEEK_IN_MONTH:
884         if (!isTimeSet)
885           computeTime();
886         time += amount * (7 * 24 * 60 * 60 * 1000L);
887         areFieldsSet = false;
888         break;
889       case AM_PM:
890         if (!isTimeSet)
891           computeTime();
892         time += amount * (12 * 60 * 60 * 1000L);
893         areFieldsSet = false;
894         break;
895       case HOUR:
896       case HOUR_OF_DAY:
897         if (!isTimeSet)
898           computeTime();
899         time += amount * (60 * 60 * 1000L);
900         areFieldsSet = false;
901         break;
902       case MINUTE:
903         if (!isTimeSet)
904           computeTime();
905         time += amount * (60 * 1000L);
906         areFieldsSet = false;
907         break;
908       case SECOND:
909         if (!isTimeSet)
910           computeTime();
911         time += amount * (1000L);
912         areFieldsSet = false;
913         break;
914       case MILLISECOND:
915         if (!isTimeSet)
916           computeTime();
917         time += amount;
918         areFieldsSet = false;
919         break;
920       case ZONE_OFFSET:
921       case DST_OFFSET:
922       default:
923         throw new IllegalArgumentException("Invalid or unknown field");
924       }
925   }
926
927
928   /**
929    * Rolls the specified time field up or down.  This means add one
930    * to the specified field, but don't change the other fields.  If
931    * the maximum for this field is reached, start over with the 
932    * minimum value.  
933    *
934    * <strong>Note:</strong> There may be situation, where the other
935    * fields must be changed, e.g rolling the month on May, 31. 
936    * The date June, 31 is automatically converted to July, 1. 
937    * This requires lenient settings.
938    *
939    * @param field the time field. One of the time field constants.
940    * @param up the direction, true for up, false for down.
941    * @throws IllegalArgumentException if one of the fields
942    *         <code>ZONE_OFFSET</code> or <code>DST_OFFSET</code> is
943    *         specified, if an unknown field is specified or if one
944    *         of the calendar fields receives an illegal value when
945    *         leniancy is not enabled.
946    */
947   public void roll(int field, boolean up)
948   {
949     roll(field, up ? 1 : -1);
950   }
951
952   /**
953    * Checks that the fields are still within their legal bounds,
954    * following use of the <code>roll()</code> method.
955    *
956    * @param field the field to check.
957    * @param delta multipler for alterations to the <code>time</code>.
958    * @see #roll(int, boolean)
959    * @see #roll(int, int)
960    */
961   private void cleanUpAfterRoll(int field, int delta)
962   {
963     switch (field)
964       {
965       case ERA:
966       case YEAR:
967       case MONTH:
968         // check that day of month is still in correct range
969         if (fields[DAY_OF_MONTH] > getActualMaximum(DAY_OF_MONTH))
970           fields[DAY_OF_MONTH] = getActualMaximum(DAY_OF_MONTH);
971         isTimeSet = false;
972         isSet[WEEK_OF_MONTH] = false;
973         isSet[DAY_OF_WEEK] = false;
974         isSet[DAY_OF_WEEK_IN_MONTH] = false;
975         isSet[DAY_OF_YEAR] = false;
976         isSet[WEEK_OF_YEAR] = false;
977         break;
978
979       case DAY_OF_MONTH:
980         isSet[WEEK_OF_MONTH] = false;
981         isSet[DAY_OF_WEEK] = false;
982         isSet[DAY_OF_WEEK_IN_MONTH] = false;
983         isSet[DAY_OF_YEAR] = false;
984         isSet[WEEK_OF_YEAR] = false;
985         time += delta * (24 * 60 * 60 * 1000L);
986         break;
987
988       case WEEK_OF_MONTH:
989         isSet[DAY_OF_MONTH] = false;
990         isSet[DAY_OF_WEEK_IN_MONTH] = false;
991         isSet[DAY_OF_YEAR] = false;
992         isSet[WEEK_OF_YEAR] = false;
993         time += delta * (7 * 24 * 60 * 60 * 1000L);
994         break;
995       case DAY_OF_WEEK_IN_MONTH:
996         isSet[DAY_OF_MONTH] = false;
997         isSet[WEEK_OF_MONTH] = false;
998         isSet[DAY_OF_YEAR] = false;
999         isSet[WEEK_OF_YEAR] = false;
1000         time += delta * (7 * 24 * 60 * 60 * 1000L);
1001         break;
1002       case DAY_OF_YEAR:
1003         isSet[MONTH] = false;
1004         isSet[DAY_OF_MONTH] = false;
1005         isSet[WEEK_OF_MONTH] = false;
1006         isSet[DAY_OF_WEEK_IN_MONTH] = false;
1007         isSet[DAY_OF_WEEK] = false;
1008         isSet[WEEK_OF_YEAR] = false;
1009         time += delta * (24 * 60 * 60 * 1000L);
1010         break;
1011       case WEEK_OF_YEAR:
1012         isSet[MONTH] = false;
1013         isSet[DAY_OF_MONTH] = false;
1014         isSet[WEEK_OF_MONTH] = false;
1015         isSet[DAY_OF_WEEK_IN_MONTH] = false;
1016         isSet[DAY_OF_YEAR] = false;
1017         time += delta * (7 * 24 * 60 * 60 * 1000L);
1018         break;
1019
1020       case AM_PM:
1021         isSet[HOUR_OF_DAY] = false;
1022         time += delta * (12 * 60 * 60 * 1000L);
1023         break;
1024       case HOUR:
1025         isSet[HOUR_OF_DAY] = false;
1026         time += delta * (60 * 60 * 1000L);
1027         break;
1028       case HOUR_OF_DAY:
1029         isSet[HOUR] = false;
1030         isSet[AM_PM] = false;
1031         time += delta * (60 * 60 * 1000L);
1032         break;
1033
1034       case MINUTE:
1035         time += delta * (60 * 1000L);
1036         break;
1037       case SECOND:
1038         time += delta * (1000L);
1039         break;
1040       case MILLISECOND:
1041         time += delta;
1042         break;
1043       }
1044   }
1045
1046   /**
1047    * Rolls the specified time field by the given amount.  This means
1048    * add amount to the specified field, but don't change the other
1049    * fields.  If the maximum for this field is reached, start over
1050    * with the minimum value and vice versa for negative amounts.
1051    *
1052    * <strong>Note:</strong> There may be situation, where the other
1053    * fields must be changed, e.g rolling the month on May, 31. 
1054    * The date June, 31 is automatically corrected to June, 30.
1055    *
1056    * @param field the time field. One of the time field constants.
1057    * @param amount the amount by which we should roll.
1058    * @throws IllegalArgumentException if one of the fields
1059    *         <code>ZONE_OFFSET</code> or <code>DST_OFFSET</code> is
1060    *         specified, if an unknown field is specified or if one
1061    *         of the calendar fields receives an illegal value when
1062    *         leniancy is not enabled.
1063    */
1064   public void roll(int field, int amount)
1065   {
1066     switch (field)
1067       {
1068       case DAY_OF_WEEK:
1069         // day of week is special: it rolls automatically
1070         add(field, amount);
1071         return;
1072       case ZONE_OFFSET:
1073       case DST_OFFSET:
1074         throw new IllegalArgumentException("Can't roll time zone");
1075       }
1076     complete();
1077     int min = getActualMinimum(field);
1078     int range = getActualMaximum(field) - min + 1;
1079     int oldval = fields[field];
1080     int newval = (oldval - min + range + amount) % range + min;
1081     if (newval < min)
1082       newval += range;
1083     fields[field] = newval;
1084     cleanUpAfterRoll(field, newval - oldval);
1085   }
1086
1087   /**
1088    * The minimum values for the calendar fields.
1089    */
1090   private static final int[] minimums =
1091       { BC,       1,  0,  0, 1,  1,   1,   SUNDAY, 1, 
1092         AM,  1,  0,  1,  1,   1, -(12*60*60*1000),               0 };
1093
1094   /**
1095    * The maximum values for the calendar fields.
1096    */
1097   private static final int[] maximums =
1098       { AD, 5000000, 11, 53, 5, 31, 366, SATURDAY, 5, 
1099         PM, 12, 23, 59, 59, 999, +(12*60*60*1000), (12*60*60*1000) };
1100
1101   /**
1102    * Gets the smallest value that is allowed for the specified field.
1103    *
1104    * @param field one of the time field constants.
1105    * @return the smallest value for the specified field.
1106    */
1107   public int getMinimum(int field)
1108   {
1109     return minimums[field];
1110   }
1111
1112   /**
1113    * Gets the biggest value that is allowed for the specified field.
1114    *
1115    * @param field one of the time field constants.
1116    * @return the biggest value.
1117    */
1118   public int getMaximum(int field)
1119   {
1120     return maximums[field];
1121   }
1122
1123
1124   /**
1125    * Gets the greatest minimum value that is allowed for the specified field.
1126    * This is the largest value returned by the <code>getActualMinimum(int)</code>
1127    * method.
1128    *
1129    * @param field the time field. One of the time field constants.
1130    * @return the greatest minimum value.
1131    * @see #getActualMinimum(int)
1132    */
1133   public int getGreatestMinimum(int field)
1134   {
1135     if (field == WEEK_OF_YEAR)
1136       return 1;
1137     return minimums[field];
1138   }
1139
1140   /**
1141    * Gets the smallest maximum value that is allowed for the
1142    * specified field.  This is the smallest value returned
1143    * by the <code>getActualMaximum(int)</code>.  For example,
1144    * this is 28 for DAY_OF_MONTH (as all months have at least
1145    * 28 days).
1146    *
1147    * @param field the time field. One of the time field constants.
1148    * @return the least maximum value.  
1149    * @see #getActualMaximum(int)
1150    * @since 1.2
1151    */
1152   public int getLeastMaximum(int field)
1153   {
1154     switch (field)
1155       {
1156       case WEEK_OF_YEAR:
1157         return 52;
1158       case DAY_OF_MONTH:
1159         return 28;
1160       case DAY_OF_YEAR:
1161         return 365;
1162       case DAY_OF_WEEK_IN_MONTH:
1163       case WEEK_OF_MONTH:
1164         return 4;
1165       default:
1166         return maximums[field];
1167       }
1168   }
1169
1170   /**
1171    * Gets the actual minimum value that is allowed for the specified field.
1172    * This value is dependent on the values of the other fields.  Note that
1173    * this calls <code>complete()</code> if not enough fields are set.  This
1174    * can have ugly side effects.  The value given depends on the current
1175    * time used by this instance.
1176    *
1177    * @param field the time field. One of the time field constants.
1178    * @return the actual minimum value.
1179    * @since 1.2
1180    */
1181   public int getActualMinimum(int field)
1182   {
1183     if (field == WEEK_OF_YEAR)
1184       {
1185         int min = getMinimalDaysInFirstWeek();
1186         if (min == 0)
1187           return 1;
1188         if (!areFieldsSet || !isSet[ERA] || !isSet[YEAR])
1189           complete();
1190
1191         int year = fields[ERA] == AD ? fields[YEAR] : 1 - fields[YEAR];
1192         int weekday = getWeekDay(year, min);
1193         if ((7 + weekday - getFirstDayOfWeek()) % 7 >= min - 1)
1194           return 1;
1195         return 0;
1196       }
1197     return minimums[field];
1198   }
1199
1200   /**
1201    * Gets the actual maximum value that is allowed for the specified field.
1202    * This value is dependent on the values of the other fields.  Note that
1203    * this calls <code>complete()</code> if not enough fields are set.  This
1204    * can have ugly side effects.  The value given depends on the current time
1205    * used by this instance; thus, leap years have a maximum day of month value of
1206    * 29, rather than 28.
1207    *
1208    * @param field the time field. One of the time field constants.
1209    * @return the actual maximum value.  
1210    */
1211   public int getActualMaximum(int field)
1212   {
1213     switch (field)
1214       {
1215       case WEEK_OF_YEAR:
1216         {
1217           if (!areFieldsSet || !isSet[ERA] || !isSet[YEAR])
1218             complete();
1219           // This is wrong for the year that contains the gregorian change.
1220           // I.e it gives the weeks in the julian year or in the gregorian
1221           // year in that case.
1222           int year = fields[ERA] == AD ? fields[YEAR] : 1 - fields[YEAR];
1223           int lastDay = isLeapYear(year) ? 366 : 365;
1224           int weekday = getWeekDay(year, lastDay);
1225           int week = (lastDay + 6
1226                       - (7 + weekday - getFirstDayOfWeek()) % 7) / 7;
1227
1228           int minimalDays = getMinimalDaysInFirstWeek();
1229           int firstWeekday = getWeekDay(year, minimalDays);
1230           /* 
1231            * Is there a set of days at the beginning of the year, before the
1232            * first day of the week, equal to or greater than the minimum number
1233            * of days required in the first week?
1234            */
1235           if (minimalDays - (7 + firstWeekday - getFirstDayOfWeek()) % 7 < 1)
1236             return week + 1; /* Add week 1: firstWeekday through to firstDayOfWeek */
1237         }
1238         case DAY_OF_MONTH:
1239         {
1240           if (!areFieldsSet || !isSet[MONTH])
1241             complete();
1242           int month = fields[MONTH];
1243           // If you change this, you should also change 
1244           // SimpleTimeZone.getDaysInMonth();
1245           if (month == FEBRUARY)
1246             {
1247               if (!isSet[YEAR] || !isSet[ERA])
1248                 complete();
1249               int year = fields[ERA] == AD ? fields[YEAR] : 1 - fields[YEAR];
1250               return isLeapYear(year) ? 29 : 28;
1251             }
1252           else if (month < AUGUST)
1253             return 31 - (month & 1);
1254           else
1255             return 30 + (month & 1);
1256         }
1257       case DAY_OF_YEAR:
1258         {
1259           if (!areFieldsSet || !isSet[ERA] || !isSet[YEAR])
1260             complete();
1261           int year = fields[ERA] == AD ? fields[YEAR] : 1 - fields[YEAR];
1262           return isLeapYear(year) ? 366 : 365;
1263         }
1264       case DAY_OF_WEEK_IN_MONTH:
1265         {
1266           // This is wrong for the month that contains the gregorian change.
1267           int daysInMonth = getActualMaximum(DAY_OF_MONTH);
1268           // That's black magic, I know
1269           return (daysInMonth - (fields[DAY_OF_MONTH] - 1) % 7 + 6) / 7;
1270         }
1271       case WEEK_OF_MONTH:
1272         {
1273           int daysInMonth = getActualMaximum(DAY_OF_MONTH);
1274           int weekday = (daysInMonth - fields[DAY_OF_MONTH]
1275                          + fields[DAY_OF_WEEK] - SUNDAY) % 7 + SUNDAY;
1276           return (daysInMonth + 6
1277                   - (7 + weekday - getFirstDayOfWeek()) % 7) / 7;
1278         }
1279       default:
1280         return maximums[field];
1281       }
1282   }
1283
1284
1285 }