001 /* 002 * Copyright 2001-2005 Stephen Colebourne 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.joda.time.field; 017 018 import org.joda.time.Chronology; 019 import org.joda.time.DateTimeField; 020 import org.joda.time.DateTimeFieldType; 021 import org.joda.time.IllegalFieldValueException; 022 023 /** 024 * Wraps another field such that a certain value is skipped. 025 * <p> 026 * This is most useful for years where you want to skip zero, so the 027 * sequence runs ...,2,1,-1,-2,... 028 * <p> 029 * SkipDateTimeField is thread-safe and immutable. 030 * 031 * @author Brian S O'Neill 032 * @author Stephen Colebourne 033 * @since 1.0 034 */ 035 public final class SkipDateTimeField extends DelegatedDateTimeField { 036 037 /** Serialization version. */ 038 private static final long serialVersionUID = -8869148464118507846L; 039 040 /** The chronology to wrap. */ 041 private final Chronology iChronology; 042 /** The value to skip. */ 043 private final int iSkip; 044 /** The calculated minimum value. */ 045 private transient int iMinValue; 046 047 /** 048 * Constructor that skips zero. 049 * 050 * @param chronology the chronoogy to use 051 * @param field the field to skip zero on 052 */ 053 public SkipDateTimeField(Chronology chronology, DateTimeField field) { 054 this(chronology, field, 0); 055 } 056 057 /** 058 * Constructor. 059 * 060 * @param chronology the chronoogy to use 061 * @param field the field to skip zero on 062 * @param skip the value to skip 063 */ 064 public SkipDateTimeField(Chronology chronology, DateTimeField field, int skip) { 065 super(field); 066 iChronology = chronology; 067 int min = super.getMinimumValue(); 068 if (min < skip) { 069 iMinValue = min - 1; 070 } else if (min == skip) { 071 iMinValue = skip + 1; 072 } else { 073 iMinValue = min; 074 } 075 iSkip = skip; 076 } 077 078 //----------------------------------------------------------------------- 079 public int get(long millis) { 080 int value = super.get(millis); 081 if (value <= iSkip) { 082 value--; 083 } 084 return value; 085 } 086 087 public long set(long millis, int value) { 088 FieldUtils.verifyValueBounds(this, value, iMinValue, getMaximumValue()); 089 if (value <= iSkip) { 090 if (value == iSkip) { 091 throw new IllegalFieldValueException 092 (DateTimeFieldType.year(), Integer.valueOf(value), null, null); 093 } 094 value++; 095 } 096 return super.set(millis, value); 097 } 098 099 public int getMinimumValue() { 100 return iMinValue; 101 } 102 103 private Object readResolve() { 104 return getType().getField(iChronology); 105 } 106 107 }