gregoriancalendar.java

来自「《移动Agent技术》一书的所有章节源代码。」· Java 代码 · 共 1,497 行 · 第 1/5 页

JAVA
1,497
字号
     * @param date the value used to set the DATE time field in the calendar.
     * @param hour the value used to set the HOUR_OF_DAY time field
     * in the calendar.
     * @param minute the value used to set the MINUTE time field
     * in the calendar.
     * @param second the value used to set the SECOND time field
     * in the calendar.
     */
    public GregorianCalendar(int year, int month, int date, int hour,
                             int minute, int second)
    {
        super(TimeZone.getDefault(), Locale.getDefault());
        this.set(ERA, AD);
        this.set(YEAR, year);
        this.set(MONTH, month);
        this.set(DATE, date);
        this.set(HOUR_OF_DAY, hour);
        this.set(MINUTE, minute);
        this.set(SECOND, second);
    }

    /**
     * Compares this calendar to the specified object.
     * The result is <code>true</code> if and only if the argument is
     * not <code>null</code> and is a <code>Calendar</code> object that
     * represents the same calendar as this object.
     * @param obj the object to compare with.
     * @return <code>true</code> if the objects are the same;
     * <code>false</code> otherwise.
     */
    public boolean equals(Object obj) {
        // This body moves to Calendar in 1.2
        if (this == obj)
            return true;
        if (!(obj instanceof Calendar))
            return false;

        Calendar that = (Calendar)obj;

        return getTimeInMillis() == that.getTimeInMillis() &&
            isLenient() == that.isLenient() &&
	    getFirstDayOfWeek() == that.getFirstDayOfWeek() &&
            getMinimalDaysInFirstWeek() == that.getMinimalDaysInFirstWeek() &&
            getTimeZone().equals(that.getTimeZone());
    }

    /**
     * Compares the time field records.
     * Equivalent to comparing result of conversion to UTC.
     * @param when the Calendar to be compared with this Calendar.
     * @return true if the current time of this Calendar is before
     * the time of Calendar when; false otherwise.
     */
    public boolean before(Object when) {
        // This body moves to Calendar in 1.2
        return when instanceof Calendar &&
            getTimeInMillis() < ((Calendar) when).getTimeInMillis();
    }

    /**
     * Compares the time field records.
     * Equivalent to comparing result of conversion to UTC.
     * @param when the Calendar to be compared with this Calendar.
     * @return true if the current time of this Calendar is after
     * the time of Calendar when; false otherwise.
     */
    public boolean after(Object when) {
        // This body moves to Calendar in 1.2
        return when instanceof Calendar &&
            getTimeInMillis() > ((Calendar) when).getTimeInMillis();
    }

    /**
     * Sets the GregorianCalendar change date. This is the point when the
     * switch from Julian dates to Gregorian dates occurred. Default is
     * 00:00:00 local time, October 15, 1582. Previous to this time and date
     * will be Julian dates.
     *
     * @param date the given Gregorian cutover date.
     */
    public void setGregorianChange(Date date)
    {
        gregorianCutover = date.getTime();
    }

    /**
     * Gets the Gregorian Calendar change date.  This is the point when the
     * switch from Julian dates to Gregorian dates occurred. Default is
     * 00:00:00 local time, October 15, 1582. Previous to
     * this time and date will be Julian dates.
     * @return the Gregorian cutover time for this calendar.
     */
    public final Date getGregorianChange()
    {
        return new Date(gregorianCutover);
    }

    private static final int julianDayToDayOfWeek(long julian)
    {
        // If julian is negative, then julian%7 will be negative, so we adjust
        // accordingly.  We add 1 because Julian day 0 is Monday.
        int dayOfWeek = (int)((julian + 1) % 7);
        return dayOfWeek + ((dayOfWeek < 0) ? (7 + SUNDAY) : SUNDAY);
    }

    /**
     * Convert the time as milliseconds to the "big" fields.  Millis must be
     * given as local wall millis to get the correct local day.  For example,
     * if it is 11:30 pm Standard, and DST is in effect, the correct DST millis
     * must be passed in to get the right date.
     *
     * Fields that are completed by this method: ERA, YEAR, MONTH, DATE,
     * DAY_OF_WEEK, DAY_OF_YEAR, WEEK_OF_YEAR, WEEK_OF_MONTH,
     * DAY_OF_WEEK_IN_MONTH.
     */
    private final void timeToFields(long theTime)
    {
        int year, month, date, dayOfWeek, dayOfYear, weekCount, era = AD;

        //---------------------------------------------------------------------
        // BEGIN modified caldat()
        //---------------------------------------------------------------------
        // The following variable names are somewhat cryptic. Unfortunately,
        // they are from the original program cited above, and no explanation
        // for their meaning is given. Given that the algorithm is cryptic too,
        // perhaps it doesn't matter...
        long ja, jb, jd;
        long jc, je; // changed from int to fix number overflow problem.

        long julian = millisToJulianDay(theTime);

        if (theTime >= gregorianCutover)
        {
            long jalpha = (long) (((double) (julian - 1867216) - 0.25)
                                  * INV1);                       /*ibm.7853*/
            ja = julian + 1 + jalpha - (long) (0.25 * jalpha);
        }
        else
        {
            ja = julian;
        }
        jb = ja + 1524;
        jc = (long) Math.floor(6680.0 + ((double) (jb - 2439870) - 122.1)
                               * INV2);                          /*ibm.7853*/
        jd = (long) Math.floor(365*jc + (0.25 * jc));
        je = (long) ((jb-jd) * INV3);                            /*ibm.7853*/
        date = (int) (jb-jd-(long) (30.6001 * je));
        month = (int) je - 1;
        if (month > 12)
            month -= 12;

        year = (int) (jc-4715);
        if (month > 2)
            --year;
        if (year <= 0)
        {
            era = BC;
            year = 1-year;
        }
        //---------------------------------------------------------------------
        // END modified caldat()
        //---------------------------------------------------------------------

        internalSet(ERA, era);
        internalSet(YEAR, year);
        internalSet(MONTH, month-1); // 0-based
        internalSet(DATE, date);

        dayOfWeek = julianDayToDayOfWeek(julian);
        internalSet(DAY_OF_WEEK, dayOfWeek); // CLH, 8-7-96

        if (isLeapYear(year))
            dayOfYear = LEAP_NUM_DAYS[month-1] + date; // month: 0-based
        else
            dayOfYear = NUM_DAYS[month-1] + date; // month: 0-based
        internalSet(DAY_OF_YEAR, dayOfYear);

        internalSet(WEEK_OF_YEAR, weekNumber(dayOfYear, dayOfWeek));
        internalSet(WEEK_OF_MONTH, weekNumber(date, dayOfWeek));

        internalSet(DAY_OF_WEEK_IN_MONTH, (date-1) / 7 + 1);
    }

    /**
     * Return the week number of a day, within a period. This may be the week number in
     * a year, or the week number in a month. Usually this will be a value >= 1, but if
     * some initial days of the period are excluded from week 1, because
     * minimalDaysInFirstWeek is > 1, then the week number will be zero for those
     * initial days. Requires the day of week for the given date in order to determine
     * the day of week of the first day of the period.
     *
     * @param dayOfPeriod  Day-of-year or day-of-month. Should be 1 for first day of period.
     * @param day   Day-of-week for given dayOfPeriod. 1-based with 1=Sunday.
     * @return      Week number, one-based, or zero if the day falls in part of the
     *              month before the first week, when there are days before the first
     *              week because the minimum days in the first week is more than one.
     */
    private int weekNumber(int dayOfPeriod, int dayOfWeek)
    {
        // Determine the day of the week of the first day of the period
        // in question (either a year or a month).  Zero represents the
        // first day of the week on this calendar.
        int periodStartDayOfWeek = (dayOfWeek - getFirstDayOfWeek() - dayOfPeriod + 1) % 7;
        if (periodStartDayOfWeek < 0) periodStartDayOfWeek += 7;

        // Compute the week number.  Initially, ignore the first week, which
        // may be fractional (or may not be).  We add periodStartDayOfWeek in
        // order to fill out the first week, if it is fractional.
        int weekNo = (dayOfPeriod + periodStartDayOfWeek - 1)/7;

        // If the first week is long enough, then count it.  If
        // the minimal days in the first week is one, or if the period start
        // is zero, we always increment weekNo.
        if ((7 - periodStartDayOfWeek) >= getMinimalDaysInFirstWeek()) ++weekNo;

        return weekNo;
    }

    /**
     * Determines if the given year is a leap year. Returns true if the
     * given year is a leap year.
     * @param year the given year.
     * @return true if the given year is a leap year; false otherwise.
     */
    public boolean isLeapYear(int year)
    {
        // Compute the rough millis for the year.  We only need this number to be
        // good enough to compare it against JULIAN_ONSET.
        long equivalent_millis = (long)((year - 1970) * 365.2422 * millisPerDay);

        // No leap years before onset of Julian calendar
        if (equivalent_millis < JULIAN_ONSET)
            return false;

        return (equivalent_millis > gregorianCutover) ?
            ((year%4 == 0) && ((year%100 != 0) || (year%400 == 0))) : // Gregorian
            (year%4 == 0); // Julian
    }

    /**
     * Overrides Calendar
     * Converts UTC as milliseconds to time field values.
     * The time is <em>not</em>
     * recomputed first; to recompute the time, then the fields, call the
     * <code>complete</code> method.
     * @see Calendar#complete
     */
    protected void computeFields()
    {
        int gmtOffset = getTimeZone().getRawOffset();
        long localMillis = time + gmtOffset;

        // Time to fields takes the wall millis (Standard or DST).
        timeToFields(localMillis);

        int era = internalGet(ERA);
        int year = internalGet(YEAR);
        int month = internalGet(MONTH);
        int date = internalGet(DATE);
        int dayOfWeek = internalGet(DAY_OF_WEEK);

        long days = (long) (localMillis / millisPerDay);
        int millisInDay = (int) (localMillis - (days * millisPerDay));
        if (millisInDay < 0) millisInDay += millisPerDay;

        // Call getOffset() to get the TimeZone offset.  The millisInDay value must
        // be standard local millis.
        int dstOffset = getTimeZone().getOffset(era,year,month,date,dayOfWeek,millisInDay) -
            gmtOffset;

        // Adjust our millisInDay for DST, if necessary.
        millisInDay += dstOffset;

        // If DST has pushed us into the next day, we must call timeToFields() again.
        // This happens in DST between 12:00 am and 1:00 am every day.  The call to
        // timeToFields() will give the wrong day, since the Standard time is in the
        // previous day.
        if (millisInDay >= millisPerDay)
        {
            millisInDay -= millisPerDay;
            localMillis += dstOffset;
            timeToFields(localMillis);
        }

        // Fill in all time-related fields based on millisInDay.  Call internalSet()
        // so as not to perturb flags.
        internalSet(MILLISECOND, millisInDay % 1000);
        millisInDay /= 1000;
        internalSet(SECOND, millisInDay % 60);
        millisInDay /= 60;
        internalSet(MINUTE, millisInDay % 60);
        millisInDay /= 60;
        internalSet(HOUR_OF_DAY, millisInDay);
        internalSet(AM_PM, millisInDay / 12);
        internalSet(HOUR, millisInDay % 12);

        internalSet(ZONE_OFFSET, gmtOffset);
        internalSet(DST_OFFSET, dstOffset);

    // Careful here: We are manually setting the time stamps[] flags to

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?