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(), new Integer(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 }