KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > joda > time > chrono > BasicMonthOfYearDateTimeField


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.DateTimeConstants;
19 import org.joda.time.DateTimeFieldType;
20 import org.joda.time.DateTimeUtils;
21 import org.joda.time.DurationField;
22 import org.joda.time.ReadablePartial;
23 import org.joda.time.field.FieldUtils;
24 import org.joda.time.field.ImpreciseDateTimeField;
25
26 /**
27  * Provides time calculations for the month of the year component of time.
28  *
29  * @author Guy Allard
30  * @author Stephen Colebourne
31  * @author Brian S O'Neill
32  * @since 1.2, refactored from GJMonthOfYearDateTimeField
33  */

34 class BasicMonthOfYearDateTimeField extends ImpreciseDateTimeField {
35
36     /** Serialization version */
37     private static final long serialVersionUID = -8258715387168736L;
38
39     private static final int MIN = DateTimeConstants.JANUARY;
40
41     private final BasicChronology iChronology;
42     private final int iMax;
43     private final int iLeapMonth;
44
45     /**
46      * Restricted constructor.
47      *
48      * @param leapMonth the month of year that leaps
49      */

50     BasicMonthOfYearDateTimeField(BasicChronology chronology, int leapMonth) {
51         super(DateTimeFieldType.monthOfYear(), chronology.getAverageMillisPerMonth());
52         iChronology = chronology;
53         iMax = iChronology.getMaxMonth();
54         iLeapMonth = leapMonth;
55     }
56
57     //-----------------------------------------------------------------------
58
public boolean isLenient() {
59         return false;
60     }
61
62     //-----------------------------------------------------------------------
63
/**
64      * Get the Month component of the specified time instant.
65      *
66      * @see org.joda.time.DateTimeField#get(long)
67      * @see org.joda.time.ReadableDateTime#getMonthOfYear()
68      * @param instant the time instant in millis to query.
69      * @return the month extracted from the input.
70      */

71     public int get(long instant) {
72         return iChronology.getMonthOfYear(instant);
73     }
74
75     //-----------------------------------------------------------------------
76
/**
77      * Add the specified month to the specified time instant.
78      * The amount added may be negative.<p>
79      * If the new month has less total days than the specified
80      * day of the month, this value is coerced to the nearest
81      * sane value. e.g.<p>
82      * 07-31 - (1 month) = 06-30<p>
83      * 03-31 - (1 month) = 02-28 or 02-29 depending<p>
84      *
85      * @see org.joda.time.DateTimeField#add
86      * @see org.joda.time.ReadWritableDateTime#addMonths(int)
87      * @param instant the time instant in millis to update.
88      * @param months the months to add (can be negative).
89      * @return the updated time instant.
90      */

91     public long add(long instant, int months) {
92         if (months == 0) {
93             return instant; // the easy case
94
}
95         //
96
// Save time part first.
97
//
98
long timePart = iChronology.getMillisOfDay(instant);
99         //
100
//
101
// Get this year and month.
102
//
103
int thisYear = iChronology.getYear(instant);
104         int thisMonth = iChronology.getMonthOfYear(instant, thisYear);
105         // ----------------------------------------------------------
106
//
107
// Do not refactor without careful consideration.
108
// Order of calculation is important.
109
//
110
int yearToUse;
111         // Initially, monthToUse is zero-based
112
int monthToUse = thisMonth - 1 + months;
113         if (monthToUse >= 0) {
114             yearToUse = thisYear + (monthToUse / iMax);
115             monthToUse = (monthToUse % iMax) + 1;
116         } else {
117             yearToUse = thisYear + (monthToUse / iMax) - 1;
118             monthToUse = Math.abs(monthToUse);
119             int remMonthToUse = monthToUse % iMax;
120             // Take care of the boundary condition
121
if (remMonthToUse == 0) {
122                 remMonthToUse = iMax;
123             }
124             monthToUse = iMax - remMonthToUse + 1;
125             // Take care of the boundary condition
126
if (monthToUse == 1) {
127                 yearToUse += 1;
128             }
129         }
130         // End of do not refactor.
131
// ----------------------------------------------------------
132

133         //
134
// Quietly force DOM to nearest sane value.
135
//
136
int dayToUse = iChronology.getDayOfMonth(instant, thisYear, thisMonth);
137         int maxDay = iChronology.getDaysInYearMonth(yearToUse, monthToUse);
138         if (dayToUse > maxDay) {
139             dayToUse = maxDay;
140         }
141         //
142
// get proper date part, and return result
143
//
144
long datePart =
145             iChronology.getYearMonthDayMillis(yearToUse, monthToUse, dayToUse);
146         return datePart + timePart;
147     }
148
149     //-----------------------------------------------------------------------
150
public long add(long instant, long months) {
151         int i_months = (int)months;
152         if (i_months == months) {
153             return add(instant, i_months);
154         }
155
156         // Copied from add(long, int) and modified slightly:
157

158         long timePart = iChronology.getMillisOfDay(instant);
159
160         int thisYear = iChronology.getYear(instant);
161         int thisMonth = iChronology.getMonthOfYear(instant, thisYear);
162
163         long yearToUse;
164         long monthToUse = thisMonth - 1 + months;
165         if (monthToUse >= 0) {
166             yearToUse = thisYear + (monthToUse / iMax);
167             monthToUse = (monthToUse % iMax) + 1;
168         } else {
169             yearToUse = thisYear + (monthToUse / iMax) - 1;
170             monthToUse = Math.abs(monthToUse);
171             int remMonthToUse = (int)(monthToUse % iMax);
172             if (remMonthToUse == 0) {
173                 remMonthToUse = iMax;
174             }
175             monthToUse = iMax - remMonthToUse + 1;
176             if (monthToUse == 1) {
177                 yearToUse += 1;
178             }
179         }
180
181         if (yearToUse < iChronology.getMinYear() ||
182             yearToUse > iChronology.getMaxYear()) {
183
184             throw new IllegalArgumentException JavaDoc
185                 ("Magnitude of add amount is too large: " + months);
186         }
187
188         int i_yearToUse = (int)yearToUse;
189         int i_monthToUse = (int)monthToUse;
190
191         int dayToUse = iChronology.getDayOfMonth(instant, thisYear, thisMonth);
192         int maxDay = iChronology.getDaysInYearMonth(i_yearToUse, i_monthToUse);
193         if (dayToUse > maxDay) {
194             dayToUse = maxDay;
195         }
196
197         long datePart =
198             iChronology.getYearMonthDayMillis(i_yearToUse, i_monthToUse, dayToUse);
199         return datePart + timePart;
200     }
201
202     //-----------------------------------------------------------------------
203
public int[] add(ReadablePartial partial, int fieldIndex, int[] values, int valueToAdd) {
204         // overridden as superclass algorithm can't handle
205
// 2004-02-29 + 48 months -> 2008-02-29 type dates
206
if (valueToAdd == 0) {
207             return values;
208         }
209         if (DateTimeUtils.isContiguous(partial)) {
210             long instant = 0L;
211             for (int i = 0, isize = partial.size(); i < isize; i++) {
212                 instant = partial.getFieldType(i).getField(iChronology).set(instant, values[i]);
213             }
214             instant = add(instant, valueToAdd);
215             return iChronology.get(partial, instant);
216         } else {
217             return super.add(partial, fieldIndex, values, valueToAdd);
218         }
219     }
220
221     //-----------------------------------------------------------------------
222
/**
223      * Add to the Month component of the specified time instant
224      * wrapping around within that component if necessary.
225      *
226      * @see org.joda.time.DateTimeField#addWrapField
227      * @param instant the time instant in millis to update.
228      * @param months the months to add (can be negative).
229      * @return the updated time instant.
230      */

231     public long addWrapField(long instant, int months) {
232         return set(instant, FieldUtils.getWrappedValue(get(instant), months, MIN, iMax));
233     }
234
235     //-----------------------------------------------------------------------
236
public long getDifferenceAsLong(long minuendInstant, long subtrahendInstant) {
237         if (minuendInstant < subtrahendInstant) {
238             return -getDifference(subtrahendInstant, minuendInstant);
239         }
240
241         int minuendYear = iChronology.getYear(minuendInstant);
242         int minuendMonth = iChronology.getMonthOfYear(minuendInstant, minuendYear);
243         int subtrahendYear = iChronology.getYear(subtrahendInstant);
244         int subtrahendMonth = iChronology.getMonthOfYear(subtrahendInstant, subtrahendYear);
245
246         long difference = (minuendYear - subtrahendYear) * ((long) iMax) + minuendMonth - subtrahendMonth;
247
248         // Before adjusting for remainder, account for special case of add
249
// where the day-of-month is forced to the nearest sane value.
250
int minuendDom = iChronology.getDayOfMonth
251             (minuendInstant, minuendYear, minuendMonth);
252         if (minuendDom == iChronology.getDaysInYearMonth(minuendYear, minuendMonth)) {
253             // Last day of the minuend month...
254
int subtrahendDom = iChronology.getDayOfMonth
255                 (subtrahendInstant, subtrahendYear, subtrahendMonth);
256             if (subtrahendDom > minuendDom) {
257                 // ...and day of subtrahend month is larger.
258
// Note: This works fine, but it ideally shouldn't invoke other
259
// fields from within a field.
260
subtrahendInstant = iChronology.dayOfMonth().set(subtrahendInstant, minuendDom);
261             }
262         }
263
264         // Inlined remainder method to avoid duplicate calls.
265
long minuendRem = minuendInstant
266             - iChronology.getYearMonthMillis(minuendYear, minuendMonth);
267         long subtrahendRem = subtrahendInstant
268             - iChronology.getYearMonthMillis(subtrahendYear, subtrahendMonth);
269
270         if (minuendRem < subtrahendRem) {
271             difference--;
272         }
273
274         return difference;
275     }
276
277     //-----------------------------------------------------------------------
278
/**
279      * Set the Month component of the specified time instant.<p>
280      * If the new month has less total days than the specified
281      * day of the month, this value is coerced to the nearest
282      * sane value. e.g.<p>
283      * 07-31 to month 6 = 06-30<p>
284      * 03-31 to month 2 = 02-28 or 02-29 depending<p>
285      *
286      * @param instant the time instant in millis to update.
287      * @param month the month (1,12) to update the time to.
288      * @return the updated time instant.
289      * @throws IllegalArgumentException if month is invalid
290      */

291     public long set(long instant, int month) {
292         FieldUtils.verifyValueBounds(this, month, MIN, iMax);
293         //
294
int thisYear = iChronology.getYear(instant);
295         //
296
int thisDom = iChronology.getDayOfMonth(instant, thisYear);
297         int maxDom = iChronology.getDaysInYearMonth(thisYear, month);
298         if (thisDom > maxDom) {
299             // Quietly force DOM to nearest sane value.
300
thisDom = maxDom;
301         }
302         // Return newly calculated millis value
303
return iChronology.getYearMonthDayMillis(thisYear, month, thisDom) +
304             iChronology.getMillisOfDay(instant);
305     }
306
307     //-----------------------------------------------------------------------
308
public DurationField getRangeDurationField() {
309         return iChronology.years();
310     }
311
312     //-----------------------------------------------------------------------
313
public boolean isLeap(long instant) {
314         int thisYear = iChronology.getYear(instant);
315         if (iChronology.isLeapYear(thisYear)) {
316             return (iChronology.getMonthOfYear(instant, thisYear) == iLeapMonth);
317         }
318         return false;
319     }
320
321     //-----------------------------------------------------------------------
322
public int getLeapAmount(long instant) {
323         return isLeap(instant) ? 1 : 0;
324     }
325
326     //-----------------------------------------------------------------------
327
public DurationField getLeapDurationField() {
328         return iChronology.days();
329     }
330
331     //-----------------------------------------------------------------------
332
public int getMinimumValue() {
333         return MIN;
334     }
335
336     //-----------------------------------------------------------------------
337
public int getMaximumValue() {
338         return iMax;
339     }
340
341     //-----------------------------------------------------------------------
342
public long roundFloor(long instant) {
343         int year = iChronology.getYear(instant);
344         int month = iChronology.getMonthOfYear(instant, year);
345         return iChronology.getYearMonthMillis(year, month);
346     }
347
348     //-----------------------------------------------------------------------
349
public long remainder(long instant) {
350         return instant - roundFloor(instant);
351     }
352
353     //-----------------------------------------------------------------------
354
/**
355      * Serialization singleton
356      */

357     private Object JavaDoc readResolve() {
358         return iChronology.monthOfYear();
359     }
360 }
361
Popular Tags