View Javadoc

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 }