1 | /* |
2 | * Copyright 2001-2005 Stephen Colebourne |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | */ |
16 | package org.joda.time.field; |
17 | |
18 | import org.joda.time.DateTimeField; |
19 | import org.joda.time.DateTimeFieldType; |
20 | import org.joda.time.DurationField; |
21 | |
22 | /** |
23 | * Generic offset adjusting datetime field. |
24 | * <p> |
25 | * OffsetDateTimeField is thread-safe and immutable. |
26 | * |
27 | * @author Brian S O'Neill |
28 | * @since 1.0 |
29 | */ |
30 | public class OffsetDateTimeField extends DecoratedDateTimeField { |
31 | private static final long serialVersionUID = 3145790132623583142L; |
32 | |
33 | private final int iOffset; |
34 | |
35 | private final int iMin; |
36 | private final int iMax; |
37 | |
38 | /** |
39 | * Constructor. |
40 | * |
41 | * @param field the field to wrap, like "year()". |
42 | * @param offset offset to add to field values |
43 | * @throws IllegalArgumentException if offset is zero |
44 | */ |
45 | public OffsetDateTimeField(DateTimeField field, int offset) { |
46 | this(field, (field == null ? null : field.getType()), offset, Integer.MIN_VALUE, Integer.MAX_VALUE); |
47 | } |
48 | |
49 | /** |
50 | * Constructor. |
51 | * |
52 | * @param field the field to wrap, like "year()". |
53 | * @param type the field type this field actually uses |
54 | * @param offset offset to add to field values |
55 | * @throws IllegalArgumentException if offset is zero |
56 | */ |
57 | public OffsetDateTimeField(DateTimeField field, DateTimeFieldType type, int offset) { |
58 | this(field, type, offset, Integer.MIN_VALUE, Integer.MAX_VALUE); |
59 | } |
60 | |
61 | /** |
62 | * Constructor. |
63 | * |
64 | * @param field the field to wrap, like "year()". |
65 | * @param type the field type this field actually uses |
66 | * @param offset offset to add to field values |
67 | * @param minValue minimum allowed value |
68 | * @param maxValue maximum allowed value |
69 | * @throws IllegalArgumentException if offset is zero |
70 | */ |
71 | public OffsetDateTimeField(DateTimeField field, DateTimeFieldType type, int offset, |
72 | int minValue, int maxValue) { |
73 | super(field, type); |
74 | |
75 | if (offset == 0) { |
76 | throw new IllegalArgumentException("The offset cannot be zero"); |
77 | } |
78 | |
79 | iOffset = offset; |
80 | |
81 | if (minValue < (field.getMinimumValue() + offset)) { |
82 | iMin = field.getMinimumValue() + offset; |
83 | } else { |
84 | iMin = minValue; |
85 | } |
86 | if (maxValue > (field.getMaximumValue() + offset)) { |
87 | iMax = field.getMaximumValue() + offset; |
88 | } else { |
89 | iMax = maxValue; |
90 | } |
91 | } |
92 | |
93 | /** |
94 | * Get the amount of offset units from the specified time instant. |
95 | * |
96 | * @param instant the time instant in millis to query. |
97 | * @return the amount of units extracted from the input. |
98 | */ |
99 | public int get(long instant) { |
100 | return super.get(instant) + iOffset; |
101 | } |
102 | |
103 | /** |
104 | * Add the specified amount of offset units to the specified time |
105 | * instant. The amount added may be negative. |
106 | * |
107 | * @param instant the time instant in millis to update. |
108 | * @param amount the amount of units to add (can be negative). |
109 | * @return the updated time instant. |
110 | */ |
111 | public long add(long instant, int amount) { |
112 | instant = super.add(instant, amount); |
113 | FieldUtils.verifyValueBounds(this, get(instant), iMin, iMax); |
114 | return instant; |
115 | } |
116 | |
117 | /** |
118 | * Add the specified amount of offset units to the specified time |
119 | * instant. The amount added may be negative. |
120 | * |
121 | * @param instant the time instant in millis to update. |
122 | * @param amount the amount of units to add (can be negative). |
123 | * @return the updated time instant. |
124 | */ |
125 | public long add(long instant, long amount) { |
126 | instant = super.add(instant, amount); |
127 | FieldUtils.verifyValueBounds(this, get(instant), iMin, iMax); |
128 | return instant; |
129 | } |
130 | |
131 | /** |
132 | * Add to the offset component of the specified time instant, |
133 | * wrapping around within that component if necessary. |
134 | * |
135 | * @param instant the time instant in millis to update. |
136 | * @param amount the amount of units to add (can be negative). |
137 | * @return the updated time instant. |
138 | */ |
139 | public long addWrapField(long instant, int amount) { |
140 | return set(instant, FieldUtils.getWrappedValue(get(instant), amount, iMin, iMax)); |
141 | } |
142 | |
143 | /** |
144 | * Set the specified amount of offset units to the specified time instant. |
145 | * |
146 | * @param instant the time instant in millis to update. |
147 | * @param value value of units to set. |
148 | * @return the updated time instant. |
149 | * @throws IllegalArgumentException if value is too large or too small. |
150 | */ |
151 | public long set(long instant, int value) { |
152 | FieldUtils.verifyValueBounds(this, value, iMin, iMax); |
153 | return super.set(instant, value - iOffset); |
154 | } |
155 | |
156 | public boolean isLeap(long instant) { |
157 | return getWrappedField().isLeap(instant); |
158 | } |
159 | |
160 | public int getLeapAmount(long instant) { |
161 | return getWrappedField().getLeapAmount(instant); |
162 | } |
163 | |
164 | public DurationField getLeapDurationField() { |
165 | return getWrappedField().getLeapDurationField(); |
166 | } |
167 | |
168 | /** |
169 | * Get the minimum value for the field. |
170 | * |
171 | * @return the minimum value |
172 | */ |
173 | public int getMinimumValue() { |
174 | return iMin; |
175 | } |
176 | |
177 | /** |
178 | * Get the maximum value for the field. |
179 | * |
180 | * @return the maximum value |
181 | */ |
182 | public int getMaximumValue() { |
183 | return iMax; |
184 | } |
185 | |
186 | public long roundFloor(long instant) { |
187 | return getWrappedField().roundFloor(instant); |
188 | } |
189 | |
190 | public long roundCeiling(long instant) { |
191 | return getWrappedField().roundCeiling(instant); |
192 | } |
193 | |
194 | public long roundHalfFloor(long instant) { |
195 | return getWrappedField().roundHalfFloor(instant); |
196 | } |
197 | |
198 | public long roundHalfCeiling(long instant) { |
199 | return getWrappedField().roundHalfCeiling(instant); |
200 | } |
201 | |
202 | public long roundHalfEven(long instant) { |
203 | return getWrappedField().roundHalfEven(instant); |
204 | } |
205 | |
206 | public long remainder(long instant) { |
207 | return getWrappedField().remainder(instant); |
208 | } |
209 | |
210 | /** |
211 | * Returns the offset added to the field values. |
212 | * |
213 | * @return the offset |
214 | */ |
215 | public int getOffset() { |
216 | return iOffset; |
217 | } |
218 | } |