1 /*
2 * Copyright 2001-2005 Stephen Colebourne
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.joda.time.chrono;
17
18 import org.joda.time.Chronology;
19 import org.joda.time.DateTimeConstants;
20
21 /**
22 * Abstract implementation of a calendar system based around fixed length months.
23 * <p>
24 * As the month length is fixed various calculations can be optimised.
25 * This implementation assumes any additional days after twelve
26 * months fall into a thirteenth month.
27 * <p>
28 * BasicFixedMonthChronology is thread-safe and immutable, and all
29 * subclasses must be as well.
30 *
31 * @author Brian S O'Neill
32 * @author Stephen Colebourne
33 * @since 1.2, refactored from CopticChronology
34 */
35 abstract class BasicFixedMonthChronology extends BasicChronology {
36
37 /** Serialization lock */
38 private static final long serialVersionUID = 261387371998L;
39
40 /** The length of the month. */
41 static final int MONTH_LENGTH = 30;
42
43 /** The typical millis per year. */
44 static final long MILLIS_PER_YEAR =
45 (long) (365.25 * DateTimeConstants.MILLIS_PER_DAY);
46
47 /** The length of the month in millis. */
48 static final long MILLIS_PER_MONTH = ((long) MONTH_LENGTH) * DateTimeConstants.MILLIS_PER_DAY;
49
50 //-----------------------------------------------------------------------
51 /**
52 * Restricted constructor.
53 *
54 * @param base the base chronology
55 * @param param the init parameter
56 * @param minDaysInFirstWeek the minimum days in the first week
57 */
58 BasicFixedMonthChronology(Chronology base, Object param, int minDaysInFirstWeek) {
59 super(base, param, minDaysInFirstWeek);
60 }
61
62 //-----------------------------------------------------------------------
63 long setYear(long instant, int year) {
64 // optimsed implementation of set, due to fixed months
65 int thisYear = getYear(instant);
66 int dayOfYear = getDayOfYear(instant, thisYear);
67 int millisOfDay = getMillisOfDay(instant);
68
69 if (dayOfYear > 365) {
70 // Current year is leap, and day is leap.
71 if (!isLeapYear(year)) {
72 // Moving to a non-leap year, leap day doesn't exist.
73 dayOfYear--;
74 }
75 }
76
77 instant = getYearMonthDayMillis(year, 1, dayOfYear);
78 instant += millisOfDay;
79 return instant;
80 }
81
82 //-----------------------------------------------------------------------
83 long getYearDifference(long minuendInstant, long subtrahendInstant) {
84 // optimsed implementation of getDifference, due to fixed months
85 int minuendYear = getYear(minuendInstant);
86 int subtrahendYear = getYear(subtrahendInstant);
87
88 // Inlined remainder method to avoid duplicate calls to get.
89 long minuendRem = minuendInstant - getYearMillis(minuendYear);
90 long subtrahendRem = subtrahendInstant - getYearMillis(subtrahendYear);
91
92 int difference = minuendYear - subtrahendYear;
93 if (minuendRem < subtrahendRem) {
94 difference--;
95 }
96 return difference;
97 }
98
99 //-----------------------------------------------------------------------
100 long getTotalMillisByYearMonth(int year, int month) {
101 return ((month - 1) * MILLIS_PER_MONTH);
102 }
103
104 //-----------------------------------------------------------------------
105 int getDayOfMonth(long millis) {
106 // optimised for fixed months
107 return (getDayOfYear(millis) - 1) % MONTH_LENGTH + 1;
108 }
109
110 //-----------------------------------------------------------------------
111 boolean isLeapYear(int year) {
112 return (year & 3) == 3;
113 }
114
115 //-----------------------------------------------------------------------
116 int getDaysInYearMonth(int year, int month) {
117 return (month != 13) ? MONTH_LENGTH : (isLeapYear(year) ? 6 : 5);
118 }
119
120 //-----------------------------------------------------------------------
121 int getDaysInMonthMax() {
122 return MONTH_LENGTH;
123 }
124
125 //-----------------------------------------------------------------------
126 int getDaysInMonthMax(int month) {
127 return (month != 13 ? MONTH_LENGTH : 6);
128 }
129
130 //-----------------------------------------------------------------------
131 int getMonthOfYear(long millis) {
132 return (getDayOfYear(millis) - 1) / MONTH_LENGTH + 1;
133 }
134
135 //-----------------------------------------------------------------------
136 int getMonthOfYear(long millis, int year) {
137 long monthZeroBased = (millis - getYearMillis(year)) / MILLIS_PER_MONTH;
138 return ((int) monthZeroBased) + 1;
139 }
140
141 //-----------------------------------------------------------------------
142 int getMaxMonth() {
143 return 13;
144 }
145
146 //-----------------------------------------------------------------------
147 long getAverageMillisPerYear() {
148 return MILLIS_PER_YEAR;
149 }
150
151 //-----------------------------------------------------------------------
152 long getAverageMillisPerYearDividedByTwo() {
153 return MILLIS_PER_YEAR / 2;
154 }
155
156 //-----------------------------------------------------------------------
157 long getAverageMillisPerMonth() {
158 return MILLIS_PER_MONTH;
159 }
160
161 }