001: /*
002: * Copyright 2001-2005 Stephen Colebourne
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.joda.time.chrono;
017:
018: import org.joda.time.Chronology;
019: import org.joda.time.DateTimeConstants;
020:
021: /**
022: * Abstract implementation of a calendar system based around fixed length months.
023: * <p>
024: * As the month length is fixed various calculations can be optimised.
025: * This implementation assumes any additional days after twelve
026: * months fall into a thirteenth month.
027: * <p>
028: * BasicFixedMonthChronology is thread-safe and immutable, and all
029: * subclasses must be as well.
030: *
031: * @author Brian S O'Neill
032: * @author Stephen Colebourne
033: * @since 1.2, refactored from CopticChronology
034: */
035: abstract class BasicFixedMonthChronology extends BasicChronology {
036:
037: /** Serialization lock */
038: private static final long serialVersionUID = 261387371998L;
039:
040: /** The length of the month. */
041: static final int MONTH_LENGTH = 30;
042:
043: /** The typical millis per year. */
044: static final long MILLIS_PER_YEAR = (long) (365.25 * DateTimeConstants.MILLIS_PER_DAY);
045:
046: /** The length of the month in millis. */
047: static final long MILLIS_PER_MONTH = ((long) MONTH_LENGTH)
048: * DateTimeConstants.MILLIS_PER_DAY;
049:
050: //-----------------------------------------------------------------------
051: /**
052: * Restricted constructor.
053: *
054: * @param base the base chronology
055: * @param param the init parameter
056: * @param minDaysInFirstWeek the minimum days in the first week
057: */
058: BasicFixedMonthChronology(Chronology base, Object param,
059: int minDaysInFirstWeek) {
060: super (base, param, minDaysInFirstWeek);
061: }
062:
063: //-----------------------------------------------------------------------
064: long setYear(long instant, int year) {
065: // optimsed implementation of set, due to fixed months
066: int this Year = getYear(instant);
067: int dayOfYear = getDayOfYear(instant, this Year);
068: int millisOfDay = getMillisOfDay(instant);
069:
070: if (dayOfYear > 365) {
071: // Current year is leap, and day is leap.
072: if (!isLeapYear(year)) {
073: // Moving to a non-leap year, leap day doesn't exist.
074: dayOfYear--;
075: }
076: }
077:
078: instant = getYearMonthDayMillis(year, 1, dayOfYear);
079: instant += millisOfDay;
080: return instant;
081: }
082:
083: //-----------------------------------------------------------------------
084: long getYearDifference(long minuendInstant, long subtrahendInstant) {
085: // optimsed implementation of getDifference, due to fixed months
086: int minuendYear = getYear(minuendInstant);
087: int subtrahendYear = getYear(subtrahendInstant);
088:
089: // Inlined remainder method to avoid duplicate calls to get.
090: long minuendRem = minuendInstant - getYearMillis(minuendYear);
091: long subtrahendRem = subtrahendInstant
092: - getYearMillis(subtrahendYear);
093:
094: int difference = minuendYear - subtrahendYear;
095: if (minuendRem < subtrahendRem) {
096: difference--;
097: }
098: return difference;
099: }
100:
101: //-----------------------------------------------------------------------
102: long getTotalMillisByYearMonth(int year, int month) {
103: return ((month - 1) * MILLIS_PER_MONTH);
104: }
105:
106: //-----------------------------------------------------------------------
107: int getDayOfMonth(long millis) {
108: // optimised for fixed months
109: return (getDayOfYear(millis) - 1) % MONTH_LENGTH + 1;
110: }
111:
112: //-----------------------------------------------------------------------
113: boolean isLeapYear(int year) {
114: return (year & 3) == 3;
115: }
116:
117: //-----------------------------------------------------------------------
118: int getDaysInYearMonth(int year, int month) {
119: return (month != 13) ? MONTH_LENGTH
120: : (isLeapYear(year) ? 6 : 5);
121: }
122:
123: //-----------------------------------------------------------------------
124: int getDaysInMonthMax() {
125: return MONTH_LENGTH;
126: }
127:
128: //-----------------------------------------------------------------------
129: int getDaysInMonthMax(int month) {
130: return (month != 13 ? MONTH_LENGTH : 6);
131: }
132:
133: //-----------------------------------------------------------------------
134: int getMonthOfYear(long millis) {
135: return (getDayOfYear(millis) - 1) / MONTH_LENGTH + 1;
136: }
137:
138: //-----------------------------------------------------------------------
139: int getMonthOfYear(long millis, int year) {
140: long monthZeroBased = (millis - getYearMillis(year))
141: / MILLIS_PER_MONTH;
142: return ((int) monthZeroBased) + 1;
143: }
144:
145: //-----------------------------------------------------------------------
146: int getMaxMonth() {
147: return 13;
148: }
149:
150: //-----------------------------------------------------------------------
151: long getAverageMillisPerYear() {
152: return MILLIS_PER_YEAR;
153: }
154:
155: //-----------------------------------------------------------------------
156: long getAverageMillisPerYearDividedByTwo() {
157: return MILLIS_PER_YEAR / 2;
158: }
159:
160: //-----------------------------------------------------------------------
161: long getAverageMillisPerMonth() {
162: return MILLIS_PER_MONTH;
163: }
164:
165: }
|