1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
28
29
30
31
32
33
34 class BasicMonthOfYearDateTimeField extends ImpreciseDateTimeField {
35
36
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
47
48
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
65
66
67
68
69
70
71 public int get(long instant) {
72 return iChronology.getMonthOfYear(instant);
73 }
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91 public long add(long instant, int months) {
92 if (months == 0) {
93 return instant;
94 }
95
96
97
98 long timePart = iChronology.getMillisOfDay(instant);
99
100
101
102
103 int thisYear = iChronology.getYear(instant);
104 int thisMonth = iChronology.getMonthOfYear(instant, thisYear);
105
106
107
108
109
110 int yearToUse;
111
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
121 if (remMonthToUse == 0) {
122 remMonthToUse = iMax;
123 }
124 monthToUse = iMax - remMonthToUse + 1;
125
126 if (monthToUse == 1) {
127 yearToUse += 1;
128 }
129 }
130
131
132
133
134
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
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
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
205
206 if (valueToAdd == 0) {
207 return values;
208 }
209 if (partial.size() > 0 && partial.getFieldType(0).equals(DateTimeFieldType.monthOfYear()) && fieldIndex == 0) {
210
211 int curMonth0 = partial.getValue(0) - 1;
212 int newMonth = ((curMonth0 + (valueToAdd % 12) + 12) % 12) + 1;
213 return set(partial, 0, values, newMonth);
214 }
215 if (DateTimeUtils.isContiguous(partial)) {
216 long instant = 0L;
217 for (int i = 0, isize = partial.size(); i < isize; i++) {
218 instant = partial.getFieldType(i).getField(iChronology).set(instant, values[i]);
219 }
220 instant = add(instant, valueToAdd);
221 return iChronology.get(partial, instant);
222 } else {
223 return super.add(partial, fieldIndex, values, valueToAdd);
224 }
225 }
226
227
228
229
230
231
232
233
234
235
236
237 public long addWrapField(long instant, int months) {
238 return set(instant, FieldUtils.getWrappedValue(get(instant), months, MIN, iMax));
239 }
240
241
242 public long getDifferenceAsLong(long minuendInstant, long subtrahendInstant) {
243 if (minuendInstant < subtrahendInstant) {
244 return -getDifference(subtrahendInstant, minuendInstant);
245 }
246
247 int minuendYear = iChronology.getYear(minuendInstant);
248 int minuendMonth = iChronology.getMonthOfYear(minuendInstant, minuendYear);
249 int subtrahendYear = iChronology.getYear(subtrahendInstant);
250 int subtrahendMonth = iChronology.getMonthOfYear(subtrahendInstant, subtrahendYear);
251
252 long difference = (minuendYear - subtrahendYear) * ((long) iMax) + minuendMonth - subtrahendMonth;
253
254
255
256 int minuendDom = iChronology.getDayOfMonth
257 (minuendInstant, minuendYear, minuendMonth);
258 if (minuendDom == iChronology.getDaysInYearMonth(minuendYear, minuendMonth)) {
259
260 int subtrahendDom = iChronology.getDayOfMonth
261 (subtrahendInstant, subtrahendYear, subtrahendMonth);
262 if (subtrahendDom > minuendDom) {
263
264
265
266 subtrahendInstant = iChronology.dayOfMonth().set(subtrahendInstant, minuendDom);
267 }
268 }
269
270
271 long minuendRem = minuendInstant
272 - iChronology.getYearMonthMillis(minuendYear, minuendMonth);
273 long subtrahendRem = subtrahendInstant
274 - iChronology.getYearMonthMillis(subtrahendYear, subtrahendMonth);
275
276 if (minuendRem < subtrahendRem) {
277 difference--;
278 }
279
280 return difference;
281 }
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297 public long set(long instant, int month) {
298 FieldUtils.verifyValueBounds(this, month, MIN, iMax);
299
300 int thisYear = iChronology.getYear(instant);
301
302 int thisDom = iChronology.getDayOfMonth(instant, thisYear);
303 int maxDom = iChronology.getDaysInYearMonth(thisYear, month);
304 if (thisDom > maxDom) {
305
306 thisDom = maxDom;
307 }
308
309 return iChronology.getYearMonthDayMillis(thisYear, month, thisDom) +
310 iChronology.getMillisOfDay(instant);
311 }
312
313
314 public DurationField getRangeDurationField() {
315 return iChronology.years();
316 }
317
318
319 public boolean isLeap(long instant) {
320 int thisYear = iChronology.getYear(instant);
321 if (iChronology.isLeapYear(thisYear)) {
322 return (iChronology.getMonthOfYear(instant, thisYear) == iLeapMonth);
323 }
324 return false;
325 }
326
327
328 public int getLeapAmount(long instant) {
329 return isLeap(instant) ? 1 : 0;
330 }
331
332
333 public DurationField getLeapDurationField() {
334 return iChronology.days();
335 }
336
337
338 public int getMinimumValue() {
339 return MIN;
340 }
341
342
343 public int getMaximumValue() {
344 return iMax;
345 }
346
347
348 public long roundFloor(long instant) {
349 int year = iChronology.getYear(instant);
350 int month = iChronology.getMonthOfYear(instant, year);
351 return iChronology.getYearMonthMillis(year, month);
352 }
353
354
355 public long remainder(long instant) {
356 return instant - roundFloor(instant);
357 }
358
359
360
361
362
363 private Object readResolve() {
364 return iChronology.monthOfYear();
365 }
366 }