/*
* Copyright 2001-2005 Stephen Colebourne
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.joda.time.chrono;
import org.joda.time.Chronology;
import org.joda.time.DateTimeConstants;
/**
* Abstract implementation of a calendar system based around fixed length months.
* <p>
* As the month length is fixed various calculations can be optimised.
* This implementation assumes any additional days after twelve
* months fall into a thirteenth month.
* <p>
* BasicFixedMonthChronology is thread-safe and immutable, and all
* subclasses must be as well.
*
* @author Brian S O'Neill
* @author Stephen Colebourne
* @since 1.2, refactored from CopticChronology
*/
abstract class BasicFixedMonthChronology extends BasicChronology {
/** Serialization lock */
private static final long serialVersionUID = 261387371998L;
/** The length of the month. */
static final int MONTH_LENGTH = 30;
/** The typical millis per year. */
static final long MILLIS_PER_YEAR =
(long) (365.25 * DateTimeConstants.MILLIS_PER_DAY);
/** The length of the month in millis. */
static final long MILLIS_PER_MONTH = ((long) MONTH_LENGTH) * DateTimeConstants.MILLIS_PER_DAY;
//-----------------------------------------------------------------------
/**
* Restricted constructor.
*
* @param base the base chronology
* @param param the init parameter
* @param minDaysInFirstWeek the minimum days in the first week
*/
BasicFixedMonthChronology(Chronology base, Object param, int minDaysInFirstWeek) {
super(base, param, minDaysInFirstWeek);
}
//-----------------------------------------------------------------------
long setYear(long instant, int year) {
// optimsed implementation of set, due to fixed months
int thisYear = getYear(instant);
int dayOfYear = getDayOfYear(instant, thisYear);
int millisOfDay = getMillisOfDay(instant);
if (dayOfYear > 365) {
// Current year is leap, and day is leap.
if (!isLeapYear(year)) {
// Moving to a non-leap year, leap day doesn't exist.
dayOfYear--;
}
}
instant = getYearMonthDayMillis(year, 1, dayOfYear);
instant += millisOfDay;
return instant;
}
//-----------------------------------------------------------------------
long getYearDifference(long minuendInstant, long subtrahendInstant) {
// optimsed implementation of getDifference, due to fixed months
int minuendYear = getYear(minuendInstant);
int subtrahendYear = getYear(subtrahendInstant);
// Inlined remainder method to avoid duplicate calls to get.
long minuendRem = minuendInstant - getYearMillis(minuendYear);
long subtrahendRem = subtrahendInstant - getYearMillis(subtrahendYear);
int difference = minuendYear - subtrahendYear;
if (minuendRem < subtrahendRem) {
difference--;
}
return difference;
}
//-----------------------------------------------------------------------
long getTotalMillisByYearMonth(int year, int month) {
return ((month - 1) * MILLIS_PER_MONTH);
}
//-----------------------------------------------------------------------
int getDayOfMonth(long millis) {
// optimised for fixed months
return (getDayOfYear(millis) - 1) % MONTH_LENGTH + 1;
}
//-----------------------------------------------------------------------
boolean isLeapYear(int year) {
return (year & 3) == 3;
}
//-----------------------------------------------------------------------
int getDaysInYearMonth(int year, int month) {
return (month != 13) ? MONTH_LENGTH : (isLeapYear(year) ? 6 : 5);
}
//-----------------------------------------------------------------------
int getDaysInMonthMax() {
return MONTH_LENGTH;
}
//-----------------------------------------------------------------------
int getDaysInMonthMax(int month) {
return (month != 13 ? MONTH_LENGTH : 6);
}
//-----------------------------------------------------------------------
int getMonthOfYear(long millis) {
return (getDayOfYear(millis) - 1) / MONTH_LENGTH + 1;
}
//-----------------------------------------------------------------------
int getMonthOfYear(long millis, int year) {
long monthZeroBased = (millis - getYearMillis(year)) / MILLIS_PER_MONTH;
return ((int) monthZeroBased) + 1;
}
//-----------------------------------------------------------------------
int getMaxMonth() {
return 13;
}
//-----------------------------------------------------------------------
long getAverageMillisPerYear() {
return MILLIS_PER_YEAR;
}
//-----------------------------------------------------------------------
long getAverageMillisPerYearDividedByTwo() {
return MILLIS_PER_YEAR / 2;
}
//-----------------------------------------------------------------------
long getAverageMillisPerMonth() {
return MILLIS_PER_MONTH;
}
}