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.DateTimeField;
019: import org.joda.time.DateTimeFieldType;
020: import org.joda.time.DurationField;
021:
022: /**
023: * Generic offset adjusting datetime field.
024: * <p>
025: * OffsetDateTimeField is thread-safe and immutable.
026: *
027: * @author Brian S O'Neill
028: * @since 1.0
029: */
030: public class OffsetDateTimeField extends DecoratedDateTimeField {
031: private static final long serialVersionUID = 3145790132623583142L;
032:
033: private final int iOffset;
034:
035: private final int iMin;
036: private final int iMax;
037:
038: /**
039: * Constructor.
040: *
041: * @param field the field to wrap, like "year()".
042: * @param offset offset to add to field values
043: * @throws IllegalArgumentException if offset is zero
044: */
045: public OffsetDateTimeField(DateTimeField field, int offset) {
046: this (field, (field == null ? null : field.getType()), offset,
047: Integer.MIN_VALUE, Integer.MAX_VALUE);
048: }
049:
050: /**
051: * Constructor.
052: *
053: * @param field the field to wrap, like "year()".
054: * @param type the field type this field actually uses
055: * @param offset offset to add to field values
056: * @throws IllegalArgumentException if offset is zero
057: */
058: public OffsetDateTimeField(DateTimeField field,
059: DateTimeFieldType type, int offset) {
060: this (field, type, offset, Integer.MIN_VALUE, Integer.MAX_VALUE);
061: }
062:
063: /**
064: * Constructor.
065: *
066: * @param field the field to wrap, like "year()".
067: * @param type the field type this field actually uses
068: * @param offset offset to add to field values
069: * @param minValue minimum allowed value
070: * @param maxValue maximum allowed value
071: * @throws IllegalArgumentException if offset is zero
072: */
073: public OffsetDateTimeField(DateTimeField field,
074: DateTimeFieldType type, int offset, int minValue,
075: int maxValue) {
076: super (field, type);
077:
078: if (offset == 0) {
079: throw new IllegalArgumentException(
080: "The offset cannot be zero");
081: }
082:
083: iOffset = offset;
084:
085: if (minValue < (field.getMinimumValue() + offset)) {
086: iMin = field.getMinimumValue() + offset;
087: } else {
088: iMin = minValue;
089: }
090: if (maxValue > (field.getMaximumValue() + offset)) {
091: iMax = field.getMaximumValue() + offset;
092: } else {
093: iMax = maxValue;
094: }
095: }
096:
097: /**
098: * Get the amount of offset units from the specified time instant.
099: *
100: * @param instant the time instant in millis to query.
101: * @return the amount of units extracted from the input.
102: */
103: public int get(long instant) {
104: return super .get(instant) + iOffset;
105: }
106:
107: /**
108: * Add the specified amount of offset units to the specified time
109: * instant. The amount added may be negative.
110: *
111: * @param instant the time instant in millis to update.
112: * @param amount the amount of units to add (can be negative).
113: * @return the updated time instant.
114: */
115: public long add(long instant, int amount) {
116: instant = super .add(instant, amount);
117: FieldUtils.verifyValueBounds(this , get(instant), iMin, iMax);
118: return instant;
119: }
120:
121: /**
122: * Add the specified amount of offset units to the specified time
123: * instant. The amount added may be negative.
124: *
125: * @param instant the time instant in millis to update.
126: * @param amount the amount of units to add (can be negative).
127: * @return the updated time instant.
128: */
129: public long add(long instant, long amount) {
130: instant = super .add(instant, amount);
131: FieldUtils.verifyValueBounds(this , get(instant), iMin, iMax);
132: return instant;
133: }
134:
135: /**
136: * Add to the offset component of the specified time instant,
137: * wrapping around within that component if necessary.
138: *
139: * @param instant the time instant in millis to update.
140: * @param amount the amount of units to add (can be negative).
141: * @return the updated time instant.
142: */
143: public long addWrapField(long instant, int amount) {
144: return set(instant, FieldUtils.getWrappedValue(get(instant),
145: amount, iMin, iMax));
146: }
147:
148: /**
149: * Set the specified amount of offset units to the specified time instant.
150: *
151: * @param instant the time instant in millis to update.
152: * @param value value of units to set.
153: * @return the updated time instant.
154: * @throws IllegalArgumentException if value is too large or too small.
155: */
156: public long set(long instant, int value) {
157: FieldUtils.verifyValueBounds(this , value, iMin, iMax);
158: return super .set(instant, value - iOffset);
159: }
160:
161: public boolean isLeap(long instant) {
162: return getWrappedField().isLeap(instant);
163: }
164:
165: public int getLeapAmount(long instant) {
166: return getWrappedField().getLeapAmount(instant);
167: }
168:
169: public DurationField getLeapDurationField() {
170: return getWrappedField().getLeapDurationField();
171: }
172:
173: /**
174: * Get the minimum value for the field.
175: *
176: * @return the minimum value
177: */
178: public int getMinimumValue() {
179: return iMin;
180: }
181:
182: /**
183: * Get the maximum value for the field.
184: *
185: * @return the maximum value
186: */
187: public int getMaximumValue() {
188: return iMax;
189: }
190:
191: public long roundFloor(long instant) {
192: return getWrappedField().roundFloor(instant);
193: }
194:
195: public long roundCeiling(long instant) {
196: return getWrappedField().roundCeiling(instant);
197: }
198:
199: public long roundHalfFloor(long instant) {
200: return getWrappedField().roundHalfFloor(instant);
201: }
202:
203: public long roundHalfCeiling(long instant) {
204: return getWrappedField().roundHalfCeiling(instant);
205: }
206:
207: public long roundHalfEven(long instant) {
208: return getWrappedField().roundHalfEven(instant);
209: }
210:
211: public long remainder(long instant) {
212: return getWrappedField().remainder(instant);
213: }
214:
215: /**
216: * Returns the offset added to the field values.
217: *
218: * @return the offset
219: */
220: public int getOffset() {
221: return iOffset;
222: }
223: }
|