001 /*
002 * Copyright 2001-2011 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.base;
017
018 import java.io.Serializable;
019
020 import org.joda.time.Chronology;
021 import org.joda.time.DateTimeUtils;
022 import org.joda.time.Interval;
023 import org.joda.time.Period;
024 import org.joda.time.PeriodType;
025 import org.joda.time.ReadableDuration;
026 import org.joda.time.ReadableInstant;
027 import org.joda.time.convert.ConverterManager;
028 import org.joda.time.convert.DurationConverter;
029 import org.joda.time.field.FieldUtils;
030
031 /**
032 * BaseDuration is an abstract implementation of ReadableDuration that stores
033 * data in a <code>long</code> duration milliseconds field.
034 * <p>
035 * This class should generally not be used directly by API users.
036 * The {@link ReadableDuration} interface should be used when different
037 * kinds of duration objects are to be referenced.
038 * <p>
039 * BaseDuration subclasses may be mutable and not thread-safe.
040 *
041 * @author Brian S O'Neill
042 * @author Stephen Colebourne
043 * @since 1.0
044 */
045 public abstract class BaseDuration
046 extends AbstractDuration
047 implements ReadableDuration, Serializable {
048
049 /** Serialization version */
050 private static final long serialVersionUID = 2581698638990L;
051
052 /** The duration length */
053 private volatile long iMillis;
054
055 /**
056 * Creates a duration from the given millisecond duration.
057 *
058 * @param duration the duration, in milliseconds
059 */
060 protected BaseDuration(long duration) {
061 super();
062 iMillis = duration;
063 }
064
065 /**
066 * Creates a duration from the given interval endpoints.
067 *
068 * @param startInstant interval start, in milliseconds
069 * @param endInstant interval end, in milliseconds
070 * @throws ArithmeticException if the duration exceeds a 64 bit long
071 */
072 protected BaseDuration(long startInstant, long endInstant) {
073 super();
074 iMillis = FieldUtils.safeAdd(endInstant, -startInstant);
075 }
076
077 /**
078 * Creates a duration from the given interval endpoints.
079 *
080 * @param start interval start, null means now
081 * @param end interval end, null means now
082 * @throws ArithmeticException if the duration exceeds a 64 bit long
083 */
084 protected BaseDuration(ReadableInstant start, ReadableInstant end) {
085 super();
086 if (start == end) {
087 iMillis = 0L;
088 } else {
089 long startMillis = DateTimeUtils.getInstantMillis(start);
090 long endMillis = DateTimeUtils.getInstantMillis(end);
091 iMillis = FieldUtils.safeAdd(endMillis, -startMillis);
092 }
093 }
094
095 /**
096 * Creates a duration from the specified object using the
097 * {@link org.joda.time.convert.ConverterManager ConverterManager}.
098 *
099 * @param duration duration to convert
100 * @throws IllegalArgumentException if duration is invalid
101 */
102 protected BaseDuration(Object duration) {
103 super();
104 DurationConverter converter = ConverterManager.getInstance().getDurationConverter(duration);
105 iMillis = converter.getDurationMillis(duration);
106 }
107
108 //-----------------------------------------------------------------------
109 /**
110 * Gets the length of this duration in milliseconds.
111 *
112 * @return the length of the duration in milliseconds.
113 */
114 public long getMillis() {
115 return iMillis;
116 }
117
118 //-----------------------------------------------------------------------
119 /**
120 * Sets the length of this duration in milliseconds.
121 *
122 * @param duration the new length of the duration
123 */
124 protected void setMillis(long duration) {
125 iMillis = duration;
126 }
127
128 //-----------------------------------------------------------------------
129 /**
130 * Converts this duration to a Period instance using the specified period type
131 * and the ISO chronology.
132 * <p>
133 * Only precise fields in the period type will be used.
134 * At most these are hours, minutes, seconds and millis - the period
135 * type may restrict the selection further.
136 * <p>
137 * For more control over the conversion process, you must pair the duration with
138 * an instant, see {@link #toPeriodFrom(ReadableInstant, PeriodType)}.
139 *
140 * @param type the period type to use, null means standard
141 * @return a Period created using the millisecond duration from this instance
142 */
143 public Period toPeriod(PeriodType type) {
144 return new Period(getMillis(), type);
145 }
146
147 /**
148 * Converts this duration to a Period instance using the standard period type
149 * and the specified chronology.
150 * <p>
151 * Only precise fields in the period type will be used.
152 * Exactly which fields are precise depends on the chronology.
153 * Only the time fields are precise for ISO chronology with a time zone.
154 * However, ISO UTC also has precise days and weeks.
155 * <p>
156 * For more control over the conversion process, you must pair the duration with
157 * an instant, see {@link #toPeriodFrom(ReadableInstant)} and
158 * {@link #toPeriodTo(ReadableInstant)}
159 *
160 * @param chrono the chronology to use, null means ISO default
161 * @return a Period created using the millisecond duration from this instance
162 */
163 public Period toPeriod(Chronology chrono) {
164 return new Period(getMillis(), chrono);
165 }
166
167 /**
168 * Converts this duration to a Period instance using the specified period type
169 * and chronology.
170 * <p>
171 * Only precise fields in the period type will be used.
172 * Exactly which fields are precise depends on the chronology.
173 * Only the time fields are precise for ISO chronology with a time zone.
174 * However, ISO UTC also has precise days and weeks.
175 * <p>
176 * For more control over the conversion process, you must pair the duration with
177 * an instant, see {@link #toPeriodFrom(ReadableInstant, PeriodType)} and
178 * {@link #toPeriodTo(ReadableInstant, PeriodType)}
179 *
180 * @param type the period type to use, null means standard
181 * @param chrono the chronology to use, null means ISO default
182 * @return a Period created using the millisecond duration from this instance
183 */
184 public Period toPeriod(PeriodType type, Chronology chrono) {
185 return new Period(getMillis(), type, chrono);
186 }
187
188 /**
189 * Converts this duration to a Period instance by adding the duration to a start
190 * instant to obtain an interval using the standard period type.
191 * <p>
192 * This conversion will determine the fields of a period accurately.
193 * The results are based on the instant millis, the chronology of the instant,
194 * the standard period type and the length of this duration.
195 *
196 * @param startInstant the instant to calculate the period from, null means now
197 * @return a Period created using the millisecond duration from this instance
198 */
199 public Period toPeriodFrom(ReadableInstant startInstant) {
200 return new Period(startInstant, this);
201 }
202
203 /**
204 * Converts this duration to a Period instance by adding the duration to a start
205 * instant to obtain an interval.
206 * <p>
207 * This conversion will determine the fields of a period accurately.
208 * The results are based on the instant millis, the chronology of the instant,
209 * the period type and the length of this duration.
210 *
211 * @param startInstant the instant to calculate the period from, null means now
212 * @param type the period type determining how to split the duration into fields, null means All type
213 * @return a Period created using the millisecond duration from this instance
214 */
215 public Period toPeriodFrom(ReadableInstant startInstant, PeriodType type) {
216 return new Period(startInstant, this, type);
217 }
218
219 /**
220 * Converts this duration to a Period instance by subtracting the duration
221 * from an end instant to obtain an interval using the standard period
222 * type.
223 * <p>
224 * This conversion will determine the fields of a period accurately.
225 * The results are based on the instant millis, the chronology of the instant,
226 * the standard period type and the length of this duration.
227 *
228 * @param endInstant the instant to calculate the period to, null means now
229 * @return a Period created using the millisecond duration from this instance
230 */
231 public Period toPeriodTo(ReadableInstant endInstant) {
232 return new Period(this, endInstant);
233 }
234
235 /**
236 * Converts this duration to a Period instance by subtracting the duration
237 * from an end instant to obtain an interval using the standard period
238 * type.
239 * <p>
240 * This conversion will determine the fields of a period accurately.
241 * The results are based on the instant millis, the chronology of the instant,
242 * the period type and the length of this duration.
243 *
244 * @param endInstant the instant to calculate the period to, null means now
245 * @param type the period type determining how to split the duration into fields, null means All type
246 * @return a Period created using the millisecond duration from this instance
247 */
248 public Period toPeriodTo(ReadableInstant endInstant, PeriodType type) {
249 return new Period(this, endInstant, type);
250 }
251
252 /**
253 * Converts this duration to an Interval starting at the specified instant.
254 *
255 * @param startInstant the instant to start the interval at, null means now
256 * @return an Interval starting at the specified instant
257 */
258 public Interval toIntervalFrom(ReadableInstant startInstant) {
259 return new Interval(startInstant, this);
260 }
261
262 /**
263 * Converts this duration to an Interval ending at the specified instant.
264 *
265 * @param endInstant the instant to end the interval at, null means now
266 * @return an Interval ending at the specified instant
267 */
268 public Interval toIntervalTo(ReadableInstant endInstant) {
269 return new Interval(this, endInstant);
270 }
271
272 }