/[classpath]/classpath/java/util/GregorianCalendar.java
ViewVC logotype

Diff of /classpath/java/util/GregorianCalendar.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.26.2.4 by gnu_andrew, Sat Jan 22 02:20:02 2005 UTC revision 1.26.2.5 by gnu_andrew, Mon Jan 24 01:59:54 2005 UTC
# Line 165  public class GregorianCalendar extends C Line 165  public class GregorianCalendar extends C
165    private static final String bundleName = "gnu.java.locale.Calendar";    private static final String bundleName = "gnu.java.locale.Calendar";
166    
167    /**    /**
168       * Days in the epoch. Relative Jan 1, year '0' which is not a leap year.
169       * (although there is no year zero, this does not matter.)
170       * This is consistent with the formula:
171       * = (year-1)*365L + ((year-1) >> 2)
172       *
173       * Plus the gregorian correction:
174       *  Math.floor((year-1) / 400.) - Math.floor((year-1) / 100.);
175       * For a correct julian date, the correction is -2 instead.
176       *
177       * The gregorian cutover in 1582 was 10 days, so by calculating the
178       * correction from year zero, we have 15 non-leap days (even centuries)
179       * minus 3 leap days (year 400,800,1200) = 12. Subtracting two corrects
180       * this to the correct number 10.
181       */
182      private static final int EPOCH_DAYS = 719162;
183    
184      /**
185     * Retrieves the resource bundle.  The resources should be loaded     * Retrieves the resource bundle.  The resources should be loaded
186     * via this method only. Iff an application uses this method, the     * via this method only. Iff an application uses this method, the
187     * resourcebundle is required.     * resourcebundle is required.
# Line 326  public class GregorianCalendar extends C Line 343  public class GregorianCalendar extends C
343     */     */
344    public boolean isLeapYear(int year)    public boolean isLeapYear(int year)
345    {    {
346        // Only years divisible by 4 can be leap years
347      if ((year & 3) != 0)      if ((year & 3) != 0)
       // Only years divisible by 4 can be leap years  
348        return false;        return false;
349    
350      // compute the linear day of the 29. February of that year.      // Is the leap-day a Julian date? Then it's a leap year
351      // The 13 is the number of days, that were omitted in the Gregorian      if (! isGregorian(year, 31 + 29 - 1))
     // Calender until the epoch.  
     int julianDay = (((year - 1) * (365 * 4 + 1)) >> 2)  
                     + (31 + 29 - (((1970 - 1) * (365 * 4 + 1)) / 4 + 1 - 13));  
   
     // If that day is smaller than the gregorianChange the julian  
     // rule applies:  This is a leap year since it is divisible by 4.  
     if (julianDay * (24 * 60 * 60 * 1000L) < gregorianCutover)  
352        return true;        return true;
353    
354        // Apply gregorian rules otherwise
355      return ((year % 100) != 0 || (year % 400) == 0);      return ((year % 100) != 0 || (year % 400) == 0);
356    }    }
357    
358    /**    /**
    * Get the linear time in milliseconds since the epoch.  If you  
    * specify a nonpositive year it is interpreted as BC as  
    * following: 0 is 1 BC, -1 is 2 BC and so on.  The date is  
    * interpreted as gregorian if the change occurred before that date.  
    *  
    * @param year the year of the date.  
    * @param dayOfYear the day of year of the date; 1 based.  
    * @param millis the millisecond in that day.  
    * @return the days since the epoch, may be negative.  
    */  
   private long getLinearTime(int year, int dayOfYear, int millis)  
   {  
     // The 13 is the number of days, that were omitted in the Gregorian  
     // Calendar until the epoch.  
     // We shift right by 2 instead of dividing by 4, to get correct  
     // results for negative years (and this is even more efficient).  
     int julianDay = ((year * (365 * 4 + 1)) >> 2) + dayOfYear  
                     - ((1970 * (365 * 4 + 1)) / 4 + 1 - 13);  
     long time = julianDay * (24 * 60 * 60 * 1000L) + millis;  
   
     if (time >= gregorianCutover)  
       {  
         // subtract the days that are missing in gregorian calendar  
         // with respect to julian calendar.  
         //  
         // Okay, here we rely on the fact that the gregorian  
         // calendar was introduced in the AD era.  This doesn't work  
         // with negative years.  
         //  
         // The additional leap year factor accounts for the fact that  
         // a leap day is not seen on Jan 1 of the leap year.  
         // And on and after the leap day, the leap day has already been  
         // included in dayOfYear.  
         int gregOffset = (year / 400) - (year / 100) + 2;  
         if (isLeapYear(year, true))  
           --gregOffset;  
         time += gregOffset * (24 * 60 * 60 * 1000L);  
       }  
     return time;  
   }  
   
   /**  
359     * Retrieves the day of the week corresponding to the specified     * Retrieves the day of the week corresponding to the specified
360     * day of the specified year.     * day of the specified year.
361     *     *
# Line 396  public class GregorianCalendar extends C Line 365  public class GregorianCalendar extends C
365     */     */
366    private int getWeekDay(int year, int dayOfYear)    private int getWeekDay(int year, int dayOfYear)
367    {    {
368      int day = (int) (getLinearTime(year, dayOfYear, 0) / (24 * 60 * 60 * 1000L));      boolean greg = isGregorian(year, dayOfYear);
369        int day = (int) getLinearDay(year, dayOfYear, greg);
370    
371      // The epoch was a thursday.      // The epoch was a thursday.
372      int weekday = (day + THURSDAY) % 7;      int weekday = (day + THURSDAY) % 7;
# Line 506  public class GregorianCalendar extends C Line 476  public class GregorianCalendar extends C
476    }    }
477    
478    /**    /**
479       * Takes a year, and a (zero based) day of year and determines
480       * if it is gregorian or not.
481       */
482      private boolean isGregorian(int year, int dayOfYear)
483      {
484        int relativeDay = (year - 1) * 365 + ((year - 1) >> 2) + dayOfYear
485                          - EPOCH_DAYS; // gregorian days from 1 to epoch.
486        int gregFactor = (int) Math.floor((double) (year - 1) / 400.)
487                         - (int) Math.floor((double) (year - 1) / 100.);
488    
489        return ((relativeDay + gregFactor) * 60L * 60L * 24L * 1000L >= gregorianCutover);
490      }
491    
492      /**
493     * Converts the time field values (<code>fields</code>) to     * Converts the time field values (<code>fields</code>) to
494     * milliseconds since the epoch UTC (<code>time</code>).     * milliseconds since the epoch UTC (<code>time</code>).
495     *     *
# Line 514  public class GregorianCalendar extends C Line 498  public class GregorianCalendar extends C
498     */     */
499    protected synchronized void computeTime()    protected synchronized void computeTime()
500    {    {
501        int millisInDay = 0;
502      int era = isSet[ERA] ? fields[ERA] : AD;      int era = isSet[ERA] ? fields[ERA] : AD;
503      int year = isSet[YEAR] ? fields[YEAR] : 1970;      int year = isSet[YEAR] ? fields[YEAR] : 1970;
504      if (isLenient() && isSet[MONTH])      int month = isSet[MONTH] ? fields[MONTH] : 0;
505        {      int day = isSet[DAY_OF_MONTH] ? fields[DAY_OF_MONTH] : 1;
506          int month = fields[MONTH];      int minute = isSet[MINUTE] ? fields[MINUTE] : 0;
507          year += month / 12;      int second = isSet[SECOND] ? fields[SECOND] : 0;
508          month %= 12;      int millis = isSet[MILLISECOND] ? fields[MILLISECOND] : 0;
509          if (month < 0)      int[] month_days = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
510            {      int[] dayCount = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
511              month += 12;      int hour = 0;
             year--;  
           }  
         fields[MONTH] = month;  
         isSet[YEAR] = true;  
         fields[YEAR] = year;  
       }  
512    
513      if (era == BC)      if (era == BC && year > 0)
514        year = 1 - year;        year = 1 - year;
515    
516      int[] daysOfYear = getDayOfYear(year);      // should negative BC years be AD?
517        // get the hour (but no check for validity)
     int hour = 0;  
518      if (isSet[HOUR_OF_DAY])      if (isSet[HOUR_OF_DAY])
519        hour = fields[HOUR_OF_DAY];        hour = fields[HOUR_OF_DAY];
520      else if (isSet[HOUR])      else if (isSet[HOUR])
# Line 550  public class GregorianCalendar extends C Line 528  public class GregorianCalendar extends C
528            hour = 0;            hour = 0;
529        }        }
530    
     int minute = isSet[MINUTE] ? fields[MINUTE] : 0;  
     int second = isSet[SECOND] ? fields[SECOND] : 0;  
     int millis = isSet[MILLISECOND] ? fields[MILLISECOND] : 0;  
     int millisInDay;  
   
531      if (isLenient())      if (isLenient())
532        {        {
533          // prevent overflow          // Read the era,year,month,day fields and convert as appropriate.
534            // Calculate number of milliseconds into the day
535            // This takes care of both h, m, s, ms over/underflows.
536          long allMillis = (((hour * 60L) + minute) * 60L + second) * 1000L          long allMillis = (((hour * 60L) + minute) * 60L + second) * 1000L
537                           + millis;                           + millis;
538          daysOfYear[1] += allMillis / (24 * 60 * 60 * 1000L);          day += allMillis / (24 * 60 * 60 * 1000L);
539          millisInDay = (int) (allMillis % (24 * 60 * 60 * 1000L));          millisInDay = (int) (allMillis % (24 * 60 * 60 * 1000L));
540    
541            if (isSet[MONTH])
542              {
543                if (month < 0)
544                  {
545                    year += (int) month / 12;
546                    month = month % 12;
547                    if (month < 0)
548                      {
549                        month += 12;
550                        year--;
551                      }
552                  }
553                if (month > 11)
554                  {
555                    year += (month / 12);
556                    month = month % 12;
557                  }
558              }
559    
560            if (isSet[DAY_OF_MONTH])
561              {
562                month_days[1] = isLeapYear(year) ? 29 : 28;
563    
564                while (day <= 0)
565                  {
566                    if (month == 0)
567                      {
568                        year--;
569                        month_days[1] = isLeapYear(year) ? 29 : 28;
570                      }
571                    month = (month + 11) % 12;
572                    day += month_days[month];
573                  }
574                while (day > month_days[month])
575                  {
576                    day -= (month_days[month]);
577                    month = (month + 1) % 12;
578                    if (month == 0)
579                      {
580                        year++;
581                        month_days[1] = isLeapYear(year) ? 29 : 28;
582                      }
583                  }
584              }
585        }        }
586      else      else
587        {        {
588          if (hour < 0 || hour >= 24 || minute < 0 || minute > 59 || second < 0          // non-lenient
589              || second > 59 || millis < 0 || millis >= 1000)          if (month < 0 || month > 11 || hour < 0 || hour >= 24 || minute < 0
590                || minute > 59 || second < 0 || second > 59 || millis < 0
591                || millis >= 1000)
592              throw new IllegalArgumentException();
593            if (day < 1 || day > month_days[month])
594            throw new IllegalArgumentException();            throw new IllegalArgumentException();
595          millisInDay = (((hour * 60) + minute) * 60 + second) * 1000 + millis;          millisInDay = (((hour * 60) + minute) * 60 + second) * 1000 + millis;
596        }        }
     time = getLinearTime(year, daysOfYear[0], millisInDay);  
597    
598      // Add the relative days after calculating the linear time, to      // ok, by here we have valid day,month,year,era and millisinday
599      // get right behaviour when jumping over the gregorianCutover.      int dayOfYear = dayCount[month] + day - 1; // (day starts on 1)
600      time += daysOfYear[1] * (24 * 60 * 60 * 1000L);      if (isLeapYear(year) && month > 1)
601          dayOfYear++;
602    
603        int relativeDay = (year - 1) * 365 + ((year - 1) >> 2) + dayOfYear
604                          - EPOCH_DAYS; // gregorian days from 1 to epoch.
605        int gregFactor = (int) Math.floor((double) (year - 1) / 400.)
606                         - (int) Math.floor((double) (year - 1) / 100.);
607    
608        if ((relativeDay + gregFactor) * 60L * 60L * 24L * 1000L >= gregorianCutover)
609          relativeDay += gregFactor;
610        else
611          relativeDay -= 2;
612    
613        time = relativeDay * (24 * 60 * 60 * 1000L) + millisInDay;
614    
615      TimeZone zone = getTimeZone();      TimeZone zone = getTimeZone();
616      int rawOffset = isSet[ZONE_OFFSET] ? fields[ZONE_OFFSET]      int rawOffset = isSet[ZONE_OFFSET] ? fields[ZONE_OFFSET]
617                                         : zone.getRawOffset();                                         : zone.getRawOffset();
618    
619      int day = (int) (time / (24 * 60 * 60 * 1000L));      // the epoch was a Thursday.
620      millisInDay = (int) (time % (24 * 60 * 60 * 1000L));      int weekday = (int) (relativeDay + THURSDAY) % 7;
621      if (millisInDay < 0)      if (weekday <= 0)
622        {        weekday += 7;
623          millisInDay += (24 * 60 * 60 * 1000);      fields[DAY_OF_WEEK] = weekday;
         day--;  
       }  
624    
     int[] f = new int[FIELD_COUNT];  
     calculateDay(f, day, time - rawOffset >= gregorianCutover);  
     year = f[YEAR];  
     int month = f[MONTH];  
     day = f[DAY_OF_MONTH];  
     int weekday = f[DAY_OF_WEEK];  
625      int dstOffset = isSet[DST_OFFSET] ? fields[DST_OFFSET]      int dstOffset = isSet[DST_OFFSET] ? fields[DST_OFFSET]
626                                        : (zone.getOffset((year < 0) ? BC : AD,                                        : (zone.getOffset((year < 1) ? BC : AD,
627                                                          (year < 0) ? 1 - year                                                          (year < 1) ? 1 - year
628                                                                     : year,                                                                     : year,
629                                                          month, day, weekday,                                                          month, day, weekday,
630                                                          millisInDay)                                                          millisInDay)
631                                        - zone.getRawOffset());                                        - zone.getRawOffset());
632      time -= rawOffset + dstOffset;      time -= (rawOffset + dstOffset);
633      isTimeSet = true;      isTimeSet = true;
634    }    }
635    
636    /**    /**
    * <p>  
    * Determines if the given year is a leap year.  
    * </p>  
    * <p>  
    * To specify a year in the BC era, use a negative value calculated  
    * as 1 - y, where y is the required year in BC.  So, 1 BC is 0,  
    * 2 BC is -1, 3 BC is -2, etc.  
    * </p>  
    *  
    * @param year a year (use a negative value for BC).  
    * @param gregorian if true, use the gregorian leap year rule.  
    * @return true, if the given year is a leap year, false otherwise.  
    */  
   private boolean isLeapYear(int year, boolean gregorian)  
   {  
     if ((year & 3) != 0)  
       // Only years divisible by 4 can be leap years  
       return false;  
   
     if (! gregorian)  
       return true;  
   
     // We rely on AD area here.  
     return ((year % 100) != 0 || (year % 400) == 0);  
   }  
   
   /**  
637     * Get the linear day in days since the epoch, using the     * Get the linear day in days since the epoch, using the
638     * Julian or Gregorian calendar as specified.  If you specify a     * Julian or Gregorian calendar as specified.  If you specify a
639     * nonpositive year it is interpreted as BC as following: 0 is 1     * nonpositive year it is interpreted as BC as following: 0 is 1
# Line 643  public class GregorianCalendar extends C Line 644  public class GregorianCalendar extends C
644     * @param gregorian <code>true</code>, if we should use the Gregorian rules.     * @param gregorian <code>true</code>, if we should use the Gregorian rules.
645     * @return the days since the epoch, may be negative.     * @return the days since the epoch, may be negative.
646     */     */
647    private long getLinearDay(int year, int dayOfYear, boolean gregorian)    public long getLinearDay(int year, int dayOfYear, boolean gregorian)
648    {    {
649      // The 13 is the number of days, that were omitted in the Gregorian      // The 13 is the number of days, that were omitted in the Gregorian
650      // Calender until the epoch.      // Calender until the epoch.
651      // We shift right by 2 instead of dividing by 4, to get correct      // We shift right by 2 instead of dividing by 4, to get correct
652      // results for negative years (and this is even more efficient).      // results for negative years (and this is even more efficient).
653      long julianDay = ((year * (365L * 4 + 1)) >> 2) + dayOfYear      long julianDay = (year - 1) * 365L + ((year - 1) >> 2) + (dayOfYear - 1)
654                       - ((1970 * (365 * 4 + 1)) / 4 + 1 - 13);                       - EPOCH_DAYS; // gregorian days from 1 to epoch.
655    
656      if (gregorian)      if (gregorian)
657        {        {
# Line 663  public class GregorianCalendar extends C Line 664  public class GregorianCalendar extends C
664          //          //
665          // The additional leap year factor accounts for the fact that          // The additional leap year factor accounts for the fact that
666          // a leap day is not seen on Jan 1 of the leap year.          // a leap day is not seen on Jan 1 of the leap year.
667          int gregOffset = (year / 400) - (year / 100) + 2;          int gregOffset = (int) Math.floor((double) (year - 1) / 400.)
668          if (isLeapYear(year, true) && dayOfYear < 31 + 29)                           - (int) Math.floor((double) (year - 1) / 100.);
669            --gregOffset;  
670          julianDay += gregOffset;          return julianDay + gregOffset;
671        }        }
672        else
673          julianDay -= 2;
674      return julianDay;      return julianDay;
675    }    }
676    
# Line 681  public class GregorianCalendar extends C Line 684  public class GregorianCalendar extends C
684     */     */
685    private void calculateDay(int[] fields, long day, boolean gregorian)    private void calculateDay(int[] fields, long day, boolean gregorian)
686    {    {
687      // the epoch is a Thursday.      // the epoch was a Thursday.
688      int weekday = (int) (day + THURSDAY) % 7;      int weekday = (int) (day + THURSDAY) % 7;
689      if (weekday <= 0)      if (weekday <= 0)
690        weekday += 7;        weekday += 7;
# Line 691  public class GregorianCalendar extends C Line 694  public class GregorianCalendar extends C
694      // year too big.      // year too big.
695      int year = 1970      int year = 1970
696                 + (int) (gregorian                 + (int) (gregorian
697                          ? ((day - 100) * 400) / (365 * 400 + 100 - 4 + 1)                          ? ((day - 100L) * 400L) / (365L * 400L + 100L - 4L
698                          : ((day - 100) * 4) / (365 * 4 + 1));                          + 1L) : ((day - 100L) * 4L) / (365L * 4L + 1L));
699      if (day >= 0)      if (day >= 0)
700        year++;        year++;
701    
# Line 719  public class GregorianCalendar extends C Line 722  public class GregorianCalendar extends C
722          fields[YEAR] = year;          fields[YEAR] = year;
723        }        }
724    
725      int leapday = isLeapYear(year, gregorian) ? 1 : 0;      int leapday = isLeapYear(year) ? 1 : 0;
726      if (day <= 31 + 28 + leapday)      if (day <= 31 + 28 + leapday)
727        {        {
728          fields[MONTH] = (int) day / 32; // 31->JANUARY, 32->FEBRUARY          fields[MONTH] = (int) day / 32; // 31->JANUARY, 32->FEBRUARY
# Line 749  public class GregorianCalendar extends C Line 752  public class GregorianCalendar extends C
752    
753      long day = localTime / (24 * 60 * 60 * 1000L);      long day = localTime / (24 * 60 * 60 * 1000L);
754      int millisInDay = (int) (localTime % (24 * 60 * 60 * 1000L));      int millisInDay = (int) (localTime % (24 * 60 * 60 * 1000L));
755    
756      if (millisInDay < 0)      if (millisInDay < 0)
757        {        {
758          millisInDay += (24 * 60 * 60 * 1000);          millisInDay += (24 * 60 * 60 * 1000);
# Line 824  public class GregorianCalendar extends C Line 828  public class GregorianCalendar extends C
828      return (cal.getTimeInMillis() == getTimeInMillis());      return (cal.getTimeInMillis() == getTimeInMillis());
829    }    }
830    
 //     /**  
 //      * Compares the given calender with this.    
 //      * @param o the object to that we should compare.  
 //      * @return true, if the given object is a calendar, and this calendar  
 //      * represents a smaller time than the calender o.  
 //      */  
 //     public boolean before(Object o) {  
 //         if (!(o instanceof GregorianCalendar))  
 //             return false;  
 //         GregorianCalendar cal = (GregorianCalendar) o;  
 //         return (cal.getTimeInMillis() < getTimeInMillis());  
 //     }  
 //     /**  
 //      * Compares the given calender with this.    
 //      * @param o the object to that we should compare.  
 //      * @return true, if the given object is a calendar, and this calendar  
 //      * represents a bigger time than the calender o.  
 //      */  
 //     public boolean after(Object o) {  
 //         if (!(o instanceof GregorianCalendar))  
 //             return false;  
 //         GregorianCalendar cal = (GregorianCalendar) o;  
 //         return (cal.getTimeInMillis() > getTimeInMillis());  
 //     }  
   
831    /**    /**
832     * Adds the specified amount of time to the given time field.  The     * Adds the specified amount of time to the given time field.  The
833     * amount may be negative to subtract the time.  If the field overflows     * amount may be negative to subtract the time.  If the field overflows

Legend:
Removed from v.1.26.2.4  
changed lines
  Added in v.1.26.2.5

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26