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 | } |