EMMA Coverage Report (generated Tue Oct 28 00:01:11 GMT 2008)
[all classes][org.joda.time.chrono]

COVERAGE SUMMARY FOR SOURCE FILE [BasicMonthOfYearDateTimeField.java]

nameclass, %method, %block, %line, %
BasicMonthOfYearDateTimeField.java100% (1/1)94%  (17/18)72%  (409/571)74%  (78/106)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class BasicMonthOfYearDateTimeField100% (1/1)94%  (17/18)72%  (409/571)74%  (78/106)
readResolve (): Object 0%   (0/1)0%   (0/4)0%   (0/1)
add (long, long): long 100% (1/1)8%   (13/162)11%  (3/28)
add (ReadablePartial, int, int [], int): int [] 100% (1/1)82%  (40/49)78%  (7/9)
BasicMonthOfYearDateTimeField (BasicChronology, int): void 100% (1/1)100% (17/17)100% (5/5)
add (long, int): long 100% (1/1)100% (106/106)100% (23/23)
addWrapField (long, int): long 100% (1/1)100% (12/12)100% (1/1)
get (long): int 100% (1/1)100% (5/5)100% (1/1)
getDifferenceAsLong (long, long): long 100% (1/1)100% (105/105)100% (17/17)
getLeapAmount (long): int 100% (1/1)100% (8/8)100% (1/1)
getLeapDurationField (): DurationField 100% (1/1)100% (4/4)100% (1/1)
getMaximumValue (): int 100% (1/1)100% (3/3)100% (1/1)
getMinimumValue (): int 100% (1/1)100% (2/2)100% (1/1)
getRangeDurationField (): DurationField 100% (1/1)100% (4/4)100% (1/1)
isLeap (long): boolean 100% (1/1)100% (24/24)100% (4/4)
isLenient (): boolean 100% (1/1)100% (2/2)100% (1/1)
remainder (long): long 100% (1/1)100% (6/6)100% (1/1)
roundFloor (long): long 100% (1/1)100% (17/17)100% (3/3)
set (long, int): long 100% (1/1)100% (41/41)100% (7/7)

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 */
16package org.joda.time.chrono;
17 
18import org.joda.time.DateTimeConstants;
19import org.joda.time.DateTimeFieldType;
20import org.joda.time.DateTimeUtils;
21import org.joda.time.DurationField;
22import org.joda.time.ReadablePartial;
23import org.joda.time.field.FieldUtils;
24import 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 */
34class 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
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 readResolve() {
358        return iChronology.monthOfYear();
359    }
360}

[all classes][org.joda.time.chrono]
EMMA 2.0.5312 (C) Vladimir Roubtsov