1 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 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 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 public boolean isLenient() { 59 return false; 60 } 61 62 71 public int get(long instant) { 72 return iChronology.getMonthOfYear(instant); 73 } 74 75 91 public long add(long instant, int months) { 92 if (months == 0) { 93 return instant; } 95 long timePart = iChronology.getMillisOfDay(instant); 99 int thisYear = iChronology.getYear(instant); 104 int thisMonth = iChronology.getMonthOfYear(instant, thisYear); 105 int yearToUse; 111 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 if (remMonthToUse == 0) { 122 remMonthToUse = iMax; 123 } 124 monthToUse = iMax - remMonthToUse + 1; 125 if (monthToUse == 1) { 127 yearToUse += 1; 128 } 129 } 130 133 int dayToUse = iChronology.getDayOfMonth(instant, thisYear, thisMonth); 137 int maxDay = iChronology.getDaysInYearMonth(yearToUse, monthToUse); 138 if (dayToUse > maxDay) { 139 dayToUse = maxDay; 140 } 141 long datePart = 145 iChronology.getYearMonthDayMillis(yearToUse, monthToUse, dayToUse); 146 return datePart + timePart; 147 } 148 149 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 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 public int[] add(ReadablePartial partial, int fieldIndex, int[] values, int valueToAdd) { 204 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 231 public long addWrapField(long instant, int months) { 232 return set(instant, FieldUtils.getWrappedValue(get(instant), months, MIN, iMax)); 233 } 234 235 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 int minuendDom = iChronology.getDayOfMonth 251 (minuendInstant, minuendYear, minuendMonth); 252 if (minuendDom == iChronology.getDaysInYearMonth(minuendYear, minuendMonth)) { 253 int subtrahendDom = iChronology.getDayOfMonth 255 (subtrahendInstant, subtrahendYear, subtrahendMonth); 256 if (subtrahendDom > minuendDom) { 257 subtrahendInstant = iChronology.dayOfMonth().set(subtrahendInstant, minuendDom); 261 } 262 } 263 264 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 291 public long set(long instant, int month) { 292 FieldUtils.verifyValueBounds(this, month, MIN, iMax); 293 int thisYear = iChronology.getYear(instant); 295 int thisDom = iChronology.getDayOfMonth(instant, thisYear); 297 int maxDom = iChronology.getDaysInYearMonth(thisYear, month); 298 if (thisDom > maxDom) { 299 thisDom = maxDom; 301 } 302 return iChronology.getYearMonthDayMillis(thisYear, month, thisDom) + 304 iChronology.getMillisOfDay(instant); 305 } 306 307 public DurationField getRangeDurationField() { 309 return iChronology.years(); 310 } 311 312 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 public int getLeapAmount(long instant) { 323 return isLeap(instant) ? 1 : 0; 324 } 325 326 public DurationField getLeapDurationField() { 328 return iChronology.days(); 329 } 330 331 public int getMinimumValue() { 333 return MIN; 334 } 335 336 public int getMaximumValue() { 338 return iMax; 339 } 340 341 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 public long remainder(long instant) { 350 return instant - roundFloor(instant); 351 } 352 353 357 private Object readResolve() { 358 return iChronology.monthOfYear(); 359 } 360 } 361 | Popular Tags |