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 Chronology for implementing chronologies based on Gregorian/Julian formulae.
023: * Most of the utility methods required by subclasses are package-private,
024: * reflecting the intention that they be defined in the same package.
025: * <p>
026: * BasicGJChronology is thread-safe and immutable, and all subclasses must
027: * be as well.
028: *
029: * @author Stephen Colebourne
030: * @author Brian S O'Neill
031: * @author Guy Allard
032: * @since 1.2, refactored from CommonGJChronology
033: */
034: abstract class BasicGJChronology extends BasicChronology {
035:
036: /** Serialization lock */
037: private static final long serialVersionUID = 538276888268L;
038:
039: // These arrays are NOT public. We trust ourselves not to alter the array.
040: // They use zero-based array indexes so the that valid range of months is
041: // automatically checked.
042: private static final int[] MIN_DAYS_PER_MONTH_ARRAY = { 31, 28, 31,
043: 30, 31, 30, 31, 31, 30, 31, 30, 31 };
044: private static final int[] MAX_DAYS_PER_MONTH_ARRAY = { 31, 29, 31,
045: 30, 31, 30, 31, 31, 30, 31, 30, 31 };
046: private static final long[] MIN_TOTAL_MILLIS_BY_MONTH_ARRAY;
047: private static final long[] MAX_TOTAL_MILLIS_BY_MONTH_ARRAY;
048: private static final long FEB_29 = (31L + 29 - 1)
049: * DateTimeConstants.MILLIS_PER_DAY;
050:
051: static {
052: MIN_TOTAL_MILLIS_BY_MONTH_ARRAY = new long[12];
053: MAX_TOTAL_MILLIS_BY_MONTH_ARRAY = new long[12];
054:
055: long minSum = 0;
056: long maxSum = 0;
057: for (int i = 0; i < 11; i++) {
058: long millis = MIN_DAYS_PER_MONTH_ARRAY[i]
059: * (long) DateTimeConstants.MILLIS_PER_DAY;
060: minSum += millis;
061: MIN_TOTAL_MILLIS_BY_MONTH_ARRAY[i + 1] = minSum;
062:
063: millis = MAX_DAYS_PER_MONTH_ARRAY[i]
064: * (long) DateTimeConstants.MILLIS_PER_DAY;
065: maxSum += millis;
066: MAX_TOTAL_MILLIS_BY_MONTH_ARRAY[i + 1] = maxSum;
067: }
068: }
069:
070: /**
071: * Constructor.
072: */
073: BasicGJChronology(Chronology base, Object param,
074: int minDaysInFirstWeek) {
075: super (base, param, minDaysInFirstWeek);
076: }
077:
078: //-----------------------------------------------------------------------
079: int getMonthOfYear(long millis, int year) {
080: // Perform a binary search to get the month. To make it go even faster,
081: // compare using ints instead of longs. The number of milliseconds per
082: // year exceeds the limit of a 32-bit int's capacity, so divide by
083: // 1024. No precision is lost (except time of day) since the number of
084: // milliseconds per day contains 1024 as a factor. After the division,
085: // the instant isn't measured in milliseconds, but in units of
086: // (128/125)seconds.
087:
088: int i = (int) ((millis - getYearMillis(year)) >> 10);
089:
090: // There are 86400000 milliseconds per day, but divided by 1024 is
091: // 84375. There are 84375 (128/125)seconds per day.
092:
093: return (isLeapYear(year)) ? ((i < 182 * 84375) ? ((i < 91 * 84375) ? ((i < 31 * 84375) ? 1
094: : (i < 60 * 84375) ? 2 : 3)
095: : ((i < 121 * 84375) ? 4 : (i < 152 * 84375) ? 5 : 6))
096: : ((i < 274 * 84375) ? ((i < 213 * 84375) ? 7
097: : (i < 244 * 84375) ? 8 : 9)
098: : ((i < 305 * 84375) ? 10
099: : (i < 335 * 84375) ? 11 : 12)))
100: : ((i < 181 * 84375) ? ((i < 90 * 84375) ? ((i < 31 * 84375) ? 1
101: : (i < 59 * 84375) ? 2 : 3)
102: : ((i < 120 * 84375) ? 4
103: : (i < 151 * 84375) ? 5 : 6))
104: : ((i < 273 * 84375) ? ((i < 212 * 84375) ? 7
105: : (i < 243 * 84375) ? 8 : 9)
106: : ((i < 304 * 84375) ? 10
107: : (i < 334 * 84375) ? 11 : 12)));
108: }
109:
110: //-----------------------------------------------------------------------
111: /**
112: * Gets the number of days in the specified month and year.
113: *
114: * @param year the year
115: * @param month the month
116: * @return the number of days
117: */
118: int getDaysInYearMonth(int year, int month) {
119: if (isLeapYear(year)) {
120: return MAX_DAYS_PER_MONTH_ARRAY[month - 1];
121: } else {
122: return MIN_DAYS_PER_MONTH_ARRAY[month - 1];
123: }
124: }
125:
126: //-----------------------------------------------------------------------
127: int getDaysInMonthMax(int month) {
128: return MAX_DAYS_PER_MONTH_ARRAY[month - 1];
129: }
130:
131: //-----------------------------------------------------------------------
132: int getDaysInMonthMaxForSet(long instant, int value) {
133: return (value > 28 ? getDaysInMonthMax(instant) : 28);
134: }
135:
136: //-----------------------------------------------------------------------
137: long getTotalMillisByYearMonth(int year, int month) {
138: if (isLeapYear(year)) {
139: return MAX_TOTAL_MILLIS_BY_MONTH_ARRAY[month - 1];
140: } else {
141: return MIN_TOTAL_MILLIS_BY_MONTH_ARRAY[month - 1];
142: }
143: }
144:
145: //-----------------------------------------------------------------------
146: long getYearDifference(long minuendInstant, long subtrahendInstant) {
147: int minuendYear = getYear(minuendInstant);
148: int subtrahendYear = getYear(subtrahendInstant);
149:
150: // Inlined remainder method to avoid duplicate calls to get.
151: long minuendRem = minuendInstant - getYearMillis(minuendYear);
152: long subtrahendRem = subtrahendInstant
153: - getYearMillis(subtrahendYear);
154:
155: // Balance leap year differences on remainders.
156: if (subtrahendRem >= FEB_29) {
157: if (isLeapYear(subtrahendYear)) {
158: if (!isLeapYear(minuendYear)) {
159: subtrahendRem -= DateTimeConstants.MILLIS_PER_DAY;
160: }
161: } else if (minuendRem >= FEB_29 && isLeapYear(minuendYear)) {
162: minuendRem -= DateTimeConstants.MILLIS_PER_DAY;
163: }
164: }
165:
166: int difference = minuendYear - subtrahendYear;
167: if (minuendRem < subtrahendRem) {
168: difference--;
169: }
170: return difference;
171: }
172:
173: //-----------------------------------------------------------------------
174: long setYear(long instant, int year) {
175: int this Year = getYear(instant);
176: int dayOfYear = getDayOfYear(instant, this Year);
177: int millisOfDay = getMillisOfDay(instant);
178:
179: if (dayOfYear > (31 + 28)) { // after Feb 28
180: if (isLeapYear(this Year)) {
181: // Current date is Feb 29 or later.
182: if (!isLeapYear(year)) {
183: // Moving to a non-leap year, Feb 29 does not exist.
184: dayOfYear--;
185: }
186: } else {
187: // Current date is Mar 01 or later.
188: if (isLeapYear(year)) {
189: // Moving to a leap year, account for Feb 29.
190: dayOfYear++;
191: }
192: }
193: }
194:
195: instant = getYearMonthDayMillis(year, 1, dayOfYear);
196: instant += millisOfDay;
197:
198: return instant;
199: }
200:
201: }
|